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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/README.md +4 -7
  2. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  3. package/dist/lib/components/collection/collection-view.component.js +1 -0
  4. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  5. package/dist/lib/components/composer/ai-composer.component.d.ts +14 -2
  6. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
  7. package/dist/lib/components/composer/ai-composer.component.js +35 -4
  8. package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
  9. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +632 -55
  10. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  11. package/dist/lib/components/conversation/conversation-chat-area.component.js +2748 -624
  12. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  13. package/dist/lib/components/conversation/forks-popover.component.d.ts +37 -0
  14. package/dist/lib/components/conversation/forks-popover.component.d.ts.map +1 -0
  15. package/dist/lib/components/conversation/forks-popover.component.js +164 -0
  16. package/dist/lib/components/conversation/forks-popover.component.js.map +1 -0
  17. package/dist/lib/components/export/export-modal.component.d.ts +7 -2
  18. package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
  19. package/dist/lib/components/export/export-modal.component.js +16 -3
  20. package/dist/lib/components/export/export-modal.component.js.map +1 -1
  21. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  22. package/dist/lib/components/message/conversation-message-rating.component.js +11 -9
  23. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  24. package/dist/lib/components/message/message-input.component.d.ts +121 -11
  25. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  26. package/dist/lib/components/message/message-input.component.js +307 -106
  27. package/dist/lib/components/message/message-input.component.js.map +1 -1
  28. package/dist/lib/components/message/message-item.component.d.ts +178 -5
  29. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  30. package/dist/lib/components/message/message-item.component.js +919 -306
  31. package/dist/lib/components/message/message-item.component.js.map +1 -1
  32. package/dist/lib/components/message/message-list.component.d.ts +92 -21
  33. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  34. package/dist/lib/components/message/message-list.component.js +337 -52
  35. package/dist/lib/components/message/message-list.component.js.map +1 -1
  36. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts +34 -0
  37. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts.map +1 -0
  38. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js +75 -0
  39. package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js.map +1 -0
  40. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts +80 -0
  41. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts.map +1 -0
  42. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js +202 -0
  43. package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js.map +1 -0
  44. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts +45 -0
  45. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts.map +1 -0
  46. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js +123 -0
  47. package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js.map +1 -0
  48. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts +90 -0
  49. package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts.map +1 -0
  50. package/dist/lib/components/realtime/capture/realtime-capture-channel.js +223 -0
  51. package/dist/lib/components/realtime/capture/realtime-capture-channel.js.map +1 -0
  52. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts +98 -0
  53. package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts.map +1 -0
  54. package/dist/lib/components/realtime/capture/realtime-capture-model.js +161 -0
  55. package/dist/lib/components/realtime/capture/realtime-capture-model.js.map +1 -0
  56. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts +48 -0
  57. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts.map +1 -0
  58. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js +205 -0
  59. package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js.map +1 -0
  60. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +19 -2
  61. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
  62. package/dist/lib/components/realtime/channels/client-context-channel.js +83 -9
  63. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
  64. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +30 -9
  65. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
  66. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +78 -14
  67. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
  68. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts +71 -0
  69. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts.map +1 -0
  70. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js +259 -0
  71. package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js.map +1 -0
  72. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts +129 -0
  73. package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts.map +1 -0
  74. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js +373 -0
  75. package/dist/lib/components/realtime/identity-verification/identity-verification-model.js.map +1 -0
  76. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts +77 -0
  77. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts.map +1 -0
  78. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js +420 -0
  79. package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js.map +1 -0
  80. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts +83 -0
  81. package/dist/lib/components/realtime/interactive-component/component-contract.d.ts.map +1 -0
  82. package/dist/lib/components/realtime/interactive-component/component-contract.js +292 -0
  83. package/dist/lib/components/realtime/interactive-component/component-contract.js.map +1 -0
  84. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts +39 -0
  85. package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts.map +1 -0
  86. package/dist/lib/components/realtime/interactive-component/component-data-state.js +152 -0
  87. package/dist/lib/components/realtime/interactive-component/component-data-state.js.map +1 -0
  88. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts +109 -0
  89. package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts.map +1 -0
  90. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js +146 -0
  91. package/dist/lib/components/realtime/interactive-component/component-instance-engine.js.map +1 -0
  92. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts +19 -0
  93. package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts.map +1 -0
  94. package/dist/lib/components/realtime/interactive-component/component-spec-content.js +39 -0
  95. package/dist/lib/components/realtime/interactive-component/component-spec-content.js.map +1 -0
  96. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts +183 -0
  97. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts.map +1 -0
  98. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js +761 -0
  99. package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js.map +1 -0
  100. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts +25 -0
  101. package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts.map +1 -0
  102. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js +57 -0
  103. package/dist/lib/components/realtime/interactive-component/interactive-component-config.js.map +1 -0
  104. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts +40 -0
  105. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts.map +1 -0
  106. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js +97 -0
  107. package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js.map +1 -0
  108. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts +144 -0
  109. package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts.map +1 -0
  110. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js +57 -0
  111. package/dist/lib/components/realtime/interactive-component/interactive-component-types.js.map +1 -0
  112. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts +36 -0
  113. package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts.map +1 -0
  114. package/dist/lib/components/realtime/interactive-component/react-component-handle.js +55 -0
  115. package/dist/lib/components/realtime/interactive-component/react-component-handle.js.map +1 -0
  116. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts +55 -0
  117. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts.map +1 -0
  118. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js +210 -0
  119. package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js.map +1 -0
  120. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts +32 -0
  121. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts.map +1 -0
  122. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js +90 -0
  123. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js.map +1 -0
  124. package/dist/lib/components/realtime/media/media-channel.d.ts +7 -0
  125. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
  126. package/dist/lib/components/realtime/media/media-channel.js +28 -1
  127. package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
  128. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +8 -1
  129. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  130. package/dist/lib/components/realtime/realtime-agent-banner.component.js +89 -71
  131. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  132. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts +21 -0
  133. package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts.map +1 -0
  134. package/dist/lib/components/realtime/realtime-agent-orb.component.js +49 -0
  135. package/dist/lib/components/realtime/realtime-agent-orb.component.js.map +1 -0
  136. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +44 -11
  137. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  138. package/dist/lib/components/realtime/realtime-agent-picker.component.js +162 -50
  139. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  140. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +8 -2
  141. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  142. package/dist/lib/components/realtime/realtime-audio-visuals.js +14 -18
  143. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  144. package/dist/lib/components/realtime/realtime-composer.component.d.ts +42 -2
  145. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  146. package/dist/lib/components/realtime/realtime-composer.component.js +137 -102
  147. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  148. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts +71 -0
  149. package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts.map +1 -0
  150. package/dist/lib/components/realtime/realtime-perception-chip.component.js +221 -0
  151. package/dist/lib/components/realtime/realtime-perception-chip.component.js.map +1 -0
  152. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +264 -22
  153. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  154. package/dist/lib/components/realtime/realtime-session-overlay.component.js +851 -135
  155. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  156. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts +14 -0
  157. package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts.map +1 -0
  158. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js +14 -0
  159. package/dist/lib/components/realtime/realtime-surface-placement-prefs.js.map +1 -0
  160. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts +74 -0
  161. package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts.map +1 -0
  162. package/dist/lib/components/realtime/realtime-surface-stage.model.js +171 -0
  163. package/dist/lib/components/realtime/realtime-surface-stage.model.js.map +1 -0
  164. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +71 -13
  165. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  166. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +232 -73
  167. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  168. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +5 -0
  169. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  170. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +8 -0
  171. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  172. package/dist/lib/components/realtime/realtime-ui-config.d.ts +12 -2
  173. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
  174. package/dist/lib/components/realtime/realtime-ui-config.js +5 -1
  175. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
  176. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +10 -1
  177. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  178. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +42 -2
  179. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  180. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +20 -3
  181. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -1
  182. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +44 -10
  183. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -1
  184. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +28 -44
  185. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
  186. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +76 -162
  187. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
  188. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  189. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  190. package/dist/lib/components/search/search-panel.component.js +25 -12
  191. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  192. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +22 -31
  193. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  194. package/dist/lib/components/workspace/conversation-workspace.component.js +50 -63
  195. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  196. package/dist/lib/conversations.module.d.ts +30 -29
  197. package/dist/lib/conversations.module.d.ts.map +1 -1
  198. package/dist/lib/conversations.module.js +27 -5
  199. package/dist/lib/conversations.module.js.map +1 -1
  200. package/dist/lib/events/chat-events.d.ts +25 -0
  201. package/dist/lib/events/chat-events.d.ts.map +1 -1
  202. package/dist/lib/events/chat-events.js +36 -0
  203. package/dist/lib/events/chat-events.js.map +1 -1
  204. package/dist/lib/models/agent-turn.model.d.ts +5 -0
  205. package/dist/lib/models/agent-turn.model.d.ts.map +1 -1
  206. package/dist/lib/models/agent-turn.model.js.map +1 -1
  207. package/dist/lib/services/agent-state.service.d.ts +34 -8
  208. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  209. package/dist/lib/services/agent-state.service.js +82 -29
  210. package/dist/lib/services/agent-state.service.js.map +1 -1
  211. package/dist/lib/services/artifact-state.service.d.ts +0 -9
  212. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  213. package/dist/lib/services/artifact-state.service.js +1 -32
  214. package/dist/lib/services/artifact-state.service.js.map +1 -1
  215. package/dist/lib/services/browser-realtime-media-host.d.ts +12 -0
  216. package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -1
  217. package/dist/lib/services/browser-realtime-media-host.js +19 -0
  218. package/dist/lib/services/browser-realtime-media-host.js.map +1 -1
  219. package/dist/lib/services/browser-recording-unload-guard.d.ts +30 -0
  220. package/dist/lib/services/browser-recording-unload-guard.d.ts.map +1 -0
  221. package/dist/lib/services/browser-recording-unload-guard.js +43 -0
  222. package/dist/lib/services/browser-recording-unload-guard.js.map +1 -0
  223. package/dist/lib/services/conversation-agent.service.d.ts +35 -11
  224. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  225. package/dist/lib/services/conversation-agent.service.js +65 -20
  226. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  227. package/dist/lib/services/conversation-detail-window.store.d.ts +22 -4
  228. package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
  229. package/dist/lib/services/conversation-detail-window.store.js +50 -9
  230. package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
  231. package/dist/lib/services/conversation-naming.d.ts +72 -22
  232. package/dist/lib/services/conversation-naming.d.ts.map +1 -1
  233. package/dist/lib/services/conversation-naming.js +84 -10
  234. package/dist/lib/services/conversation-naming.js.map +1 -1
  235. package/dist/lib/services/data-cache.service.d.ts +13 -5
  236. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  237. package/dist/lib/services/data-cache.service.js +39 -19
  238. package/dist/lib/services/data-cache.service.js.map +1 -1
  239. package/dist/lib/services/export.service.d.ts +26 -9
  240. package/dist/lib/services/export.service.d.ts.map +1 -1
  241. package/dist/lib/services/export.service.js +61 -18
  242. package/dist/lib/services/export.service.js.map +1 -1
  243. package/dist/lib/services/realtime-audio-recorder.d.ts +33 -5
  244. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -1
  245. package/dist/lib/services/realtime-audio-recorder.js +71 -11
  246. package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
  247. package/dist/lib/services/realtime-pairing.d.ts +10 -5
  248. package/dist/lib/services/realtime-pairing.d.ts.map +1 -1
  249. package/dist/lib/services/realtime-pairing.js +15 -6
  250. package/dist/lib/services/realtime-pairing.js.map +1 -1
  251. package/dist/lib/services/realtime-session.service.d.ts +3 -2
  252. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  253. package/dist/lib/services/realtime-session.service.js +7 -2
  254. package/dist/lib/services/realtime-session.service.js.map +1 -1
  255. package/dist/lib/services/search.service.d.ts +7 -2
  256. package/dist/lib/services/search.service.d.ts.map +1 -1
  257. package/dist/lib/services/search.service.js +13 -4
  258. package/dist/lib/services/search.service.js.map +1 -1
  259. package/dist/lib/util/frame-zone.d.ts +10 -0
  260. package/dist/lib/util/frame-zone.d.ts.map +1 -0
  261. package/dist/lib/util/frame-zone.js +10 -0
  262. package/dist/lib/util/frame-zone.js.map +1 -0
  263. package/dist/lib/utils/conversation-branching.d.ts +4 -0
  264. package/dist/lib/utils/conversation-branching.d.ts.map +1 -0
  265. package/dist/lib/utils/conversation-branching.js +5 -0
  266. package/dist/lib/utils/conversation-branching.js.map +1 -0
  267. package/dist/lib/utils/conversation-forks.d.ts +315 -0
  268. package/dist/lib/utils/conversation-forks.d.ts.map +1 -0
  269. package/dist/lib/utils/conversation-forks.js +456 -0
  270. package/dist/lib/utils/conversation-forks.js.map +1 -0
  271. package/dist/public-api.d.ts +23 -1
  272. package/dist/public-api.d.ts.map +1 -1
  273. package/dist/public-api.js +30 -1
  274. package/dist/public-api.js.map +1 -1
  275. package/package.json +37 -32
  276. package/dist/lib/components/thread/thread-panel.component.d.ts +0 -126
  277. package/dist/lib/components/thread/thread-panel.component.d.ts.map +0 -1
  278. package/dist/lib/components/thread/thread-panel.component.js +0 -440
  279. package/dist/lib/components/thread/thread-panel.component.js.map +0 -1
@@ -7,6 +7,7 @@ import { SelectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';
7
7
  import { BuildConversationTimeline } from '../../utils/realtime-session-timeline';
8
8
  import { DEFAULT_TRANSCRIPT_PAGE_SIZE } from '../../utils/conversation-detail-window';
9
9
  import { ResolveDateJumpTarget } from '../../utils/date-jump';
10
+ import { EMPTY_FORK_CHIPS } from '../../utils/conversation-forks';
10
11
  import * as i0 from "@angular/core";
11
12
  import * as i1 from "@memberjunction/ng-ui-components";
12
13
  import * as i2 from "@memberjunction/ng-shared-generic";
@@ -16,29 +17,29 @@ const _c2 = ["olderSentinel"];
16
17
  const _c3 = ["spacerTemplate"];
17
18
  function MessageListComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
18
19
  const _r1 = i0.ɵɵgetCurrentView();
19
- i0.ɵɵelementStart(0, "div", 5)(1, "div", 8)(2, "button", 9);
20
+ i0.ɵɵelementStart(0, "div", 5)(1, "div", 7)(2, "button", 8);
20
21
  i0.ɵɵlistener("click", function MessageListComponent_Conditional_2_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleDateNav()); });
21
22
  i0.ɵɵelementStart(3, "span");
22
23
  i0.ɵɵtext(4);
23
24
  i0.ɵɵelementEnd();
24
- i0.ɵɵelement(5, "i", 10);
25
+ i0.ɵɵelement(5, "i", 9);
25
26
  i0.ɵɵelementEnd();
26
- i0.ɵɵelementStart(6, "div", 11)(7, "div", 12);
27
+ i0.ɵɵelementStart(6, "div", 10)(7, "div", 11);
27
28
  i0.ɵɵtext(8, "Jump to...");
28
29
  i0.ɵɵelementEnd();
29
- i0.ɵɵelementStart(9, "div", 13);
30
+ i0.ɵɵelementStart(9, "div", 12);
30
31
  i0.ɵɵlistener("click", function MessageListComponent_Conditional_2_Template_div_click_9_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.jumpToDate("today")); });
31
32
  i0.ɵɵtext(10, "Today");
32
33
  i0.ɵɵelementEnd();
33
- i0.ɵɵelementStart(11, "div", 13);
34
+ i0.ɵɵelementStart(11, "div", 12);
34
35
  i0.ɵɵlistener("click", function MessageListComponent_Conditional_2_Template_div_click_11_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.jumpToDate("yesterday")); });
35
36
  i0.ɵɵtext(12, "Yesterday");
36
37
  i0.ɵɵelementEnd();
37
- i0.ɵɵelementStart(13, "div", 13);
38
+ i0.ɵɵelementStart(13, "div", 12);
38
39
  i0.ɵɵlistener("click", function MessageListComponent_Conditional_2_Template_div_click_13_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.jumpToDate("last-week")); });
39
40
  i0.ɵɵtext(14, "Last week");
40
41
  i0.ɵɵelementEnd();
41
- i0.ɵɵelementStart(15, "div", 13);
42
+ i0.ɵɵelementStart(15, "div", 12);
42
43
  i0.ɵɵlistener("click", function MessageListComponent_Conditional_2_Template_div_click_15_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.jumpToDate("last-month")); });
43
44
  i0.ɵɵtext(16, "Last month");
44
45
  i0.ɵɵelementEnd()()()();
@@ -50,16 +51,16 @@ function MessageListComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
50
51
  i0.ɵɵclassProp("show", ctx_r1.showDateNav);
51
52
  } }
52
53
  function MessageListComponent_Conditional_3_Conditional_2_Template(rf, ctx) { if (rf & 1) {
53
- i0.ɵɵelement(0, "mj-loading", 14);
54
+ i0.ɵɵelement(0, "mj-loading", 13);
54
55
  } }
55
56
  function MessageListComponent_Conditional_3_Conditional_3_Template(rf, ctx) { if (rf & 1) {
56
- i0.ɵɵelementStart(0, "span", 15);
57
+ i0.ɵɵelementStart(0, "span", 14);
57
58
  i0.ɵɵtext(1, "Earlier messages");
58
59
  i0.ɵɵelementEnd();
59
60
  } }
60
61
  function MessageListComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
61
62
  i0.ɵɵelementStart(0, "div", 6, 3);
62
- i0.ɵɵconditionalCreate(2, MessageListComponent_Conditional_3_Conditional_2_Template, 1, 0, "mj-loading", 14)(3, MessageListComponent_Conditional_3_Conditional_3_Template, 2, 0, "span", 15);
63
+ i0.ɵɵconditionalCreate(2, MessageListComponent_Conditional_3_Conditional_2_Template, 1, 0, "mj-loading", 13)(3, MessageListComponent_Conditional_3_Conditional_3_Template, 2, 0, "span", 14);
63
64
  i0.ɵɵelementEnd();
64
65
  } if (rf & 2) {
65
66
  const ctx_r1 = i0.ɵɵnextContext();
@@ -67,13 +68,32 @@ function MessageListComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
67
68
  i0.ɵɵconditional(ctx_r1.IsLoadingOlder ? 2 : 3);
68
69
  } }
69
70
  function MessageListComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) {
70
- i0.ɵɵelement(0, "div", 16);
71
+ i0.ɵɵelement(0, "div", 15);
71
72
  } if (rf & 2) {
72
73
  const height_r3 = ctx.height;
73
74
  i0.ɵɵstyleProp("height", height_r3, "px");
74
75
  } }
76
+ function MessageListComponent_Conditional_8_Conditional_0_Template(rf, ctx) { if (rf & 1) {
77
+ i0.ɵɵelementStart(0, "div", 16);
78
+ i0.ɵɵelement(1, "i", 18);
79
+ i0.ɵɵelementStart(2, "span", 19);
80
+ i0.ɵɵtext(3);
81
+ i0.ɵɵelementEnd();
82
+ i0.ɵɵelement(4, "span", 20);
83
+ i0.ɵɵelementEnd();
84
+ } if (rf & 2) {
85
+ const ctx_r1 = i0.ɵɵnextContext(2);
86
+ i0.ɵɵadvance(3);
87
+ i0.ɵɵtextInterpolate(ctx_r1.EmptyViewMarkerText);
88
+ } }
89
+ function MessageListComponent_Conditional_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
90
+ i0.ɵɵelement(0, "mj-empty-state", 17);
91
+ } }
75
92
  function MessageListComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
76
- i0.ɵɵelement(0, "mj-empty-state", 7);
93
+ i0.ɵɵconditionalCreate(0, MessageListComponent_Conditional_8_Conditional_0_Template, 5, 1, "div", 16)(1, MessageListComponent_Conditional_8_Conditional_1_Template, 1, 0, "mj-empty-state", 17);
94
+ } if (rf & 2) {
95
+ const ctx_r1 = i0.ɵɵnextContext();
96
+ i0.ɵɵconditional(ctx_r1.EmptyViewMarkerText ? 0 : ctx_r1.showEmptyFill ? 1 : -1);
77
97
  } }
78
98
  /**
79
99
  * Container component for displaying a list of messages
@@ -104,6 +124,42 @@ export class MessageListComponent extends BaseAngularComponent {
104
124
  get conversation() {
105
125
  return this.Conversation;
106
126
  }
127
+ /** Fork chips per normalized detail id, from the chat area's fork summaries. A new map is pushed into the items on screen. */
128
+ set ForkChipMap(value) {
129
+ this._forkChipMap = value ?? new Map();
130
+ this.applyForkChips();
131
+ }
132
+ get ForkChipMap() {
133
+ return this._forkChipMap ?? new Map();
134
+ }
135
+ _forkChipMap = new Map();
136
+ /** How a fork view draws its rows; null in Main. A new layout is pushed into the items on screen. */
137
+ set ForkLayout(value) {
138
+ this._forkLayout = value ?? null;
139
+ this.applyForkLayout();
140
+ }
141
+ get ForkLayout() {
142
+ return this._forkLayout ?? null;
143
+ }
144
+ _forkLayout = null;
145
+ /** True when the person may start forks; a new value is pushed into the items on screen. False hides the fork actions. */
146
+ set CanFork(value) {
147
+ this._canFork = value !== false;
148
+ this.applyCanFork();
149
+ }
150
+ get CanFork() {
151
+ return this._canFork !== false;
152
+ }
153
+ _canFork = true;
154
+ /** The latest turn that in-place Edit and Regenerate may change; null when there is none. A new value is pushed into the items on screen. */
155
+ set InPlaceTurn(value) {
156
+ this._inPlaceTurn = value ?? null;
157
+ this.applyInPlaceRoles();
158
+ }
159
+ get InPlaceTurn() {
160
+ return this._inPlaceTurn ?? null;
161
+ }
162
+ _inPlaceTurn = null;
107
163
  CurrentUser;
108
164
  /** @deprecated Use {@link CurrentUser}. */
109
165
  set currentUser(value) {
@@ -213,6 +269,23 @@ export class MessageListComponent extends BaseAngularComponent {
213
269
  return this._readOnly;
214
270
  }
215
271
  _readOnly = false;
272
+ /** Whether message items offer Stop on an in-progress agent reply. Default true. */
273
+ AllowStopRun = true;
274
+ /**
275
+ * How many agent replies are in flight in the open view; items offer their own Stop only above
276
+ * one. Changes mid-session as runs start and finish, so it is restamped onto rendered items.
277
+ */
278
+ set InFlightCount(value) {
279
+ if (value === this._inFlightCount) {
280
+ return;
281
+ }
282
+ this._inFlightCount = value;
283
+ this.restampAssistantIdentity();
284
+ }
285
+ get InFlightCount() {
286
+ return this._inFlightCount;
287
+ }
288
+ _inFlightCount = 0;
216
289
  // ── Windowed-transcript paging state ────────────────────────────────────────
217
290
  // The list renders only the LOADED window, not the whole conversation. These two
218
291
  // describe what lies above it. Unused until the Phase 5 sentinel lands; wired now so
@@ -446,15 +519,26 @@ export class MessageListComponent extends BaseAngularComponent {
446
519
  * initialise in order, and the other way round this captures undefined.
447
520
  */
448
521
  deleteMessage = this.DeleteMessage;
522
+ /** Forwarded from MessageItemComponent: the user asked for a new reply in place of an AI reply. */
523
+ RegenerateRequested = new EventEmitter();
524
+ /** @deprecated Use {@link RegenerateRequested}. Emits with it, for hosts that still bind the old name. */
449
525
  RetryMessage = new EventEmitter();
450
526
  /**
451
- * @deprecated Use {@link RetryMessage}.
527
+ * @deprecated Use {@link RegenerateRequested}.
452
528
  *
453
529
  * The same emitter under the old binding name, so a template still binding
454
530
  * (retryMessage) keeps working. Must stay AFTER RetryMessage: class fields
455
531
  * initialise in order, and the other way round this captures undefined.
456
532
  */
457
533
  retryMessage = this.RetryMessage;
534
+ /** Forwarded from MessageItemComponent: the user edited a message to save as a new fork. */
535
+ EditResendRequested = new EventEmitter();
536
+ /** A chip was clicked in one of the items: a fork to open, or the view and message of an original chip. */
537
+ ForkOpenRequested = new EventEmitter();
538
+ /** An item asked to fork the conversation at its message. */
539
+ ForkRequested = new EventEmitter();
540
+ /** Forwarded from MessageItemComponent: "Save and resend" saved a user message; the host reruns its turn. */
541
+ ResendInPlaceRequested = new EventEmitter();
458
542
  TestFeedbackMessage = new EventEmitter();
459
543
  /**
460
544
  * @deprecated Use {@link TestFeedbackMessage}.
@@ -473,24 +557,6 @@ export class MessageListComponent extends BaseAngularComponent {
473
557
  * initialise in order, and the other way round this captures undefined.
474
558
  */
475
559
  artifactClicked = this.ArtifactClicked;
476
- ReplyInThread = new EventEmitter();
477
- /**
478
- * @deprecated Use {@link ReplyInThread}.
479
- *
480
- * The same emitter under the old binding name, so a template still binding
481
- * (replyInThread) keeps working. Must stay AFTER ReplyInThread: class fields
482
- * initialise in order, and the other way round this captures undefined.
483
- */
484
- replyInThread = this.ReplyInThread;
485
- ViewThread = new EventEmitter();
486
- /**
487
- * @deprecated Use {@link ViewThread}.
488
- *
489
- * The same emitter under the old binding name, so a template still binding
490
- * (viewThread) keeps working. Must stay AFTER ViewThread: class fields
491
- * initialise in order, and the other way round this captures undefined.
492
- */
493
- viewThread = this.ViewThread;
494
560
  MessageEdited = new EventEmitter();
495
561
  /**
496
562
  * @deprecated Use {@link MessageEdited}.
@@ -536,6 +602,13 @@ export class MessageListComponent extends BaseAngularComponent {
536
602
  * initialise in order, and the other way round this captures undefined.
537
603
  */
538
604
  diagnosticRequested = this.DiagnosticRequested; // emits messageId
605
+ /**
606
+ * Relays a message item's `BeforeStopClicked`: fired before an in-progress run is stopped,
607
+ * cancelable by setting `event.Cancel = true`.
608
+ */
609
+ BeforeStopClicked = new EventEmitter();
610
+ /** Relays a message item's uncanceled stop request: the host stops the run behind that AI reply. */
611
+ StopMessage = new EventEmitter();
539
612
  MessagePinToggled = new EventEmitter();
540
613
  /**
541
614
  * @deprecated Use {@link MessagePinToggled}.
@@ -812,6 +885,39 @@ export class MessageListComponent extends BaseAngularComponent {
812
885
  * (not just scroll to it) use this instead of a `[data-message-id]` query, which fails for
813
886
  * exactly the cases listed — see {@link scrollToTimelineEntry}.
814
887
  */
888
+ /**
889
+ * Refreshes one rendered message in place: the streaming path's alternative to replacing the
890
+ * whole `messages` array, which rebuilds the timeline and re-measures the mounted range on
891
+ * every delta. Marks the item as streaming so its stylesheet can lift the status-line cap.
892
+ *
893
+ * @returns false only when the message has no rendered entry at all, so the caller can fall
894
+ * back to the full path for that one update. A spacer or a session card standing in for the
895
+ * message is a no-op: the entity holds the text and a remount renders it.
896
+ */
897
+ RefreshRenderedMessage(message) {
898
+ const existing = this._renderedMessages.get(this.getMessageKey(message));
899
+ if (!existing) {
900
+ return false;
901
+ }
902
+ switch (existing.kind) {
903
+ case 'embedded':
904
+ existing.ref.context.$implicit = message;
905
+ existing.ref.context.message = message;
906
+ if (!existing.ref.destroyed) {
907
+ existing.ref.detectChanges();
908
+ }
909
+ return true;
910
+ case 'component':
911
+ existing.ref.instance.message = message;
912
+ existing.ref.instance.IsStreaming = true;
913
+ if (!this.isViewDestroyed(existing.ref.changeDetectorRef)) {
914
+ existing.ref.changeDetectorRef.detectChanges();
915
+ }
916
+ return true;
917
+ default:
918
+ return true;
919
+ }
920
+ }
815
921
  FindTimelineElement(messageId) {
816
922
  const detail = this.messages?.find(m => UUIDsEqual(m.ID, messageId));
817
923
  if (!detail) {
@@ -905,6 +1011,114 @@ export class MessageListComponent extends BaseAngularComponent {
905
1011
  this.updateMessages(this.messages);
906
1012
  }
907
1013
  }
1014
+ /** The fork marker shown on its own when the view has no rows (a draft fork with no earlier rows); null otherwise. */
1015
+ get EmptyViewMarkerText() {
1016
+ const layout = this.ForkLayout;
1017
+ return layout && !layout.MarkerDetailID ? layout.MarkerText : null;
1018
+ }
1019
+ /** The chips placed under a message. */
1020
+ chipsFor(detailId) {
1021
+ return this.ForkChipMap.get(NormalizeUUID(detailId)) ?? EMPTY_FORK_CHIPS;
1022
+ }
1023
+ /** Pushes the current chips into every rendered message component. */
1024
+ applyForkChips() {
1025
+ for (const [, rendered] of this._renderedMessages ?? new Map()) {
1026
+ if (rendered.kind === 'component') {
1027
+ const instance = rendered.ref.instance;
1028
+ instance.ForkChips = this.chipsFor(instance.message.ID);
1029
+ rendered.ref.changeDetectorRef.markForCheck();
1030
+ }
1031
+ }
1032
+ }
1033
+ /** The rail of a row in the current layout. */
1034
+ railFor(detailId) {
1035
+ const layout = this.ForkLayout;
1036
+ if (!layout) {
1037
+ return null;
1038
+ }
1039
+ return layout.InheritedIDs.has(NormalizeUUID(detailId)) ? 'Inherited' : 'Own';
1040
+ }
1041
+ /** The fork marker under a row in the current layout. */
1042
+ markerFor(detailId) {
1043
+ const layout = this.ForkLayout;
1044
+ return layout?.MarkerDetailID && UUIDsEqual(layout.MarkerDetailID, detailId) ? layout.MarkerText : null;
1045
+ }
1046
+ /** Pushes the current layout into every rendered message component. */
1047
+ applyForkLayout() {
1048
+ for (const [, rendered] of this._renderedMessages ?? new Map()) {
1049
+ if (rendered.kind === 'component') {
1050
+ const instance = rendered.ref.instance;
1051
+ instance.ForkRail = this.railFor(instance.message.ID);
1052
+ instance.ForkMarkerText = this.markerFor(instance.message.ID);
1053
+ rendered.ref.changeDetectorRef.markForCheck();
1054
+ }
1055
+ }
1056
+ }
1057
+ /** The in-place role of a row in the current turn. */
1058
+ inPlaceRoleFor(detailId) {
1059
+ const turn = this.InPlaceTurn;
1060
+ if (!turn) {
1061
+ return null;
1062
+ }
1063
+ if (UUIDsEqual(turn.UserDetailID, detailId)) {
1064
+ return 'User';
1065
+ }
1066
+ return turn.AnswerDetailID && UUIDsEqual(turn.AnswerDetailID, detailId) ? 'Answer' : null;
1067
+ }
1068
+ /** Pushes the in-place roles into every rendered message component. */
1069
+ applyInPlaceRoles() {
1070
+ for (const [, rendered] of this._renderedMessages ?? new Map()) {
1071
+ if (rendered.kind === 'component') {
1072
+ const instance = rendered.ref.instance;
1073
+ instance.InPlaceRole = this.inPlaceRoleFor(instance.message.ID);
1074
+ instance.PendingReplace = this.pendingReplaceFor(instance.message.ID);
1075
+ rendered.ref.changeDetectorRef.markForCheck();
1076
+ }
1077
+ }
1078
+ }
1079
+ /** The message whose inline editor is open; null when none is. */
1080
+ editingDetailId = null;
1081
+ /** True when a message other than `detailId` has its inline editor open. */
1082
+ editOpenElsewhere(detailId) {
1083
+ return this.editingDetailId != null && !UUIDsEqual(this.editingDetailId, detailId);
1084
+ }
1085
+ /** True for the latest turn's answer while its user message is edited with "Save and resend". */
1086
+ pendingReplaceFor(detailId) {
1087
+ const turn = this.InPlaceTurn;
1088
+ return !!turn?.AnswerDetailID && this.editingDetailId != null
1089
+ && UUIDsEqual(this.editingDetailId, turn.UserDetailID) && UUIDsEqual(turn.AnswerDetailID, detailId);
1090
+ }
1091
+ /** A row's inline editor opened or closed: records it and pushes the edit state into every rendered row. */
1092
+ onRowEditingChanged(detailId, open) {
1093
+ if (open) {
1094
+ this.editingDetailId = detailId;
1095
+ }
1096
+ else if (this.editingDetailId != null && UUIDsEqual(this.editingDetailId, detailId)) {
1097
+ this.editingDetailId = null;
1098
+ }
1099
+ this.applyEditState();
1100
+ }
1101
+ /** Pushes the edit state (another row editing, answer pending replace) into every rendered message component. */
1102
+ applyEditState() {
1103
+ for (const [, rendered] of this._renderedMessages ?? new Map()) {
1104
+ if (rendered.kind === 'component') {
1105
+ const instance = rendered.ref.instance;
1106
+ instance.EditOpenElsewhere = this.editOpenElsewhere(instance.message.ID);
1107
+ instance.PendingReplace = this.pendingReplaceFor(instance.message.ID);
1108
+ rendered.ref.changeDetectorRef.markForCheck();
1109
+ }
1110
+ }
1111
+ }
1112
+ /** Pushes {@link CanFork} into every rendered message component. */
1113
+ applyCanFork() {
1114
+ for (const [, rendered] of this._renderedMessages ?? new Map()) {
1115
+ if (rendered.kind === 'component') {
1116
+ const instance = rendered.ref.instance;
1117
+ instance.CanFork = this.CanFork;
1118
+ rendered.ref.changeDetectorRef.markForCheck();
1119
+ }
1120
+ }
1121
+ }
908
1122
  /**
909
1123
  * Re-stamp the assistant-identity overrides onto every already-rendered message
910
1124
  * item. Called from the identity setters (see the inputs above) — items are created
@@ -1198,12 +1412,19 @@ export class MessageListComponent extends BaseAngularComponent {
1198
1412
  const timeline = BuildConversationTimeline(messages);
1199
1413
  // Remove rendered items (messages AND session blocks) that no longer exist
1200
1414
  const currentKeys = new Set(timeline.map(item => this.getTimelineKey(item)));
1415
+ const editingBefore = this.editingDetailId;
1201
1416
  this._renderedMessages.forEach((entry, key) => {
1202
1417
  if (!currentKeys.has(key)) {
1418
+ if (entry.kind === 'component' && this.editingDetailId != null && UUIDsEqual(entry.ref.instance.message?.ID, this.editingDetailId)) {
1419
+ this.editingDetailId = null;
1420
+ }
1203
1421
  entry.ref.destroy();
1204
1422
  this._renderedMessages.delete(key);
1205
1423
  }
1206
1424
  });
1425
+ if (editingBefore !== this.editingDetailId) {
1426
+ this.applyEditState();
1427
+ }
1207
1428
  // Add or update timeline items in chronological order. `renderMessageItem`
1208
1429
  // internally branches on the slot template (messageRenderer) vs the
1209
1430
  // default MessageItemComponent; `renderSessionBlock` always creates a
@@ -1216,6 +1437,7 @@ export class MessageListComponent extends BaseAngularComponent {
1216
1437
  // components. The tail and any in-progress message are always kept.
1217
1438
  const range = this.computeMountedRange(timeline);
1218
1439
  const lastMessageKey = this.findLastMessageKey(timeline);
1440
+ const lastUserKey = this.findLastUserMessageKey(timeline);
1219
1441
  for (let i = 0; i < timeline.length; i++) {
1220
1442
  const item = timeline[i];
1221
1443
  const mounted = (i >= range.start && i <= range.end)
@@ -1227,7 +1449,8 @@ export class MessageListComponent extends BaseAngularComponent {
1227
1449
  this.renderSessionBlock(item.Group, i);
1228
1450
  }
1229
1451
  else {
1230
- this.renderMessageItem(item.Detail, messages, this.getMessageKey(item.Detail) === lastMessageKey, i);
1452
+ const key = this.getMessageKey(item.Detail);
1453
+ this.renderMessageItem(item.Detail, messages, key === lastMessageKey, key === lastMessageKey || key === lastUserKey, i);
1231
1454
  }
1232
1455
  }
1233
1456
  // Decide where the viewport should end up.
@@ -1521,6 +1744,16 @@ export class MessageListComponent extends BaseAngularComponent {
1521
1744
  }
1522
1745
  return null;
1523
1746
  }
1747
+ /** The render key of the last User message item in the timeline (the latest turn's user message), or null when none. */
1748
+ findLastUserMessageKey(timeline) {
1749
+ for (let i = timeline.length - 1; i >= 0; i--) {
1750
+ const item = timeline[i];
1751
+ if (item.Kind === 'message' && item.Detail.Role === 'User') {
1752
+ return this.getMessageKey(item.Detail);
1753
+ }
1754
+ }
1755
+ return null;
1756
+ }
1524
1757
  /**
1525
1758
  * Creates or updates the ONE timeline card a realtime session collapses to.
1526
1759
  * Click/Open on the card bubbles up via {@link realtimeSessionOpenRequested} so the
@@ -1559,7 +1792,7 @@ export class MessageListComponent extends BaseAngularComponent {
1559
1792
  * dynamic-component path. Both paths flow through the shared
1560
1793
  * `createRenderedEntry` / `updateMessageItemInstance` helpers.
1561
1794
  */
1562
- renderMessageItem(message, messages, isLastMessage, timelineIndex) {
1795
+ renderMessageItem(message, messages, isLastMessage, isLatestTurn, timelineIndex) {
1563
1796
  const key = this.getMessageKey(message);
1564
1797
  // `index` is only used for the `isLastMessage` heuristic inside
1565
1798
  // updateMessageItemInstance — synthesize a value that produces the right
@@ -1577,7 +1810,7 @@ export class MessageListComponent extends BaseAngularComponent {
1577
1810
  }
1578
1811
  if (existing && existing.kind === 'component' && !useCustomRenderer) {
1579
1812
  // Update existing MessageItemComponent in place
1580
- this.updateMessageItemInstance(existing.ref, message, messages, index);
1813
+ this.updateMessageItemInstance(existing.ref, message, messages, index, isLatestTurn);
1581
1814
  return;
1582
1815
  }
1583
1816
  if (existing) {
@@ -1586,17 +1819,22 @@ export class MessageListComponent extends BaseAngularComponent {
1586
1819
  existing.ref.destroy();
1587
1820
  this._renderedMessages.delete(key);
1588
1821
  }
1589
- this.createRenderedEntry(message, messages, index, key, useCustomRenderer, timelineIndex);
1822
+ this.createRenderedEntry(message, messages, index, isLatestTurn, key, useCustomRenderer, timelineIndex);
1590
1823
  }
1591
1824
  /**
1592
1825
  * Updates an existing `MessageItemComponent` in place — used on the default
1593
1826
  * (non-custom-renderer) path when a message's status / artifacts / agent-run /
1594
1827
  * etc. changes mid-stream.
1595
1828
  */
1596
- updateMessageItemInstance(ref, message, messages, index) {
1829
+ updateMessageItemInstance(ref, message, messages, index, isLatestTurn) {
1597
1830
  const instance = ref.instance;
1598
1831
  const previousMessage = instance.message;
1599
1832
  instance.message = message;
1833
+ // Streaming ends with the message. It is deliberately NOT cleared on an in-progress full
1834
+ // render (an artifact landing mid-stream): that would snap the status cap back on for a frame.
1835
+ if (message.Status !== 'In-Progress') {
1836
+ instance.IsStreaming = false;
1837
+ }
1600
1838
  instance.allMessages = messages;
1601
1839
  instance.isProcessing = this.IsProcessing;
1602
1840
  instance.userAvatarMap = this.UserAvatarMap;
@@ -1606,6 +1844,11 @@ export class MessageListComponent extends BaseAngularComponent {
1606
1844
  instance.agentRun = this.AgentRunMap.get(message.ID) || null;
1607
1845
  instance.ratings = this.RatingsMap.get(message.ID);
1608
1846
  instance.attachments = this.AttachmentsMap.get(message.ID) || [];
1847
+ instance.ForkChips = this.chipsFor(message.ID);
1848
+ instance.ForkRail = this.railFor(message.ID);
1849
+ instance.ForkMarkerText = this.markerFor(message.ID);
1850
+ instance.InPlaceRole = this.inPlaceRoleFor(message.ID);
1851
+ this.applyRowTurnState(instance, isLatestTurn);
1609
1852
  // After the inputs above, for the same reason as the create path: this can force a
1610
1853
  // synchronous child pass, which would otherwise paint the previous refresh's agent run,
1611
1854
  // ratings and attachments.
@@ -1615,6 +1858,12 @@ export class MessageListComponent extends BaseAngularComponent {
1615
1858
  ref.changeDetectorRef.markForCheck();
1616
1859
  }
1617
1860
  }
1861
+ /** Sets a row's latest-turn flag and its edit state. */
1862
+ applyRowTurnState(instance, isLatestTurn) {
1863
+ instance.IsLatestTurn = isLatestTurn;
1864
+ instance.EditOpenElsewhere = this.editOpenElsewhere(instance.message.ID);
1865
+ instance.PendingReplace = this.pendingReplaceFor(instance.message.ID);
1866
+ }
1618
1867
  /**
1619
1868
  * Forward the host-level per-message feature gates onto a MessageItemComponent
1620
1869
  * instance. These are static host config (not per-message data), so the same
@@ -1629,6 +1878,9 @@ export class MessageListComponent extends BaseAngularComponent {
1629
1878
  instance.allowMessageEdit = this.AllowMessageEdit;
1630
1879
  instance.allowMessageDelete = this.AllowMessageDelete;
1631
1880
  instance.ReadOnly = this.ReadOnly;
1881
+ instance.AllowStopRun = this.AllowStopRun;
1882
+ instance.InFlightCount = this.InFlightCount;
1883
+ instance.CanFork = this.CanFork;
1632
1884
  instance.assistantDisplayName = this.AssistantDisplayName;
1633
1885
  instance.assistantAvatarUrl = this.AssistantAvatarUrl;
1634
1886
  }
@@ -1638,7 +1890,7 @@ export class MessageListComponent extends BaseAngularComponent {
1638
1890
  * Stores the entry in `_renderedMessages` and stamps a back-reference on the
1639
1891
  * message entity.
1640
1892
  */
1641
- createRenderedEntry(message, messages, index, key, useCustomRenderer, timelineIndex) {
1893
+ createRenderedEntry(message, messages, index, isLatestTurn, key, useCustomRenderer, timelineIndex) {
1642
1894
  if (useCustomRenderer && this.MessageRendererTemplate) {
1643
1895
  // The slot directive carries TemplateRef<unknown>; assert the contract here
1644
1896
  // (consumers' `let-message` bindings consume the message context shape below).
@@ -1663,9 +1915,24 @@ export class MessageListComponent extends BaseAngularComponent {
1663
1915
  instance.agentRun = this.AgentRunMap.get(message.ID) || null;
1664
1916
  instance.ratings = this.RatingsMap.get(message.ID);
1665
1917
  instance.attachments = this.AttachmentsMap.get(message.ID) || [];
1918
+ instance.ForkChips = this.chipsFor(message.ID);
1919
+ instance.ForkRail = this.railFor(message.ID);
1920
+ instance.ForkMarkerText = this.markerFor(message.ID);
1921
+ instance.InPlaceRole = this.inPlaceRoleFor(message.ID);
1922
+ this.applyRowTurnState(instance, isLatestTurn);
1923
+ instance.EditingChanged.subscribe((open) => this.onRowEditingChanged(instance.message.ID, open));
1924
+ instance.EditResendRequested.subscribe((e) => this.EditResendRequested.emit(e));
1925
+ instance.ForkOpenRequested.subscribe((e) => this.ForkOpenRequested.emit(e));
1926
+ instance.ForkRequested.subscribe((m) => this.ForkRequested.emit(m));
1927
+ instance.ResendInPlaceRequested.subscribe((m) => this.ResendInPlaceRequested.emit(m));
1666
1928
  instance.editClicked.subscribe((msg) => this.EditMessage.emit(msg));
1667
1929
  instance.deleteClicked.subscribe((msg) => this.DeleteMessage.emit(msg));
1668
- instance.retryClicked.subscribe((msg) => this.RetryMessage.emit(msg));
1930
+ instance.RegenerateRequested.subscribe((msg) => {
1931
+ this.RegenerateRequested.emit(msg);
1932
+ this.RetryMessage.emit(msg);
1933
+ });
1934
+ instance.BeforeStopClicked.subscribe((e) => this.BeforeStopClicked.emit(e));
1935
+ instance.StopRequested.subscribe((msg) => this.StopMessage.emit(msg));
1669
1936
  instance.testFeedbackClicked.subscribe((msg) => this.TestFeedbackMessage.emit(msg));
1670
1937
  instance.artifactClicked.subscribe((data) => this.ArtifactClicked.emit(data));
1671
1938
  instance.messageEdited.subscribe((msg) => this.MessageEdited.emit(msg));
@@ -1875,13 +2142,13 @@ export class MessageListComponent extends BaseAngularComponent {
1875
2142
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.spacerTemplate = _t.first);
1876
2143
  } }, hostVars: 2, hostBindings: function MessageListComponent_HostBindings(rf, ctx) { if (rf & 2) {
1877
2144
  i0.ɵɵclassProp("mj-list-host-scrolled", ctx.HostSuppliesScroller);
1878
- } }, inputs: { messages: "messages", Conversation: "Conversation", conversation: "conversation", CurrentUser: "CurrentUser", currentUser: "currentUser", IsProcessing: "IsProcessing", isProcessing: "isProcessing", ShowEmptyFill: "ShowEmptyFill", showEmptyFill: "showEmptyFill", ShowDateNavigation: "ShowDateNavigation", showDateNavigation: "showDateNavigation", ShowAgentRunDetails: "ShowAgentRunDetails", showAgentRunDetails: "showAgentRunDetails", ShowReactions: "ShowReactions", showReactions: "showReactions", ShowMessageRating: "ShowMessageRating", showMessageRating: "showMessageRating", AllowPinning: "AllowPinning", allowPinning: "allowPinning", AllowMessageEdit: "AllowMessageEdit", allowMessageEdit: "allowMessageEdit", AllowMessageDelete: "AllowMessageDelete", allowMessageDelete: "allowMessageDelete", ReadOnly: "ReadOnly", HasMoreAbove: "HasMoreAbove", IsLoadingOlder: "IsLoadingOlder", ScrollRoot: "ScrollRoot", AssistantDisplayName: "AssistantDisplayName", assistantDisplayName: "assistantDisplayName", AssistantAvatarUrl: "AssistantAvatarUrl", assistantAvatarUrl: "assistantAvatarUrl", ArtifactMap: "ArtifactMap", artifactMap: "artifactMap", AgentRunMap: "AgentRunMap", agentRunMap: "agentRunMap", RatingsMap: "RatingsMap", ratingsMap: "ratingsMap", UserAvatarMap: "UserAvatarMap", userAvatarMap: "userAvatarMap", AttachmentsMap: "AttachmentsMap", attachmentsMap: "attachmentsMap", SessionMetaMap: "SessionMetaMap", sessionMetaMap: "sessionMetaMap", MessageRendererTemplate: "MessageRendererTemplate", messageRendererTemplate: "messageRendererTemplate", MessageExtraTemplate: "MessageExtraTemplate", messageExtraTemplate: "messageExtraTemplate", MessagesUpdate: "MessagesUpdate", messagesUpdate: "messagesUpdate" }, outputs: { EditMessage: "EditMessage", editMessage: "editMessage", DeleteMessage: "DeleteMessage", deleteMessage: "deleteMessage", RetryMessage: "RetryMessage", retryMessage: "retryMessage", TestFeedbackMessage: "TestFeedbackMessage", testFeedbackMessage: "testFeedbackMessage", ArtifactClicked: "ArtifactClicked", artifactClicked: "artifactClicked", ReplyInThread: "ReplyInThread", replyInThread: "replyInThread", ViewThread: "ViewThread", viewThread: "viewThread", MessageEdited: "MessageEdited", messageEdited: "messageEdited", OpenEntityRecord: "OpenEntityRecord", openEntityRecord: "openEntityRecord", SuggestedResponseSelected: "SuggestedResponseSelected", suggestedResponseSelected: "suggestedResponseSelected", AttachmentClicked: "AttachmentClicked", attachmentClicked: "attachmentClicked", DiagnosticRequested: "DiagnosticRequested", diagnosticRequested: "diagnosticRequested", MessagePinToggled: "MessagePinToggled", messagePinToggled: "messagePinToggled", LivenessCheckRequested: "LivenessCheckRequested", RealtimeSessionOpenRequested: "RealtimeSessionOpenRequested", realtimeSessionOpenRequested: "realtimeSessionOpenRequested", BeforeResponseFormSubmitted: "BeforeResponseFormSubmitted", beforeResponseFormSubmitted: "beforeResponseFormSubmitted", AfterResponseFormSubmitted: "AfterResponseFormSubmitted", afterResponseFormSubmitted: "afterResponseFormSubmitted", OlderRequested: "OlderRequested", DateJumpRequested: "DateJumpRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 9, vars: 3, consts: [["scrollContainer", ""], ["spacerTemplate", ""], ["messageContainer", ""], ["olderSentinel", ""], [1, "message-list-container"], [1, "sticky-date-header"], [1, "transcript-older-sentinel"], ["Icon", "fa-solid fa-comments", "Title", "No messages yet. Start a conversation!", 1, "messages-empty-fill"], [1, "sticky-date-wrapper"], [1, "sticky-date-button", 3, "click"], [1, "fas", "fa-chevron-down"], [1, "date-nav-dropdown"], [1, "date-nav-option", "jump-to"], [1, "date-nav-option", 3, "click"], ["text", "Loading earlier messages\u2026", "size", "small"], [1, "transcript-older-label"], ["aria-hidden", "true", 1, "transcript-spacer"]], template: function MessageListComponent_Template(rf, ctx) { if (rf & 1) {
2145
+ } }, inputs: { messages: "messages", Conversation: "Conversation", conversation: "conversation", ForkChipMap: "ForkChipMap", ForkLayout: "ForkLayout", CanFork: "CanFork", InPlaceTurn: "InPlaceTurn", CurrentUser: "CurrentUser", currentUser: "currentUser", IsProcessing: "IsProcessing", isProcessing: "isProcessing", ShowEmptyFill: "ShowEmptyFill", showEmptyFill: "showEmptyFill", ShowDateNavigation: "ShowDateNavigation", showDateNavigation: "showDateNavigation", ShowAgentRunDetails: "ShowAgentRunDetails", showAgentRunDetails: "showAgentRunDetails", ShowReactions: "ShowReactions", showReactions: "showReactions", ShowMessageRating: "ShowMessageRating", showMessageRating: "showMessageRating", AllowPinning: "AllowPinning", allowPinning: "allowPinning", AllowMessageEdit: "AllowMessageEdit", allowMessageEdit: "allowMessageEdit", AllowMessageDelete: "AllowMessageDelete", allowMessageDelete: "allowMessageDelete", ReadOnly: "ReadOnly", AllowStopRun: "AllowStopRun", InFlightCount: "InFlightCount", HasMoreAbove: "HasMoreAbove", IsLoadingOlder: "IsLoadingOlder", ScrollRoot: "ScrollRoot", AssistantDisplayName: "AssistantDisplayName", assistantDisplayName: "assistantDisplayName", AssistantAvatarUrl: "AssistantAvatarUrl", assistantAvatarUrl: "assistantAvatarUrl", ArtifactMap: "ArtifactMap", artifactMap: "artifactMap", AgentRunMap: "AgentRunMap", agentRunMap: "agentRunMap", RatingsMap: "RatingsMap", ratingsMap: "ratingsMap", UserAvatarMap: "UserAvatarMap", userAvatarMap: "userAvatarMap", AttachmentsMap: "AttachmentsMap", attachmentsMap: "attachmentsMap", SessionMetaMap: "SessionMetaMap", sessionMetaMap: "sessionMetaMap", MessageRendererTemplate: "MessageRendererTemplate", messageRendererTemplate: "messageRendererTemplate", MessageExtraTemplate: "MessageExtraTemplate", messageExtraTemplate: "messageExtraTemplate", MessagesUpdate: "MessagesUpdate", messagesUpdate: "messagesUpdate" }, outputs: { EditMessage: "EditMessage", editMessage: "editMessage", DeleteMessage: "DeleteMessage", deleteMessage: "deleteMessage", RegenerateRequested: "RegenerateRequested", RetryMessage: "RetryMessage", retryMessage: "retryMessage", EditResendRequested: "EditResendRequested", ForkOpenRequested: "ForkOpenRequested", ForkRequested: "ForkRequested", ResendInPlaceRequested: "ResendInPlaceRequested", TestFeedbackMessage: "TestFeedbackMessage", testFeedbackMessage: "testFeedbackMessage", ArtifactClicked: "ArtifactClicked", artifactClicked: "artifactClicked", MessageEdited: "MessageEdited", messageEdited: "messageEdited", OpenEntityRecord: "OpenEntityRecord", openEntityRecord: "openEntityRecord", SuggestedResponseSelected: "SuggestedResponseSelected", suggestedResponseSelected: "suggestedResponseSelected", AttachmentClicked: "AttachmentClicked", attachmentClicked: "attachmentClicked", DiagnosticRequested: "DiagnosticRequested", diagnosticRequested: "diagnosticRequested", BeforeStopClicked: "BeforeStopClicked", StopMessage: "StopMessage", MessagePinToggled: "MessagePinToggled", messagePinToggled: "messagePinToggled", LivenessCheckRequested: "LivenessCheckRequested", RealtimeSessionOpenRequested: "RealtimeSessionOpenRequested", realtimeSessionOpenRequested: "realtimeSessionOpenRequested", BeforeResponseFormSubmitted: "BeforeResponseFormSubmitted", beforeResponseFormSubmitted: "beforeResponseFormSubmitted", AfterResponseFormSubmitted: "AfterResponseFormSubmitted", afterResponseFormSubmitted: "afterResponseFormSubmitted", OlderRequested: "OlderRequested", DateJumpRequested: "DateJumpRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 9, vars: 3, consts: [["scrollContainer", ""], ["spacerTemplate", ""], ["messageContainer", ""], ["olderSentinel", ""], [1, "message-list-container"], [1, "sticky-date-header"], [1, "transcript-older-sentinel"], [1, "sticky-date-wrapper"], [1, "sticky-date-button", 3, "click"], [1, "fas", "fa-chevron-down"], [1, "date-nav-dropdown"], [1, "date-nav-option", "jump-to"], [1, "date-nav-option", 3, "click"], ["text", "Loading earlier messages\u2026", "size", "small"], [1, "transcript-older-label"], ["aria-hidden", "true", 1, "transcript-spacer"], ["role", "note", 1, "fork-marker"], ["Icon", "fa-solid fa-comments", "Title", "No messages yet. Start a conversation!", 1, "messages-empty-fill"], ["aria-hidden", "true", 1, "fa-solid", "fa-code-branch"], [1, "fork-marker-text"], ["aria-hidden", "true", 1, "fork-marker-line"]], template: function MessageListComponent_Template(rf, ctx) { if (rf & 1) {
1879
2146
  i0.ɵɵelementStart(0, "div", 4, 0);
1880
2147
  i0.ɵɵconditionalCreate(2, MessageListComponent_Conditional_2_Template, 17, 3, "div", 5);
1881
2148
  i0.ɵɵconditionalCreate(3, MessageListComponent_Conditional_3_Template, 4, 1, "div", 6);
1882
2149
  i0.ɵɵtemplate(4, MessageListComponent_ng_template_4_Template, 1, 2, "ng-template", null, 1, i0.ɵɵtemplateRefExtractor);
1883
2150
  i0.ɵɵelementContainer(6, null, 2);
1884
- i0.ɵɵconditionalCreate(8, MessageListComponent_Conditional_8_Template, 1, 0, "mj-empty-state", 7);
2151
+ i0.ɵɵconditionalCreate(8, MessageListComponent_Conditional_8_Template, 2, 1);
1885
2152
  i0.ɵɵelementEnd();
1886
2153
  } if (rf & 2) {
1887
2154
  i0.ɵɵadvance(2);
@@ -1889,18 +2156,26 @@ export class MessageListComponent extends BaseAngularComponent {
1889
2156
  i0.ɵɵadvance();
1890
2157
  i0.ɵɵconditional(ctx.HasMoreAbove ? 3 : -1);
1891
2158
  i0.ɵɵadvance(5);
1892
- i0.ɵɵconditional(ctx.messages.length === 0 && ctx.showEmptyFill ? 8 : -1);
1893
- } }, dependencies: [i1.MJEmptyStateComponent, i2.LoadingComponent], styles: ["\n\n\n\n.message-list-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n\n.messages-empty-fill[_ngcontent-%COMP%] {\n height: 100%;\n}\n\n\n.sticky-date-header[_ngcontent-%COMP%] {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper[_ngcontent-%COMP%] {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n\n.date-nav-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show[_ngcontent-%COMP%] {\n display: block;\n}\n\n.date-nav-option[_ngcontent-%COMP%] {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%]:hover {\n background: none;\n}\n\n\n\n\n.transcript-older-sentinel[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 2.5rem;\n padding: 0.75rem 1rem;\n}\n\n.transcript-older-label[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n\n\n.transcript-spacer[_ngcontent-%COMP%] {\n width: 100%;\n flex-shrink: 0;\n}\n\n\n\n\n\n\n\n\n\n.mj-list-host-scrolled[_nghost-%COMP%] .message-list-container[_ngcontent-%COMP%] {\n overflow: visible;\n}"] });
2159
+ i0.ɵɵconditional(ctx.messages.length === 0 ? 8 : -1);
2160
+ } }, dependencies: [i1.MJEmptyStateComponent, i2.LoadingComponent], styles: ["\n\n\n\n.message-list-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n\n.messages-empty-fill[_ngcontent-%COMP%] {\n height: 100%;\n}\n\n\n.sticky-date-header[_ngcontent-%COMP%] {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper[_ngcontent-%COMP%] {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n\n.date-nav-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show[_ngcontent-%COMP%] {\n display: block;\n}\n\n.date-nav-option[_ngcontent-%COMP%] {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%]:hover {\n background: none;\n}\n\n\n\n\n.transcript-older-sentinel[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 2.5rem;\n padding: 0.75rem 1rem;\n}\n\n.transcript-older-label[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n\n\n.transcript-spacer[_ngcontent-%COMP%] {\n width: 100%;\n flex-shrink: 0;\n}\n\n\n\n\n\n\n\n\n\n.mj-list-host-scrolled[_nghost-%COMP%] .message-list-container[_ngcontent-%COMP%] {\n overflow: visible;\n}\n\n\n.fork-marker[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-4) var(--mj-space-6) var(--mj-space-2);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n}\n.fork-marker[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n}\n.fork-marker-line[_ngcontent-%COMP%] {\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n@media (max-width: 768px) {\n .fork-marker[_ngcontent-%COMP%] {\n padding: var(--mj-space-3) var(--mj-space-3) var(--mj-space-2);\n }\n}\n@media (max-width: 480px) {\n .fork-marker[_ngcontent-%COMP%] {\n padding: var(--mj-space-2);\n }\n}"] });
1894
2161
  }
1895
2162
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageListComponent, [{
1896
2163
  type: Component,
1897
- args: [{ standalone: false, selector: 'mj-conversation-message-list', template: "<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (showDateNavigation && shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <!-- Windowed transcript: older pages load when this scrolls into view (IntersectionObserver\n in the component, not a scroll listener). Absent entirely once the top is reached. -->\n @if (HasMoreAbove) {\n <div #olderSentinel class=\"transcript-older-sentinel\">\n @if (IsLoadingOlder) {\n <mj-loading text=\"Loading earlier messages\u2026\" size=\"small\"></mj-loading>\n } @else {\n <span class=\"transcript-older-label\">Earlier messages</span>\n }\n </div>\n }\n\n <!-- Height-holding stand-in for a timeline item that has been unmounted to keep the DOM\n bounded. Declared here but rendered into #messageContainer at the item's own index,\n so scroll geometry is unchanged. -->\n <ng-template #spacerTemplate let-height=\"height\">\n <div class=\"transcript-spacer\" [style.height.px]=\"height\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0 && showEmptyFill) {\n <mj-empty-state\n class=\"messages-empty-fill\"\n Icon=\"fa-solid fa-comments\"\n Title=\"No messages yet. Start a conversation!\" />\n }\n</div>", styles: ["/* Scrolls itself ONLY when no host scroller was supplied \u2014 see the `mj-list-host-scrolled`\n host binding. `overflow-y` here makes this element the nearest scrolling ancestor, which is\n what `position: sticky` binds to; when the host owns the scrolling this container never\n moves, so anything sticky inside it silently scrolls away instead of pinning. */\n.message-list-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n/* Empty-state fills the message pane vertically */\n.messages-empty-fill {\n height: 100%;\n}\n\n/* Sticky Date Header */\n.sticky-date-header {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button i {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n/* Date Navigation Dropdown */\n.date-nav-dropdown {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show {\n display: block;\n}\n\n.date-nav-option {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to:hover {\n background: none;\n}\n\n/* \u2500\u2500 Windowed transcript sentinel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Sits above the first loaded message while older pages remain. Needs real height\n so the IntersectionObserver has something to observe. */\n.transcript-older-sentinel {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 2.5rem;\n padding: 0.75rem 1rem;\n}\n\n.transcript-older-label {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n/* Stands in for an unmounted timeline item so the scroll range never changes when the\n DOM is trimmed. Height comes from the item's last measured size. */\n.transcript-spacer {\n width: 100%;\n flex-shrink: 0;\n}\n\n/* Host owns the scrolling: stop creating a scroll context here so `position: sticky`\n descendants (the date navigator) bind to the host's real scroller and actually pin.\n\n BOTH axes, not just `overflow-y`. Per CSS Overflow, when one axis is `visible` and the\n other is not, the `visible` one computes to `auto` \u2014 so leaving `overflow-x: hidden` in\n place silently kept this element a scroll container and the header kept scrolling away.\n Horizontal clipping is not lost: the host's own scroller (`.chat-messages-container`)\n already carries `overflow-x: hidden`. */\n:host(.mj-list-host-scrolled) .message-list-container {\n overflow: visible;\n}\n"] }]
2164
+ args: [{ standalone: false, selector: 'mj-conversation-message-list', template: "<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (showDateNavigation && shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <!-- Windowed transcript: older pages load when this scrolls into view (IntersectionObserver\n in the component, not a scroll listener). Absent entirely once the top is reached. -->\n @if (HasMoreAbove) {\n <div #olderSentinel class=\"transcript-older-sentinel\">\n @if (IsLoadingOlder) {\n <mj-loading text=\"Loading earlier messages\u2026\" size=\"small\"></mj-loading>\n } @else {\n <span class=\"transcript-older-label\">Earlier messages</span>\n }\n </div>\n }\n\n <!-- Height-holding stand-in for a timeline item that has been unmounted to keep the DOM\n bounded. Declared here but rendered into #messageContainer at the item's own index,\n so scroll geometry is unchanged. -->\n <ng-template #spacerTemplate let-height=\"height\">\n <div class=\"transcript-spacer\" [style.height.px]=\"height\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0) {\n @if (EmptyViewMarkerText) {\n <!-- A draft fork with no earlier rows: the fork marker, not the new-conversation empty state -->\n <div class=\"fork-marker\" role=\"note\">\n <i class=\"fa-solid fa-code-branch\" aria-hidden=\"true\"></i>\n <span class=\"fork-marker-text\">{{ EmptyViewMarkerText }}</span>\n <span class=\"fork-marker-line\" aria-hidden=\"true\"></span>\n </div>\n } @else if (showEmptyFill) {\n <mj-empty-state\n class=\"messages-empty-fill\"\n Icon=\"fa-solid fa-comments\"\n Title=\"No messages yet. Start a conversation!\" />\n }\n }\n</div>", styles: ["/* Scrolls itself ONLY when no host scroller was supplied \u2014 see the `mj-list-host-scrolled`\n host binding. `overflow-y` here makes this element the nearest scrolling ancestor, which is\n what `position: sticky` binds to; when the host owns the scrolling this container never\n moves, so anything sticky inside it silently scrolls away instead of pinning. */\n.message-list-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n/* Empty-state fills the message pane vertically */\n.messages-empty-fill {\n height: 100%;\n}\n\n/* Sticky Date Header */\n.sticky-date-header {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button i {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n/* Date Navigation Dropdown */\n.date-nav-dropdown {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show {\n display: block;\n}\n\n.date-nav-option {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to:hover {\n background: none;\n}\n\n/* \u2500\u2500 Windowed transcript sentinel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Sits above the first loaded message while older pages remain. Needs real height\n so the IntersectionObserver has something to observe. */\n.transcript-older-sentinel {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 2.5rem;\n padding: 0.75rem 1rem;\n}\n\n.transcript-older-label {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n/* Stands in for an unmounted timeline item so the scroll range never changes when the\n DOM is trimmed. Height comes from the item's last measured size. */\n.transcript-spacer {\n width: 100%;\n flex-shrink: 0;\n}\n\n/* Host owns the scrolling: stop creating a scroll context here so `position: sticky`\n descendants (the date navigator) bind to the host's real scroller and actually pin.\n\n BOTH axes, not just `overflow-y`. Per CSS Overflow, when one axis is `visible` and the\n other is not, the `visible` one computes to `auto` \u2014 so leaving `overflow-x: hidden` in\n place silently kept this element a scroll container and the header kept scrolling away.\n Horizontal clipping is not lost: the host's own scroller (`.chat-messages-container`)\n already carries `overflow-x: hidden`. */\n:host(.mj-list-host-scrolled) .message-list-container {\n overflow: visible;\n}\n\n/* The fork marker of a view with no rows; the same look as the marker under a row (message-item) */\n.fork-marker {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-4) var(--mj-space-6) var(--mj-space-2);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n}\n.fork-marker i {\n color: var(--mj-status-info);\n}\n.fork-marker-line {\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n@media (max-width: 768px) {\n .fork-marker {\n padding: var(--mj-space-3) var(--mj-space-3) var(--mj-space-2);\n }\n}\n@media (max-width: 480px) {\n .fork-marker {\n padding: var(--mj-space-2);\n }\n}\n"] }]
1898
2165
  }], () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], { messages: [{
1899
2166
  type: Input
1900
2167
  }], Conversation: [{
1901
2168
  type: Input
1902
2169
  }], conversation: [{
1903
2170
  type: Input
2171
+ }], ForkChipMap: [{
2172
+ type: Input
2173
+ }], ForkLayout: [{
2174
+ type: Input
2175
+ }], CanFork: [{
2176
+ type: Input
2177
+ }], InPlaceTurn: [{
2178
+ type: Input
1904
2179
  }], CurrentUser: [{
1905
2180
  type: Input
1906
2181
  }], currentUser: [{
@@ -1943,6 +2218,10 @@ export class MessageListComponent extends BaseAngularComponent {
1943
2218
  type: Input
1944
2219
  }], ReadOnly: [{
1945
2220
  type: Input
2221
+ }], AllowStopRun: [{
2222
+ type: Input
2223
+ }], InFlightCount: [{
2224
+ type: Input
1946
2225
  }], HasMoreAbove: [{
1947
2226
  type: Input
1948
2227
  }], IsLoadingOlder: [{
@@ -2000,25 +2279,27 @@ export class MessageListComponent extends BaseAngularComponent {
2000
2279
  type: Output
2001
2280
  }], deleteMessage: [{
2002
2281
  type: Output
2282
+ }], RegenerateRequested: [{
2283
+ type: Output
2003
2284
  }], RetryMessage: [{
2004
2285
  type: Output
2005
2286
  }], retryMessage: [{
2006
2287
  type: Output
2007
- }], TestFeedbackMessage: [{
2288
+ }], EditResendRequested: [{
2008
2289
  type: Output
2009
- }], testFeedbackMessage: [{
2290
+ }], ForkOpenRequested: [{
2010
2291
  type: Output
2011
- }], ArtifactClicked: [{
2292
+ }], ForkRequested: [{
2012
2293
  type: Output
2013
- }], artifactClicked: [{
2294
+ }], ResendInPlaceRequested: [{
2014
2295
  type: Output
2015
- }], ReplyInThread: [{
2296
+ }], TestFeedbackMessage: [{
2016
2297
  type: Output
2017
- }], replyInThread: [{
2298
+ }], testFeedbackMessage: [{
2018
2299
  type: Output
2019
- }], ViewThread: [{
2300
+ }], ArtifactClicked: [{
2020
2301
  type: Output
2021
- }], viewThread: [{
2302
+ }], artifactClicked: [{
2022
2303
  type: Output
2023
2304
  }], MessageEdited: [{
2024
2305
  type: Output
@@ -2040,6 +2321,10 @@ export class MessageListComponent extends BaseAngularComponent {
2040
2321
  type: Output
2041
2322
  }], diagnosticRequested: [{
2042
2323
  type: Output
2324
+ }], BeforeStopClicked: [{
2325
+ type: Output
2326
+ }], StopMessage: [{
2327
+ type: Output
2043
2328
  }], MessagePinToggled: [{
2044
2329
  type: Output
2045
2330
  }], messagePinToggled: [{
@@ -2079,5 +2364,5 @@ export class MessageListComponent extends BaseAngularComponent {
2079
2364
  }], messagesUpdate: [{
2080
2365
  type: Input
2081
2366
  }] }); })();
2082
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageListComponent, { className: "MessageListComponent", filePath: "src/lib/components/message/message-list.component.ts", lineNumber: 109 }); })();
2367
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageListComponent, { className: "MessageListComponent", filePath: "src/lib/components/message/message-list.component.ts", lineNumber: 111 }); })();
2083
2368
  //# sourceMappingURL=message-list.component.js.map