@memberjunction/ng-conversations 6.2.0-edge.0 → 6.2.0-edge.1
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.
- package/README.md +35 -2
- package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts +19 -3
- package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts.map +1 -1
- package/dist/lib/components/active-tasks/active-tasks-panel.component.js +39 -7
- package/dist/lib/components/active-tasks/active-tasks-panel.component.js.map +1 -1
- package/dist/lib/components/agent/active-agent-indicator.component.d.ts +74 -6
- package/dist/lib/components/agent/active-agent-indicator.component.d.ts.map +1 -1
- package/dist/lib/components/agent/active-agent-indicator.component.js +111 -21
- package/dist/lib/components/agent/active-agent-indicator.component.js.map +1 -1
- package/dist/lib/components/agent/agent-process-panel.component.d.ts +31 -5
- package/dist/lib/components/agent/agent-process-panel.component.d.ts.map +1 -1
- package/dist/lib/components/agent/agent-process-panel.component.js +71 -15
- package/dist/lib/components/agent/agent-process-panel.component.js.map +1 -1
- package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +65 -9
- package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/artifact/artifact-share-modal.component.js +169 -57
- package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
- package/dist/lib/components/attachment/image-viewer.component.d.ts +77 -11
- package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/attachment/image-viewer.component.js +181 -47
- package/dist/lib/components/attachment/image-viewer.component.js.map +1 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts +129 -19
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js +350 -116
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts +60 -8
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.js +130 -46
- package/dist/lib/components/collection/artifact-create-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-artifact-card.component.d.ts +63 -3
- package/dist/lib/components/collection/collection-artifact-card.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-artifact-card.component.js +113 -19
- package/dist/lib/components/collection/collection-artifact-card.component.js.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts +54 -8
- package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.js +130 -46
- package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-share-modal.component.d.ts +70 -10
- package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-share-modal.component.js +175 -53
- package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts +89 -9
- package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.js +220 -70
- package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
- package/dist/lib/components/collection/collection-view.component.d.ts +89 -11
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +154 -40
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts +390 -38
- package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.js +951 -367
- package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
- package/dist/lib/components/composer/ai-composer.component.d.ts +213 -18
- package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
- package/dist/lib/components/composer/ai-composer.component.js +388 -44
- package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +12 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.js +26 -4
- package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +1090 -123
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +2399 -706
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +139 -19
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.js +296 -59
- package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.d.ts +579 -78
- package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.js +2322 -823
- package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
- package/dist/lib/components/conversation/pinned-messages-panel.component.d.ts +40 -4
- package/dist/lib/components/conversation/pinned-messages-panel.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/pinned-messages-panel.component.js +72 -14
- package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
- package/dist/lib/components/dialogs/input-dialog.component.d.ts +57 -11
- package/dist/lib/components/dialogs/input-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/dialogs/input-dialog.component.js +128 -16
- package/dist/lib/components/dialogs/input-dialog.component.js.map +1 -1
- package/dist/lib/components/dialogs/rating-dialog.component.d.ts +68 -10
- package/dist/lib/components/dialogs/rating-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/dialogs/rating-dialog.component.js +151 -27
- package/dist/lib/components/dialogs/rating-dialog.component.js.map +1 -1
- package/dist/lib/components/export/export-modal.component.d.ts +84 -10
- package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
- package/dist/lib/components/export/export-modal.component.js +173 -49
- package/dist/lib/components/export/export-modal.component.js.map +1 -1
- package/dist/lib/components/global-tasks/global-tasks-panel.component.d.ts +29 -3
- package/dist/lib/components/global-tasks/global-tasks-panel.component.d.ts.map +1 -1
- package/dist/lib/components/global-tasks/global-tasks-panel.component.js +58 -12
- package/dist/lib/components/global-tasks/global-tasks-panel.component.js.map +1 -1
- package/dist/lib/components/library/library-full-view.component.d.ts +57 -8
- package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/library/library-full-view.component.js +119 -35
- package/dist/lib/components/library/library-full-view.component.js.map +1 -1
- package/dist/lib/components/members/members-modal.component.d.ts +76 -10
- package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
- package/dist/lib/components/members/members-modal.component.js +164 -50
- package/dist/lib/components/members/members-modal.component.js.map +1 -1
- package/dist/lib/components/message/actionable-commands.component.d.ts +37 -5
- package/dist/lib/components/message/actionable-commands.component.d.ts.map +1 -1
- package/dist/lib/components/message/actionable-commands.component.js +82 -16
- package/dist/lib/components/message/actionable-commands.component.js.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts +46 -10
- package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.js +120 -36
- package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +549 -74
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +1250 -421
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +411 -29
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +896 -222
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +288 -29
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +561 -123
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/navigation/conversation-navigation.component.d.ts +64 -5
- package/dist/lib/components/navigation/conversation-navigation.component.d.ts.map +1 -1
- package/dist/lib/components/navigation/conversation-navigation.component.js +101 -11
- package/dist/lib/components/navigation/conversation-navigation.component.js.map +1 -1
- package/dist/lib/components/notification/activity-indicator.component.d.ts +6 -2
- package/dist/lib/components/notification/activity-indicator.component.d.ts.map +1 -1
- package/dist/lib/components/notification/activity-indicator.component.js +13 -3
- package/dist/lib/components/notification/activity-indicator.component.js.map +1 -1
- package/dist/lib/components/notification/notification-badge.component.d.ts +15 -3
- package/dist/lib/components/notification/notification-badge.component.d.ts.map +1 -1
- package/dist/lib/components/notification/notification-badge.component.js +36 -8
- package/dist/lib/components/notification/notification-badge.component.js.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.js +4 -4
- package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.d.ts +93 -11
- package/dist/lib/components/project/project-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.js +348 -87
- package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
- package/dist/lib/components/project/project-selector.component.d.ts +78 -8
- package/dist/lib/components/project/project-selector.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-selector.component.js +177 -46
- package/dist/lib/components/project/project-selector.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.js +2 -2
- package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.js +2 -2
- package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-session-overlay.component.js +18 -18
- package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +47 -23
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +136 -92
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js +4 -4
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js +3 -3
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
- package/dist/lib/components/realtime/realtime-ui-config.d.ts +13 -11
- package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-ui-config.js +29 -25
- package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +3 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +6 -2
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
- package/dist/lib/components/search/search-panel.component.d.ts +133 -22
- package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
- package/dist/lib/components/search/search-panel.component.js +312 -83
- package/dist/lib/components/search/search-panel.component.js.map +1 -1
- package/dist/lib/components/share/share-modal.component.d.ts +69 -9
- package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/share/share-modal.component.js +139 -31
- package/dist/lib/components/share/share-modal.component.js.map +1 -1
- package/dist/lib/components/shared/user-picker.component.d.ts +48 -8
- package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
- package/dist/lib/components/shared/user-picker.component.js +110 -30
- package/dist/lib/components/shared/user-picker.component.js.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +114 -11
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.js +199 -21
- package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
- package/dist/lib/components/sidebar/routines-section.component.d.ts +20 -1
- package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -1
- package/dist/lib/components/sidebar/routines-section.component.js +25 -5
- package/dist/lib/components/sidebar/routines-section.component.js.map +1 -1
- package/dist/lib/components/slots/slot-interfaces.d.ts +19 -0
- package/dist/lib/components/slots/slot-interfaces.d.ts.map +1 -1
- package/dist/lib/components/slots/slot-interfaces.js.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.d.ts +95 -13
- package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.js +223 -75
- package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
- package/dist/lib/components/tasks/task-widget.component.d.ts +46 -6
- package/dist/lib/components/tasks/task-widget.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/task-widget.component.js +100 -16
- package/dist/lib/components/tasks/task-widget.component.js.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +64 -7
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js +127 -27
- package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.d.ts +66 -8
- package/dist/lib/components/thread/thread-panel.component.d.ts.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.js +146 -36
- package/dist/lib/components/thread/thread-panel.component.js.map +1 -1
- package/dist/lib/components/toast/toast.component.d.ts +11 -1
- package/dist/lib/components/toast/toast.component.d.ts.map +1 -1
- package/dist/lib/components/toast/toast.component.js +25 -5
- package/dist/lib/components/toast/toast.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +385 -42
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +887 -291
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +8 -0
- package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -1
- package/dist/lib/composer-plugins/base-conversation-mention.provider.js +8 -1
- package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -1
- package/dist/lib/directives/chat-slot.directive.d.ts +5 -1
- package/dist/lib/directives/chat-slot.directive.d.ts.map +1 -1
- package/dist/lib/directives/chat-slot.directive.js.map +1 -1
- package/dist/lib/directives/search-shortcut.directive.d.ts +9 -1
- package/dist/lib/directives/search-shortcut.directive.d.ts.map +1 -1
- package/dist/lib/directives/search-shortcut.directive.js +14 -4
- package/dist/lib/directives/search-shortcut.directive.js.map +1 -1
- package/dist/lib/events/chat-events.d.ts +34 -7
- package/dist/lib/events/chat-events.d.ts.map +1 -1
- package/dist/lib/events/chat-events.js +37 -7
- package/dist/lib/events/chat-events.js.map +1 -1
- package/dist/lib/models/agent-turn.model.d.ts +103 -0
- package/dist/lib/models/agent-turn.model.d.ts.map +1 -0
- package/dist/lib/models/agent-turn.model.js +12 -0
- package/dist/lib/models/agent-turn.model.js.map +1 -0
- package/dist/lib/models/collection-view.model.js.map +1 -1
- package/dist/lib/models/conversation-state.model.d.ts +8 -0
- package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
- package/dist/lib/models/conversation-state.model.js.map +1 -1
- package/dist/lib/models/lazy-artifact-info.d.ts +44 -12
- package/dist/lib/models/lazy-artifact-info.d.ts.map +1 -1
- package/dist/lib/models/lazy-artifact-info.js +98 -34
- package/dist/lib/models/lazy-artifact-info.js.map +1 -1
- package/dist/lib/services/active-tasks.service.d.ts +30 -4
- package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
- package/dist/lib/services/active-tasks.service.js +71 -19
- package/dist/lib/services/active-tasks.service.js.map +1 -1
- package/dist/lib/services/agent-state.service.d.ts +17 -1
- package/dist/lib/services/agent-state.service.d.ts.map +1 -1
- package/dist/lib/services/agent-state.service.js +48 -16
- package/dist/lib/services/agent-state.service.js.map +1 -1
- package/dist/lib/services/artifact-permission.service.d.ts +39 -0
- package/dist/lib/services/artifact-permission.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-permission.service.js +152 -17
- package/dist/lib/services/artifact-permission.service.js.map +1 -1
- package/dist/lib/services/artifact-state.service.d.ts +58 -5
- package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-state.service.js +135 -35
- package/dist/lib/services/artifact-state.service.js.map +1 -1
- package/dist/lib/services/collection-permission.service.d.ts +28 -0
- package/dist/lib/services/collection-permission.service.d.ts.map +1 -1
- package/dist/lib/services/collection-permission.service.js +88 -32
- package/dist/lib/services/collection-permission.service.js.map +1 -1
- package/dist/lib/services/collection-state.service.d.ts +11 -1
- package/dist/lib/services/collection-state.service.d.ts.map +1 -1
- package/dist/lib/services/collection-state.service.js +25 -5
- package/dist/lib/services/collection-state.service.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +26 -4
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +57 -18
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts +17 -0
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-attachment.service.js +38 -10
- package/dist/lib/services/conversation-attachment.service.js.map +1 -1
- package/dist/lib/services/conversation-streaming.service.d.ts +22 -0
- package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-streaming.service.js +50 -10
- package/dist/lib/services/conversation-streaming.service.js.map +1 -1
- package/dist/lib/services/data-cache.service.d.ts +31 -0
- package/dist/lib/services/data-cache.service.d.ts.map +1 -1
- package/dist/lib/services/data-cache.service.js +71 -15
- package/dist/lib/services/data-cache.service.js.map +1 -1
- package/dist/lib/services/dialog.service.d.ts +13 -0
- package/dist/lib/services/dialog.service.d.ts.map +1 -1
- package/dist/lib/services/dialog.service.js +25 -5
- package/dist/lib/services/dialog.service.js.map +1 -1
- package/dist/lib/services/export.service.d.ts +2 -0
- package/dist/lib/services/export.service.d.ts.map +1 -1
- package/dist/lib/services/export.service.js +5 -1
- package/dist/lib/services/export.service.js.map +1 -1
- package/dist/lib/services/mention-parser.service.d.ts +10 -0
- package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
- package/dist/lib/services/mention-parser.service.js +25 -5
- package/dist/lib/services/mention-parser.service.js.map +1 -1
- package/dist/lib/services/notification.service.d.ts +54 -6
- package/dist/lib/services/notification.service.d.ts.map +1 -1
- package/dist/lib/services/notification.service.js +123 -27
- package/dist/lib/services/notification.service.js.map +1 -1
- package/dist/lib/services/realtime-audio-recorder.d.ts +4 -4
- package/dist/lib/services/realtime-audio-recorder.js +12 -12
- package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
- package/dist/lib/services/realtime-pcm-wav.d.ts +4 -0
- package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -1
- package/dist/lib/services/realtime-pcm-wav.js +10 -2
- package/dist/lib/services/realtime-pcm-wav.js.map +1 -1
- package/dist/lib/services/search.service.d.ts +42 -9
- package/dist/lib/services/search.service.d.ts.map +1 -1
- package/dist/lib/services/search.service.js +103 -23
- package/dist/lib/services/search.service.js.map +1 -1
- package/dist/lib/services/toast.service.d.ts +19 -1
- package/dist/lib/services/toast.service.d.ts.map +1 -1
- package/dist/lib/services/toast.service.js +45 -9
- package/dist/lib/services/toast.service.js.map +1 -1
- package/dist/lib/services/ui-command-handler.service.d.ts +16 -2
- package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
- package/dist/lib/services/ui-command-handler.service.js +36 -8
- package/dist/lib/services/ui-command-handler.service.js.map +1 -1
- package/dist/lib/utils/agent-artifact-summary.d.ts +2 -2
- package/dist/lib/utils/agent-artifact-summary.js +3 -3
- package/dist/lib/utils/agent-artifact-summary.js.map +1 -1
- package/dist/lib/utils/agent-turn-routing.d.ts +69 -0
- package/dist/lib/utils/agent-turn-routing.d.ts.map +1 -0
- package/dist/lib/utils/agent-turn-routing.js +96 -0
- package/dist/lib/utils/agent-turn-routing.js.map +1 -0
- package/dist/lib/utils/artifact-panel-action.d.ts +15 -4
- package/dist/lib/utils/artifact-panel-action.d.ts.map +1 -1
- package/dist/lib/utils/artifact-panel-action.js +10 -2
- package/dist/lib/utils/artifact-panel-action.js.map +1 -1
- package/dist/lib/utils/distinct-artifacts.d.ts +2 -0
- package/dist/lib/utils/distinct-artifacts.d.ts.map +1 -1
- package/dist/lib/utils/distinct-artifacts.js +5 -1
- package/dist/lib/utils/distinct-artifacts.js.map +1 -1
- package/dist/lib/utils/plan-mode-preference.d.ts +2 -2
- package/dist/lib/utils/plan-mode-preference.js +6 -6
- package/dist/lib/utils/plan-mode-preference.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +32 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/message-list.component.ts","../../../../src/lib/components/message/message-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n HostBinding,\n EventEmitter,\n ViewChild,\n ViewContainerRef,\n OnInit,\n OnDestroy,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ElementRef,\n AfterViewInit,\n AfterViewChecked,\n ComponentRef,\n EmbeddedViewRef,\n ViewRef,\n TemplateRef\n} from '@angular/core';\nimport { MJConversationDetailEntity, MJConversationEntity, RatingJSON } from '@memberjunction/core-entities';\nimport { UserInfo, CompositeKey } from '@memberjunction/core';\nimport { NormalizeUUID, UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MessageItemComponent, MessageAttachment, MessageArtifactRef, MessagePendingArtifactRef } from './message-item.component';\nimport {\n BeforeResponseFormSubmittedEventArgs,\n AfterResponseFormSubmittedEventArgs,\n} from '../../events/chat-events';\nimport { RealtimeSessionTimelineCardComponent } from '../realtime/realtime-session-timeline-card.component';\nimport { LazyArtifactInfo } from '../../models/lazy-artifact-info';\nimport { selectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';\nimport {\n BuildConversationTimeline,\n ConversationTimelineItem,\n RealtimeSessionTimelineGroup,\n RealtimeSessionTimelineMeta\n} from '../../utils/realtime-session-timeline';\nimport { MJAIAgentRunEntityExtended } from '@memberjunction/ai-core-plus';\nimport { DEFAULT_TRANSCRIPT_PAGE_SIZE } from '../../utils/conversation-detail-window';\nimport {\n ResolveDateJumpTarget,\n type DateJumpPeriod,\n type DateJumpOutcome\n} from '../../utils/date-jump';\n\n/** Context handed to the `messageRenderer` slot template per message. */\ninterface MessageRendererContext {\n $implicit: MJConversationDetailEntity;\n message: MJConversationDetailEntity;\n}\n\n/**\n * One per rendered message in the list. Three paths can produce an entry:\n * - `component` — the default `MessageItemComponent` (single message).\n * - `embedded` — an `EmbeddedViewRef` from the consumer's\n * `messageRenderer` slot template (full per-message\n * replacement, PR 2c slot system).\n * - `realtime-session` — a `RealtimeSessionTimelineCardComponent` collapsing\n * an entire past realtime session into one timeline\n * card (PR #2787 co-agent timeline). The grouping pass\n * (`BuildConversationTimeline`) emits these alongside\n * normal messages — see the timeline utility for the\n * rules.\n *\n * Discriminated by the `kind` tag for ergonomic narrowing.\n */\ntype RenderedMessageEntry =\n | { kind: 'component'; ref: ComponentRef<MessageItemComponent> }\n | { kind: 'embedded'; ref: EmbeddedViewRef<MessageRendererContext> }\n | { kind: 'realtime-session'; ref: ComponentRef<RealtimeSessionTimelineCardComponent> }\n /**\n * A timeline item that has been UNMOUNTED to keep the DOM bounded — replaced by a\n * fixed-height div so the scroll range is unchanged. Stored under the item's own\n * timeline key so it can be swapped back for the real view on scroll-back.\n */\n | { kind: 'spacer'; ref: EmbeddedViewRef<SpacerContext> };\n\n/** Context for the spacer template — the height the unmounted item occupied. */\ninterface SpacerContext {\n height: number;\n}\n\n/**\n * Container component for displaying a list of messages\n * Uses dynamic component creation (like skip-chat) to avoid Angular binding overhead\n * This dramatically improves performance when messages are added/removed\n */\n/** Dropdown label per period. Kept beside the guard so a new period cannot render blank. */\nconst DATE_JUMP_LABELS: Record<DateJumpPeriod, string> = {\n 'today': 'Today',\n 'yesterday': 'Yesterday',\n 'last-week': 'Last week',\n 'last-month': 'Last month'\n};\n\n/** Narrows the template's string to the period union — the template cannot type its own literals. */\nfunction isDateJumpPeriod(value: string): value is DateJumpPeriod {\n return Object.prototype.hasOwnProperty.call(DATE_JUMP_LABELS, value);\n}\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-message-list',\n templateUrl: './message-list.component.html',\n styleUrls: ['./message-list.component.css']\n})\nexport class MessageListComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit, AfterViewChecked {\n @Input() public messages: MJConversationDetailEntity[] = [];\n @Input() public conversation!: MJConversationEntity | null;\n @Input() public currentUser!: UserInfo;\n @Input() public isProcessing: boolean = false;\n /** Whether the built-in \"No messages yet\" filler renders for empty conversations. Hosts with their own empty-state chrome set false. */\n @Input() public showEmptyFill: boolean = true;\n /** Whether the sticky date header + jump-to-date dropdown render. */\n @Input() public showDateNavigation: boolean = true;\n // Per-message feature gates — forwarded onto each MessageItemComponent instance\n // (see applyMessageItemFeatureFlags). All default true.\n @Input() public showAgentRunDetails: boolean = true;\n @Input() public showReactions: boolean = true;\n @Input() public showMessageRating: boolean = true;\n @Input() public allowPinning: boolean = true;\n @Input() public allowMessageEdit: boolean = true;\n @Input() public allowMessageDelete: boolean = true;\n\n // ── Windowed-transcript paging state ────────────────────────────────────────\n // The list renders only the LOADED window, not the whole conversation. These two\n // describe what lies above it. Unused until the Phase 5 sentinel lands; wired now so\n // the host binding is in place and the component's contract is stable.\n\n /**\n * True when older pages remain above the loaded window.\n *\n * Setter rather than a plain input: flipping this creates or destroys the sentinel via\n * `@if`, and the observer has to be re-pointed at the new element. Relying on an ambient\n * `ngAfterViewChecked` tick to notice is fragile — once the list settles there may not be\n * another one.\n */\n @Input()\n public set HasMoreAbove(value: boolean) {\n if (value === this._hasMoreAbove) {\n return;\n }\n this._hasMoreAbove = value;\n // Gates the date navigator too — see updateDateFilterVisibility. Without this the button\n // would only re-evaluate on a `messages` change, so exhausting history would leave it up.\n this.updateDateFilterVisibility();\n // Deferred: the `@if` has not rendered the sentinel yet at set time.\n Promise.resolve().then(() => this.syncOlderObserver());\n }\n public get HasMoreAbove(): boolean {\n return this._hasMoreAbove;\n }\n private _hasMoreAbove = false;\n\n /** True while an older page is in flight. */\n @Input() public IsLoadingOlder: boolean = false;\n\n /**\n * The host's scrolling element, used as the sentinel observer's root.\n *\n * This component's own container does NOT scroll — hosts wrap it in their own scroller\n * (in the chat area, `.chat-messages-container`, which carries the `min-height: 0` a flex\n * child needs). Passing it in is deterministic; discovering it by walking the DOM depends\n * on layout having settled, which is not knowable from in here.\n *\n * Optional: when omitted the component falls back to walking its ancestors.\n */\n @Input()\n public set ScrollRoot(value: HTMLElement | null | undefined) {\n const next = value ?? null;\n if (next === this._scrollRoot) {\n return;\n }\n this._scrollRoot = next;\n this._scrollParent = next;\n // The root changed, so any live observer is pointed at the wrong element.\n Promise.resolve().then(() => this.syncOlderObserver());\n }\n public get ScrollRoot(): HTMLElement | null {\n return this._scrollRoot;\n }\n private _scrollRoot: HTMLElement | null = null;\n\n /**\n * Marks the host as \"someone else owns the scrolling\", which drops `overflow-y` on this\n * component's own container.\n *\n * `position: sticky` pins to the nearest ancestor with `overflow-y: auto|scroll`. When a\n * host supplies a scroller, this component's container still declared `overflow-y: auto`\n * but never actually scrolled (its content grows to fit), so the sticky date header bound\n * to a container whose `scrollTop` is permanently 0 — it rendered, then rode out of view\n * with the messages and could not be clicked.\n *\n * Driven off `_scrollRoot` rather than `resolveScrollParent()` on purpose: the DOM walk is\n * lazy and layout-dependent, and dropping `overflow-y` for a consumer that turned out to\n * have NO scrolling ancestor would leave the transcript unable to scroll or page at all.\n * The explicit input is the only signal that is safe here — a host that passes it has, by\n * definition, a scroller of its own.\n */\n @HostBinding('class.mj-list-host-scrolled')\n public get HostSuppliesScroller(): boolean {\n return this._scrollRoot !== null;\n }\n\n // ── Assistant identity overrides — static host config forwarded to every message\n // item (null = engine identity). Setters (not ngOnChanges) so an imperative\n // host — `@ViewChild(MessageListComponent).assistantDisplayName = …` — restamps\n // too, and so identity changes don't pay a check on every other input's cycle.\n // Identity can land AFTER first render (branding resolves async) or change\n // mid-session (per-conversation persona), and message items are created\n // dynamically with the overrides stamped as static config — so a change has to\n // restamp the ALREADY-rendered items or existing bubbles keep the old identity\n // until the next messages-array mutation. ──\n /** Display name shown on AI messages. Null = the engine-resolved agent name. */\n @Input()\n public set assistantDisplayName(value: string | null) {\n if (value !== this._assistantDisplayName) {\n this._assistantDisplayName = value;\n this.restampAssistantIdentity();\n }\n }\n public get assistantDisplayName(): string | null {\n return this._assistantDisplayName;\n }\n private _assistantDisplayName: string | null = null;\n\n /** Image URL for the AI message avatar. Null = the agent's Font Awesome icon. */\n @Input()\n public set assistantAvatarUrl(value: string | null) {\n if (value !== this._assistantAvatarUrl) {\n this._assistantAvatarUrl = value;\n this.restampAssistantIdentity();\n }\n }\n public get assistantAvatarUrl(): string | null {\n return this._assistantAvatarUrl;\n }\n private _assistantAvatarUrl: string | null = null;\n @Input() public artifactMap: Map<string, LazyArtifactInfo[]> = new Map();\n @Input() public agentRunMap: Map<string, MJAIAgentRunEntityExtended> = new Map();\n @Input() public ratingsMap: Map<string, RatingJSON[]> = new Map();\n @Input() public userAvatarMap: Map<string, {imageUrl: string | null; iconClass: string | null}> = new Map();\n @Input() public attachmentsMap: Map<string, MessageAttachment[]> = new Map();\n /**\n * Optional session-row enrichment for realtime SESSION BLOCKS, keyed by\n * `NormalizeUUID(sessionId)` (agent name / status / close reason). Details stamped\n * with an `AgentSessionID` collapse into one timeline card per session — see\n * `BuildConversationTimeline` — and this map dresses those cards up when present.\n */\n @Input() public sessionMetaMap: Map<string, RealtimeSessionTimelineMeta> = new Map();\n\n /**\n * Optional per-iteration custom message renderer. When set, the list renders each\n * message via this template (full replacement) instead of the default\n * `MessageItemComponent`. Forwarded by chat-area when a consumer projects\n * `mjChatSlot=\"messageRenderer\"`. The template receives the message as\n * `$implicit` and as a named `message` context binding.\n *\n * Consumers opting into a custom renderer take full responsibility for displaying\n * the message — edit/delete/retry affordances, artifacts, ratings, attachments,\n * etc. The minimal `MJChatMessageBubbleDefaultComponent` ships as a ready-to-use\n * bubble renderer.\n */\n @Input() public messageRendererTemplate: TemplateRef<unknown> | null = null;\n\n /**\n * Optional per-message additive decoration template, projected INSIDE the default\n * `MessageItemComponent` (after the message text). Forwarded by chat-area when a\n * consumer projects `mjChatSlot=\"messageExtra\"`. Ignored when\n * `messageRendererTemplate` is set (custom renderers own all per-message content).\n */\n @Input() public messageExtraTemplate: TemplateRef<unknown> | null = null;\n\n @Output() public editMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public deleteMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public retryMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public testFeedbackMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public artifactClicked = new EventEmitter<{artifactId: string; versionId?: string}>();\n @Output() public replyInThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public viewThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public messageEdited = new EventEmitter<MJConversationDetailEntity>();\n @Output() public openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n @Output() public suggestedResponseSelected = new EventEmitter<{text: string; customInput?: string}>();\n @Output() public attachmentClicked = new EventEmitter<MessageAttachment>();\n @Output() public diagnosticRequested = new EventEmitter<string>(); // emits messageId\n @Output() public messagePinToggled = new EventEmitter<MJConversationDetailEntity>();\n /** Emitted with the `MJ: AI Agent Sessions.ID` when a realtime session block's Open affordance is clicked. */\n @Output() public realtimeSessionOpenRequested = new EventEmitter<string>();\n\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public beforeResponseFormSubmitted = new EventEmitter<BeforeResponseFormSubmittedEventArgs>();\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public afterResponseFormSubmitted = new EventEmitter<AfterResponseFormSubmittedEventArgs>();\n\n /**\n * Asks the host to load the next older page. Fired when the \"earlier messages\"\n * sentinel scrolls into view — never on a raw scroll event, so a fast scroll costs\n * one emit rather than one per pixel.\n */\n @Output() public OlderRequested = new EventEmitter<void>();\n\n /**\n * Asks the host to page older history far enough back to satisfy a date jump, then scroll.\n * Emitted instead of handled locally because paging belongs to the window store.\n */\n @Output() public DateJumpRequested = new EventEmitter<DateJumpPeriod>();\n\n @ViewChild('messageContainer', { read: ViewContainerRef }) messageContainerRef!: ViewContainerRef;\n @ViewChild('scrollContainer') scrollContainer!: ElementRef;\n /** Only present while `HasMoreAbove` is true — the `@if` creates and destroys it. */\n @ViewChild('olderSentinel') olderSentinel?: ElementRef<HTMLElement>;\n /** Template rendered in place of an unmounted timeline item. */\n @ViewChild('spacerTemplate') private spacerTemplate?: TemplateRef<SpacerContext>;\n\n /**\n * Per-message rendered entries — see `RenderedMessageEntry` for the 3-way\n * union (default MessageItemComponent / consumer messageRenderer slot\n * embedded view / collapsed realtime session timeline card).\n */\n private _renderedMessages = new Map<string, RenderedMessageEntry>();\n\n /**\n * Per-message artifact-load counter, so a stale in-flight load cannot clobber a newer one.\n * Keyed by the child instance and held weakly, so an entry lives exactly as long as its\n * component — nothing to prune when a message leaves the timeline.\n *\n * Created on first use rather than as a field initializer. `message-list-windowing.test.ts`\n * constructs this component off the prototype, which runs none of the initializers; a\n * field initializer here failed nine of its cases.\n */\n private _artifactLoadGeneration?: WeakMap<MessageItemComponent, number>;\n\n private get artifactLoadGeneration(): WeakMap<MessageItemComponent, number> {\n return (this._artifactLoadGeneration ??= new WeakMap<MessageItemComponent, number>());\n }\n private _shouldScrollToBottom = false;\n private _previousMessageCount = 0; // Track previous count to detect new messages\n\n /** Watches the \"earlier messages\" sentinel. Rebuilt whenever the sentinel comes or goes. */\n private _olderObserver?: IntersectionObserver;\n /**\n * Set when the newest render PREPENDED older content, so `ngAfterViewChecked` can hold\n * the user's reading position instead of letting the browser's pixel-based `scrollTop`\n * slide them to unfamiliar content.\n */\n private _restoreScrollAfterPrepend = false;\n /** `scrollHeight` captured immediately before a prepend render. */\n private _heightBeforePrepend = 0;\n /** Memoized result of {@link resolveScrollParent} — the host's scroller, not ours. */\n private _scrollParent: HTMLElement | null = null;\n /** What the live observer is currently watching, so a stale pairing can be detected. */\n private _observedSentinel: HTMLElement | null = null;\n private _observedRoot: HTMLElement | null = null;\n /** Guards the no-scroll-parent warning so it fires once, not every checked cycle. */\n private _warnedNoScrollParent = false;\n /** Guards the missing-spacer-template warning the same way. */\n private _warnedNoSpacerTemplate = false;\n\n // ── DOM unmount (bounded transcript) ────────────────────────────────────────\n // Paging up 20 times would otherwise leave 200 live MessageItemComponents mounted.\n // Items far from the viewport are destroyed and replaced by a height-holding spacer,\n // then remounted from `messages` (already in memory — no network) on scroll-back.\n\n /** Rendered pixel height per timeline key, captured just before an item is unmounted. */\n private _measuredHeights = new Map<string, number>();\n /** Watches spacers so an item remounts as the user scrolls back toward it. */\n private _spacerObserver?: IntersectionObserver;\n /** Which spacers the live observer is watching, so it is only rebuilt when the set changes. */\n private _observedSpacerKeys = '';\n /** Scroller the window listener is attached to, and its coalescing frame handle. */\n private _scrollListenerTarget: HTMLElement | null = null;\n private _onScroll: (() => void) | null = null;\n private _scrollFrame: number | null = null;\n\n /** Items kept mounted beyond the visible page, above and below. */\n private static readonly MOUNT_BUFFER = 5;\n /**\n * Height used for an item unmounted before it was ever measured. Only a first-render\n * fallback — a real measurement replaces it and is preferred forever after.\n */\n private static readonly ESTIMATED_MESSAGE_HEIGHT = 72;\n private static readonly ESTIMATED_SESSION_HEIGHT = 88;\n /** Frames spent waiting for a scroller to appear, and the pending rAF handle. */\n private _scrollParentRetries = 0;\n private _scrollParentRetryHandle: number | null = null;\n /** ~1s at 60fps — long enough for layout to settle, short enough to report a real fault. */\n private static readonly MAX_SCROLL_PARENT_RETRIES = 60;\n /**\n * Render key of the FIRST timeline item last time we rendered. A change here means older\n * content arrived at the head — the only reliable way to tell a prepend from an append,\n * since both grow `messages.length`.\n */\n private _previousFirstKey: string | null = null;\n\n public currentDateDisplay: string = 'Today';\n public showDateNav: boolean = false;\n public shouldShowDateFilter: boolean = false;\n\n constructor(private cdRef: ChangeDetectorRef, private hostRef: ElementRef<HTMLElement>) {\n super();\n }\n\n public toggleDateNav(): void {\n this.showDateNav = !this.showDateNav;\n }\n\n /**\n * Handles a date-navigator selection.\n *\n * The list cannot page history itself — it is a Generic widget with no store — so it asks\n * the host, which owns the window and runs the older-page loop, then calls back into\n * {@link ScrollToDateTarget}. The label updates immediately so the dropdown feels responsive\n * while paging runs.\n */\n public jumpToDate(period: string): void {\n this.showDateNav = false;\n if (!isDateJumpPeriod(period)) {\n return;\n }\n this.currentDateDisplay = DATE_JUMP_LABELS[period];\n this.DateJumpRequested.emit(period);\n }\n\n /**\n * Scrolls to the start of `period` within the currently loaded messages.\n *\n * Called by the host AFTER it has paged as far back as it intends to, so whatever is loaded\n * now is the best answer available. Returns the outcome rather than failing silently — the\n * plan's explicit requirement for this path.\n */\n public ScrollToDateTarget(period: DateJumpPeriod): DateJumpOutcome {\n if (!this.messages || this.messages.length === 0) {\n return 'empty';\n }\n\n const { Detail } = ResolveDateJumpTarget(this.messages, period, new Date());\n // A miss lands the user on the oldest loaded message — where paging left them — rather\n // than leaving the viewport wherever it happened to be.\n const target = Detail ?? this.messages[0];\n const scrolled = this.scrollToDetail(target);\n if (!scrolled) {\n return 'empty';\n }\n return Detail ? 'reached' : 'oldest';\n }\n\n /**\n * Scrolls a loaded detail into view, mounted or not.\n *\n * Resolves through the TIMELINE KEY rather than querying `[data-message-id]`, because the\n * jump target is by definition far above the viewport — exactly the region this component\n * unmounts and replaces with height-holding spacers. A DOM query for the message id misses\n * every unmounted target, which made a legitimate jump report \"nothing loaded to jump to\".\n *\n * Spacers carry the same timeline key as the item they stand in for, so scrolling to the\n * key lands on the right place either way; the spacer observer then remounts the real item\n * as it enters the viewport.\n */\n private scrollToDetail(detail: MJConversationDetailEntity): boolean {\n return this.scrollToTimelineEntry(detail.ID, detail.AgentSessionID, 'start');\n }\n\n /**\n * Scrolls a LOADED message into view by id, mounted or not, and returns whether it landed.\n *\n * Public because the pins panel's \"Jump to message\" lives on the host: a pin can be far\n * above the viewport, which is exactly the region this component unmounts into spacers, so\n * the host's own `[data-message-id]` query found nothing and the button silently did\n * nothing. Resolution goes through the timeline key instead — see\n * {@link scrollToTimelineEntry}.\n *\n * Returns false when the message is not in the loaded window at all; the host decides\n * whether to page back for it or tell the user.\n */\n public ScrollToMessage(messageId: string): boolean {\n const detail = this.messages?.find(m => UUIDsEqual(m.ID, messageId));\n if (!detail) {\n return false;\n }\n return this.scrollToTimelineEntry(detail.ID, detail.AgentSessionID, 'center');\n }\n\n /**\n * The node standing for a LOADED message on screen — the mounted item, the spacer holding\n * its place while it is unmounted, or the session card a session-stamped row folds into.\n * Null when the message is not in the loaded window. Hosts that need to MEASURE a message\n * (not just scroll to it) use this instead of a `[data-message-id]` query, which fails for\n * exactly the cases listed — see {@link scrollToTimelineEntry}.\n */\n public FindTimelineElement(messageId: string): HTMLElement | null {\n const detail = this.messages?.find(m => UUIDsEqual(m.ID, messageId));\n if (!detail) {\n return null;\n }\n return this.resolveTimelineNode(detail.ID, detail.AgentSessionID) ?? null;\n }\n\n /**\n * Shared resolution for both jump paths: timeline key -> rendered node.\n *\n * Two things a `[data-message-id]` query cannot do, and both matter here:\n * - A session-stamped row folds into its session CARD, so the row itself never has a\n * node of its own; the card is what is on screen.\n * - An item far from the viewport is unmounted and replaced by a height-holding spacer,\n * which carries the SAME timeline key — so scrolling to the key lands in the right\n * place either way, and the spacer observer remounts the real item on arrival.\n */\n private scrollToTimelineEntry(\n detailId: string,\n agentSessionId: string | null,\n block: ScrollLogicalPosition\n ): boolean {\n const node = this.resolveTimelineNode(detailId, agentSessionId);\n if (!node) {\n return false;\n }\n node.scrollIntoView({ behavior: 'smooth', block });\n return true;\n }\n\n /** Timeline key -> rendered node for a detail (or the session card its stamped row folds into). */\n private resolveTimelineNode(detailId: string, agentSessionId: string | null): HTMLElement | undefined {\n const stampedSessionId = agentSessionId?.trim() || null;\n const timeline = BuildConversationTimeline(this.messages);\n const item = timeline.find(entry =>\n entry.Kind === 'session'\n ? stampedSessionId !== null && UUIDsEqual(entry.Group.SessionID, stampedSessionId)\n : UUIDsEqual(entry.Detail.ID, detailId)\n );\n return item ? this.nodeForKey(this.getTimelineKey(item)) : undefined;\n }\n\n // Track whether initial render has happened\n private _initialRenderComplete = false;\n\n ngOnInit() {\n // Initial render will happen in ngAfterViewInit when ViewContainerRef is available\n }\n\n ngAfterViewInit() {\n // ViewContainerRef is now available - perform initial render if we have messages\n if (this.messages && this.messages.length > 0 && this.messageContainerRef && !this._initialRenderComplete) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // React to messages array changes\n // Note: On initial load, messageContainerRef may not be available yet (ngOnChanges runs before ngAfterViewInit)\n // In that case, ngAfterViewInit will handle the initial render\n if (changes['messages'] && this.messages && this.messageContainerRef) {\n this._initialRenderComplete = true;\n // Capture the pre-render height so a prepend can be corrected for. Must happen\n // BEFORE updateMessages — afterwards the new rows are already in the layout — and\n // must read the HOST's scroller, which is the element whose height actually changes.\n this._heightBeforePrepend = this.resolveScrollParent()?.scrollHeight ?? 0;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n\n // Watch for artifactMap changes to handle newly created artifacts\n // While artifacts are pre-loaded during initial peripheral data load,\n // new artifacts can be created mid-conversation (e.g., by agent runs)\n // This ensures artifact cards appear in messages immediately without requiring a refresh\n if (changes['artifactMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for attachmentsMap changes to handle newly created attachments\n // This ensures media attachments (e.g., images generated by agents) appear\n // immediately without requiring a page refresh\n if (changes['attachmentsMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for session-meta changes so realtime session blocks pick up their\n // agent name / status chip once the (async, batched) session lookup lands\n if (changes['sessionMetaMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n }\n\n /**\n * Re-stamp the assistant-identity overrides onto every already-rendered message\n * item. Called from the identity setters (see the inputs above) — items are created\n * dynamically with these values stamped as static config, so without this a change\n * that arrives after first render wouldn't reach existing bubbles.\n *\n * No-op before the first render (the map is empty), so it's safe to fire during\n * Angular's initial input binding.\n */\n private restampAssistantIdentity(): void {\n for (const entry of this._renderedMessages.values()) {\n if (entry.kind === 'component') {\n this.applyMessageItemFeatureFlags(entry.ref.instance);\n entry.ref.changeDetectorRef.markForCheck();\n }\n }\n }\n\n ngAfterViewChecked() {\n // Mutually exclusive on purpose: scrolling to the bottom would undo a prepend restore.\n if (this._restoreScrollAfterPrepend) {\n this.restoreScrollAfterPrepend();\n this._restoreScrollAfterPrepend = false;\n } else if (this._shouldScrollToBottom) {\n this.scrollToBottom();\n this._shouldScrollToBottom = false;\n }\n // Measure while things are on screen, so an item has a real height recorded before it\n // ever needs a spacer — the plan's \"measure offsetHeight the first time an item is\n // mounted and remember it by key\".\n this.measureMountedItems();\n this.syncScrollListener();\n this.syncOlderObserver();\n this.syncSpacerObserver();\n }\n\n /** The rendered sentinel, read from the DOM so it does not depend on view-query timing. */\n private findSentinelElement(): HTMLElement | null {\n return this.hostRef.nativeElement.querySelector('.transcript-older-sentinel');\n }\n\n /**\n * Whether this instance is actually on screen.\n *\n * `offsetParent` is null for any element in a `display: none` subtree — which is how the\n * chat area parks the message lists of conversations you are not currently looking at.\n */\n private isHostVisible(): boolean {\n const host = this.hostRef.nativeElement;\n return host.offsetParent !== null || getComputedStyle(host).position === 'fixed';\n }\n\n /**\n * Retries {@link syncOlderObserver} on animation frames until a scroller appears.\n *\n * Bounded: after {@link MAX_SCROLL_PARENT_RETRIES} frames it gives up and logs the DOM\n * chain it walked, so a genuine host-layout problem names itself instead of presenting\n * as \"paging silently doesn't work\".\n */\n private scheduleScrollParentRetry(): void {\n if (this._scrollParentRetryHandle !== null) {\n return; // one retry loop at a time\n }\n // A HIDDEN instance can never resolve a scroller: the chat area keeps one message list\n // alive per visited conversation in a DOM cache, and a display:none subtree reports\n // every height as 0, so `scrollHeight > clientHeight` is false all the way up. Keep\n // waiting (it may be shown later) but never burn the retry budget or warn — that noise\n // would point at the wrong instance entirely.\n if (!this.isHostVisible()) {\n this._scrollParentRetryHandle = requestAnimationFrame(() => {\n this._scrollParentRetryHandle = null;\n this.syncOlderObserver();\n });\n return;\n }\n if (this._scrollParentRetries >= MessageListComponent.MAX_SCROLL_PARENT_RETRIES) {\n this.warnNoScrollParentOnce();\n return;\n }\n this._scrollParentRetries++;\n this._scrollParentRetryHandle = requestAnimationFrame(() => {\n this._scrollParentRetryHandle = null;\n this.syncOlderObserver();\n });\n }\n\n /** One-time diagnostic dump of the ancestor chain, so the failure is self-explaining. */\n private warnNoScrollParentOnce(): void {\n if (this._warnedNoScrollParent) {\n return;\n }\n this._warnedNoScrollParent = true;\n\n const chain: Array<Record<string, unknown>> = [];\n let el: HTMLElement | null =\n this.findSentinelElement() ?? this.scrollContainer?.nativeElement ?? null;\n while (el && chain.length < 20) {\n const style = getComputedStyle(el);\n chain.push({\n el: el.className || el.tagName,\n overflowY: style.overflowY,\n scrollHeight: el.scrollHeight,\n clientHeight: el.clientHeight\n });\n el = el.parentElement;\n }\n\n console.warn(\n '[MessageList] \"Earlier messages\" is showing but no scrolling ancestor was found, so '\n + 'older pages cannot auto-load. The host must give the transcript a scrollable container '\n + '(overflow-y: auto AND a bounded height, e.g. min-height: 0 on a flex child). '\n + 'Walked from '\n + (this.olderSentinel ? 'the sentinel' : this.scrollContainer ? 'the list container' : 'NOTHING — both view children are undefined')\n + ':',\n chain\n );\n }\n\n /**\n * The element that ACTUALLY scrolls the transcript.\n *\n * This component's own `.message-list-container` does not scroll: the chat area wraps it\n * in `.chat-messages-container`, and that outer div is the one carrying `min-height: 0`\n * alongside `overflow-y: auto` — the pair a flex child needs before it will scroll instead\n * of growing to fit its content. Targeting the inner div means writing `scrollTop` on an\n * element whose `scrollHeight === clientHeight`, which silently does nothing, and giving\n * an IntersectionObserver a root that never scrolls.\n *\n * Walking up keeps this component agnostic about the host's markup — any consumer that\n * wraps it in its own scroller works the same way.\n */\n private resolveScrollParent(): HTMLElement | null {\n // Host-supplied root wins — no discovery, no timing dependency.\n if (this._scrollRoot?.isConnected) {\n return this._scrollRoot;\n }\n if (this._scrollParent && this._scrollParent.isConnected) {\n return this._scrollParent;\n }\n // Start from the sentinel when it exists: it is the element being observed, so it is\n // guaranteed present exactly when the walk matters. `@ViewChild('scrollContainer')`\n // resolves on Angular's own schedule and can still be undefined here, which would end\n // the walk before it began.\n let el: HTMLElement | null =\n this.findSentinelElement() ?? this.scrollContainer?.nativeElement ?? null;\n while (el) {\n const overflowY = getComputedStyle(el).overflowY;\n if ((overflowY === 'auto' || overflowY === 'scroll') && el.scrollHeight > el.clientHeight) {\n this._scrollParent = el;\n return el;\n }\n el = el.parentElement;\n }\n return null; // nothing overflows yet — short conversation, nothing to scroll\n }\n\n /**\n * Holds the user's reading position after older content is spliced in above.\n *\n * `scrollTop` is a pixel offset from the top, so inserting content above silently shifts\n * everything down — the user ends up looking at messages they never scrolled to. Adding\n * the height delta puts the same message back under their eyes.\n */\n private restoreScrollAfterPrepend(): void {\n const el = this.resolveScrollParent();\n if (!el) {\n return;\n }\n const delta = el.scrollHeight - this._heightBeforePrepend;\n if (delta > 0) {\n el.scrollTop = el.scrollTop + delta;\n }\n }\n\n /**\n * True when the environment provides `IntersectionObserver`.\n *\n * False under SSR and in the unit-test projects. Both observer syncs are reached a\n * microtask late (see the `HasMoreAbove` setter), so a spec that stubs the global and\n * restores it synchronously has already restored it by the time the sync runs — the\n * constructor call then throws inside a `.then()` with no catch, which surfaces as an\n * unhandled rejection rather than a test failure and fails the run despite every\n * assertion passing.\n */\n private get canObserve(): boolean {\n return typeof IntersectionObserver !== 'undefined';\n }\n\n /**\n * Keeps the IntersectionObserver attached to the current sentinel element.\n *\n * The sentinel lives inside `@if (HasMoreAbove)`, so it is created and destroyed as the\n * user reaches the top of the loaded window and as older pages arrive. Runs every checked\n * cycle and is a no-op once attached.\n *\n * Observer-on-sentinel rather than a scroll listener: a fast scroll costs one callback,\n * not one per frame.\n */\n private syncOlderObserver(): void {\n if (!this.canObserve) {\n return;\n }\n if (!this.HasMoreAbove) {\n this._olderObserver?.disconnect();\n this._olderObserver = undefined;\n this._observedSentinel = null;\n this._observedRoot = null;\n return;\n }\n\n // Query the DOM rather than reading `@ViewChild('olderSentinel')`.\n //\n // The sentinel lives inside `@if`, so the view query resolves on Angular's own\n // schedule — and `updateMessages` detaches/reattaches this component's change detector\n // around every render, which makes that schedule hard to reason about. Reading the host\n // element directly is timing-independent: if the div is on the page, we find it.\n const el = this.findSentinelElement();\n if (!el) {\n this.scheduleScrollParentRetry(); // not rendered yet — look again next frame\n return;\n }\n\n // The scroll parent is not resolvable until something actually overflows, which is not\n // true on the first checked cycle. Bailing (rather than observing with a null root)\n // matters: a viewport-rooted observer never sees a sentinel clipped inside a scrolled\n // container, so it would silently never fire.\n const root = this.resolveScrollParent();\n if (!root) {\n // A scroller only becomes findable once its content overflows, which is not true on\n // the tick the sentinel first renders. Retry on animation frames rather than waiting\n // for another change-detection pass — once the list settles there may not be one.\n this.scheduleScrollParentRetry();\n return;\n }\n this._scrollParentRetries = 0;\n\n // Rebuild whenever EITHER end of the relationship changes — `@if` swaps the sentinel\n // element as HasMoreAbove toggles, and the root only becomes known once content\n // overflows. Observing a stale element or a stale root is silent, not loud.\n if (this._olderObserver && this._observedSentinel === el && this._observedRoot === root) {\n return;\n }\n this._olderObserver?.disconnect();\n\n this._olderObserver = new IntersectionObserver(\n entries => {\n // Re-check the flags at fire time: the observer can fire while a load is already\n // running, and LoadOlder's own guard shouldn't be the only thing standing between\n // a fast scroll and a burst of duplicate requests.\n if (entries.some(e => e.isIntersecting) && this.HasMoreAbove && !this.IsLoadingOlder) {\n this.OlderRequested.emit();\n }\n },\n // Root must be the REAL scroller, not this component's own container — an observer\n // rooted on a non-scrolling ancestor reports the sentinel as permanently visible.\n { root, threshold: 0.01 }\n );\n this._olderObserver.observe(el);\n this._observedSentinel = el;\n this._observedRoot = root;\n }\n\n ngOnDestroy() {\n this._olderObserver?.disconnect();\n this._olderObserver = undefined;\n this._spacerObserver?.disconnect();\n this._spacerObserver = undefined;\n if (this._scrollParentRetryHandle !== null) {\n cancelAnimationFrame(this._scrollParentRetryHandle);\n this._scrollParentRetryHandle = null;\n }\n\n // Clean up all dynamically created components AND embedded views (both have destroy()).\n this._renderedMessages.forEach((entry) => {\n if (entry) {\n entry.ref.destroy();\n }\n });\n this._renderedMessages.clear();\n\n if (this.messageContainerRef) {\n this.messageContainerRef.clear();\n }\n }\n\n /**\n * Called when messages array changes\n * Efficiently updates the DOM without re-rendering everything\n */\n @Input()\n set messagesUpdate(messages: MJConversationDetailEntity[]) {\n if (messages && this.messageContainerRef) {\n this.updateMessages(messages);\n }\n }\n\n /**\n * Updates the message list using dynamic component creation\n * Only adds/removes changed messages for optimal performance\n *\n * REALTIME SESSIONS: details stamped with an `AgentSessionID` (turns persisted during\n * a live realtime session) do NOT render as normal chat bubbles. The timeline pass\n * (`BuildConversationTimeline`) collapses each session's stamped rows into ONE session\n * block, rendered as a `RealtimeSessionTimelineCardComponent` at the session's\n * chronological position. Everything else renders exactly as before.\n */\n private updateMessages(messages: MJConversationDetailEntity[]): void {\n // Temporarily detach change detection for performance\n this.cdRef.detach();\n\n try {\n // Build the timeline first — collapses contiguous realtime-session rows\n // into ONE session block per session, leaving normal messages in place.\n // See `BuildConversationTimeline` in `utils/realtime-session-timeline`.\n const timeline = BuildConversationTimeline(messages);\n\n // Remove rendered items (messages AND session blocks) that no longer exist\n const currentKeys = new Set(timeline.map(item => this.getTimelineKey(item)));\n this._renderedMessages.forEach((entry, key) => {\n if (!currentKeys.has(key)) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n });\n\n // Add or update timeline items in chronological order. `renderMessageItem`\n // internally branches on the slot template (messageRenderer) vs the\n // default MessageItemComponent; `renderSessionBlock` always creates a\n // RealtimeSessionTimelineCardComponent.\n // The timeline index is passed through so newly created views land at the RIGHT\n // position. `createComponent` appends by default, which would put prepended older\n // messages at the bottom of the DOM despite being the oldest content.\n // Items far from the viewport are UNMOUNTED and replaced by a height-holding spacer,\n // so paging a long way up leaves a bounded DOM rather than hundreds of live message\n // components. The tail and any in-progress message are always kept.\n const range = this.computeMountedRange(timeline);\n const lastMessageKey = this.findLastMessageKey(timeline);\n for (let i = 0; i < timeline.length; i++) {\n const item = timeline[i];\n const mounted = (i >= range.start && i <= range.end)\n || this.mustStayMounted(item, i, timeline.length);\n\n if (!mounted) {\n this.ensureSpacer(this.getTimelineKey(item), item, i);\n } else if (item.Kind === 'session') {\n this.renderSessionBlock(item.Group, i);\n } else {\n this.renderMessageItem(item.Detail, messages, this.getMessageKey(item.Detail) === lastMessageKey, i);\n }\n }\n\n // Decide where the viewport should end up.\n //\n // A raw `length > previousCount` check cannot tell an append from a prepend — paging\n // older history also grows the array, and treating that as \"someone sent a message\"\n // would snap the user to the newest message every time they scrolled up. Compare the\n // FIRST timeline key instead: if it changed, older content arrived at the head.\n const previousCount = this._previousMessageCount;\n this._previousMessageCount = messages.length;\n\n const firstKey = timeline.length > 0 ? this.getTimelineKey(timeline[0]) : null;\n const prepended = this._previousFirstKey !== null\n && firstKey !== null\n && firstKey !== this._previousFirstKey;\n this._previousFirstKey = firstKey;\n\n if (prepended) {\n this._restoreScrollAfterPrepend = true;\n } else if (messages.length > previousCount) {\n this._shouldScrollToBottom = true;\n }\n } finally {\n // Re-attach change detection\n this.cdRef.reattach();\n this.cdRef.detectChanges();\n }\n }\n\n /**\n * The span of timeline indices that stay mounted.\n *\n * Follows the tail on first paint and whenever nothing measurable is on screen. Once items\n * are rendered, the span is centred on what the reader is actually looking at — measured\n * from scroll position, plus {@link MessageListComponent.MOUNT_BUFFER} either side — so\n * scrolling back does not collapse the window to the newest messages on the next render.\n *\n * (An earlier design pinned the top of the span with a remembered key instead. It was\n * replaced by the measurement below for the reason that comment explains, and the key no\n * longer exists.)\n */\n private computeMountedRange(\n timeline: ConversationTimelineItem<MJConversationDetailEntity>[]\n ): { start: number; end: number } {\n const lastIndex = timeline.length - 1;\n const span = DEFAULT_TRANSCRIPT_PAGE_SIZE + MessageListComponent.MOUNT_BUFFER * 2;\n const tailRange = { start: Math.max(0, timeline.length - span), end: lastIndex };\n\n const root = this.resolveScrollParent();\n if (!root || this._renderedMessages.size === 0) {\n return tailRange; // first paint — follow the tail\n }\n\n // Derived from SCROLL POSITION, which nothing in the render loop feeds back into.\n //\n // Reacting to spacer intersections instead is circular: a spacer's height is an\n // estimate, so where it sits decides what is visible, which decides which spacers fire,\n // which changes what is mounted, which changes heights. That loop is what made the\n // transcript replay the same region; constraining it to one direction only traded the\n // ping-pong for dead zones that never remounted.\n const rootTop = root.getBoundingClientRect().top;\n const viewportHeight = root.clientHeight;\n let firstVisible = -1;\n let lastVisible = -1;\n\n for (let i = 0; i < timeline.length; i++) {\n const node = this.nodeForKey(this.getTimelineKey(timeline[i]));\n if (!node) {\n continue;\n }\n const rect = node.getBoundingClientRect();\n const top = rect.top - rootTop;\n const bottom = top + rect.height;\n if (bottom > 0 && firstVisible < 0) {\n firstVisible = i;\n }\n if (top < viewportHeight) {\n lastVisible = i;\n }\n }\n if (firstVisible < 0 || lastVisible < 0) {\n return tailRange;\n }\n\n return {\n start: Math.max(0, firstVisible - MessageListComponent.MOUNT_BUFFER),\n end: Math.min(lastIndex, lastVisible + MessageListComponent.MOUNT_BUFFER)\n };\n }\n\n /** The rendered DOM node for a timeline key, whatever kind of entry backs it. */\n private nodeForKey(key: string): HTMLElement | undefined {\n const entry = this._renderedMessages.get(key);\n if (!entry) {\n return undefined;\n }\n return entry.kind === 'embedded' || entry.kind === 'spacer'\n ? (entry.ref.rootNodes[0] as HTMLElement | undefined)\n : (entry.ref.location.nativeElement as HTMLElement | undefined);\n }\n\n /**\n * Items that must never be unmounted regardless of position.\n *\n * The tail carries streaming output, `isLastMessage` affordances and suggested\n * responses; an in-progress message is mid-stream and would lose its live state.\n */\n private mustStayMounted(\n item: ConversationTimelineItem<MJConversationDetailEntity>,\n index: number,\n timelineLength: number\n ): boolean {\n if (index === timelineLength - 1) {\n return true;\n }\n return item.Kind === 'message' && item.Detail.Status === 'In-Progress';\n }\n\n /**\n * Records what an entry occupied on screen, so its spacer holds exactly that much space.\n *\n * Called immediately BEFORE destroying — afterwards the node is gone. A wrong height here\n * is the failure mode that makes scrolling jump, which is the whole thing spacers exist\n * to prevent.\n */\n private rememberHeight(key: string, entry: RenderedMessageEntry): void {\n const node = entry.kind === 'embedded' || entry.kind === 'spacer'\n ? (entry.ref.rootNodes[0] as HTMLElement | undefined)\n : (entry.ref.location.nativeElement as HTMLElement | undefined);\n const height = node?.offsetHeight ?? 0;\n if (height > 0) {\n this._measuredHeights.set(key, height);\n }\n }\n\n /** Measured height when we have one, else a kind-appropriate estimate. */\n private heightFor(key: string, item: ConversationTimelineItem<MJConversationDetailEntity>): number {\n const measured = this._measuredHeights.get(key);\n if (measured !== undefined) {\n return measured;\n }\n return item.Kind === 'session'\n ? MessageListComponent.ESTIMATED_SESSION_HEIGHT\n : MessageListComponent.ESTIMATED_MESSAGE_HEIGHT;\n }\n\n /**\n * Measures every currently-mounted item.\n *\n * Runs each checked cycle so an item has a real height recorded BEFORE it scrolls far\n * enough to be unmounted — otherwise its first spacer is always a guess.\n */\n private measureMountedItems(): void {\n this._renderedMessages.forEach((entry, key) => {\n if (entry.kind === 'spacer') {\n return;\n }\n const node = entry.kind === 'embedded'\n ? (entry.ref.rootNodes[0] as HTMLElement | undefined)\n : (entry.ref.location.nativeElement as HTMLElement | undefined);\n const height = node?.offsetHeight ?? 0;\n if (height > 0) {\n this._measuredHeights.set(key, height);\n }\n });\n }\n\n\n /**\n * Replaces a mounted item with a height-holding spacer, or leaves an existing spacer\n * alone. Stored under the item's own timeline key so {@link updateMessages}'s\n * remove-stale pass and the remount path both find it.\n */\n private ensureSpacer(\n key: string,\n item: ConversationTimelineItem<MJConversationDetailEntity>,\n timelineIndex: number\n ): void {\n const existing = this._renderedMessages.get(key);\n if (existing?.kind === 'spacer') {\n return;\n }\n if (!this.spacerTemplate) {\n // Staying mounted is the safe choice, but silently doing so means the transcript\n // grows without bound and nothing says why. Report it once.\n if (!this._warnedNoSpacerTemplate) {\n this._warnedNoSpacerTemplate = true;\n console.warn(\n '[MessageList] spacerTemplate did not resolve, so off-screen messages cannot be '\n + 'unmounted and the DOM will grow with every page loaded.'\n );\n }\n return;\n }\n if (existing) {\n this.rememberHeight(key, existing);\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n const viewRef = this.messageContainerRef.createEmbeddedView<SpacerContext>(\n this.spacerTemplate,\n { height: this.heightFor(key, item) },\n { index: timelineIndex }\n );\n this._renderedMessages.set(key, { kind: 'spacer', ref: viewRef });\n }\n\n /**\n * Re-evaluates the mounted window as the user scrolls.\n *\n * Attached once to the host's scroller. Coalesced onto an animation frame so a fast scroll\n * costs one re-render per frame rather than one per event, and skipped entirely when the\n * window has not actually moved.\n */\n private syncScrollListener(): void {\n const root = this.resolveScrollParent();\n if (!root || root === this._scrollListenerTarget) {\n return;\n }\n this.detachScrollListener();\n this._scrollListenerTarget = root;\n this._onScroll = () => {\n if (this._scrollFrame !== null) {\n return;\n }\n this._scrollFrame = requestAnimationFrame(() => {\n this._scrollFrame = null;\n if (this.messages?.length) {\n this.updateMessages(this.messages);\n }\n });\n };\n root.addEventListener('scroll', this._onScroll, { passive: true });\n }\n\n private detachScrollListener(): void {\n if (this._scrollListenerTarget && this._onScroll) {\n this._scrollListenerTarget.removeEventListener('scroll', this._onScroll);\n }\n this._scrollListenerTarget = null;\n this._onScroll = null;\n if (this._scrollFrame !== null) {\n cancelAnimationFrame(this._scrollFrame);\n this._scrollFrame = null;\n }\n }\n\n /**\n * Watches the current spacers so scrolling back toward one remounts it.\n *\n * Rebuilt on every render because spacers come and go. Remounting reads from `messages`,\n * which is already in memory — this never triggers a fetch.\n */\n private syncSpacerObserver(): void {\n if (!this.canObserve) {\n return;\n }\n const root = this.resolveScrollParent();\n if (!root) {\n this._spacerObserver?.disconnect();\n this._spacerObserver = undefined;\n this._observedSpacerKeys = '';\n return;\n }\n const spacers: Array<{ key: string; el: HTMLElement }> = [];\n this._renderedMessages.forEach((entry, key) => {\n if (entry.kind === 'spacer') {\n const el = entry.ref.rootNodes[0] as HTMLElement | undefined;\n if (el) {\n spacers.push({ key, el });\n }\n }\n });\n if (spacers.length === 0) {\n this._spacerObserver?.disconnect();\n this._spacerObserver = undefined;\n this._observedSpacerKeys = '';\n return;\n }\n\n // Rebuild ONLY when the spacer set actually changes.\n //\n // This runs every checked cycle, and a fresh IntersectionObserver delivers an initial\n // callback for everything it observes. Rebuilding unconditionally therefore re-fired\n // remountAround on every change-detection pass, which re-rendered, which triggered\n // another pass — the transcript visibly stuck, replaying the same region.\n const signature = spacers.map(s => s.key).sort().join('|');\n if (this._spacerObserver && signature === this._observedSpacerKeys) {\n return;\n }\n this._spacerObserver?.disconnect();\n this._observedSpacerKeys = signature;\n\n this._spacerObserver = new IntersectionObserver(\n entries => {\n const hit = entries.find(e => e.isIntersecting);\n if (!hit) {\n return;\n }\n // The range is computed from scroll position; a spacer coming into view just means\n // it is time to recompute. No key is threaded through, so there is no feedback loop.\n if (this.messages?.length) {\n this.updateMessages(this.messages);\n }\n },\n { root, threshold: 0.01 }\n );\n for (const s of spacers) {\n this._spacerObserver.observe(s.el);\n }\n }\n\n\n /** Stable render key for a timeline item — message ID, or a prefixed session key for session blocks. */\n private getTimelineKey(item: ConversationTimelineItem<MJConversationDetailEntity>): string {\n return item.Kind === 'session' ? this.getSessionKey(item.Group.SessionID) : this.getMessageKey(item.Detail);\n }\n\n /** Render key for a session block (case-insensitive on the session id; prefixed so it can't collide with message IDs). */\n private getSessionKey(sessionId: string): string {\n return `session:${NormalizeUUID(sessionId)}`;\n }\n\n /** The render key of the LAST normal message item in the timeline (drives `isLastMessage`), or null when none. */\n private findLastMessageKey(timeline: ConversationTimelineItem<MJConversationDetailEntity>[]): string | null {\n for (let i = timeline.length - 1; i >= 0; i--) {\n const item = timeline[i];\n if (item.Kind === 'message') {\n return this.getMessageKey(item.Detail);\n }\n }\n return null;\n }\n\n /**\n * Creates or updates the ONE timeline card a realtime session collapses to.\n * Click/Open on the card bubbles up via {@link realtimeSessionOpenRequested} so the\n * chat area can host the SESSION REVIEW overlay for it.\n */\n private renderSessionBlock(group: RealtimeSessionTimelineGroup, timelineIndex: number): void {\n const key = this.getSessionKey(group.SessionID);\n const meta = this.sessionMetaMap.get(NormalizeUUID(group.SessionID)) ?? null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'realtime-session') {\n // Update existing card in place.\n const instance = existing.ref.instance;\n instance.Group = group;\n instance.Meta = meta;\n existing.ref.changeDetectorRef.markForCheck();\n return;\n }\n\n // Different kind at this key (e.g. mode changed) — drop the old entry, fall through to create.\n if (existing) {\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n const componentRef = this.messageContainerRef.createComponent(\n RealtimeSessionTimelineCardComponent,\n { index: timelineIndex }\n );\n componentRef.instance.Group = group;\n componentRef.instance.Meta = meta;\n componentRef.instance.UserName = this.currentUser?.Name || 'You';\n componentRef.instance.OpenRequested.subscribe((sessionId: string) => this.realtimeSessionOpenRequested.emit(sessionId));\n this._renderedMessages.set(key, { kind: 'realtime-session', ref: componentRef });\n }\n\n /**\n * Creates or updates one normal chat message item. Routes to the\n * consumer-projected `messageRenderer` slot template (EmbeddedViewRef path)\n * when present, otherwise falls back to the default `MessageItemComponent`\n * dynamic-component path. Both paths flow through the shared\n * `createRenderedEntry` / `updateMessageItemInstance` helpers.\n */\n private renderMessageItem(\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n isLastMessage: boolean,\n timelineIndex: number\n ): void {\n const key = this.getMessageKey(message);\n // `index` is only used for the `isLastMessage` heuristic inside\n // updateMessageItemInstance — synthesize a value that produces the right\n // boolean (last index when `isLastMessage` is true, else 0 — any non-last\n // index works since it just affects that one comparison).\n const index = isLastMessage ? messages.length - 1 : 0;\n const useCustomRenderer = this.messageRendererTemplate !== null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'embedded' && useCustomRenderer) {\n // Update existing embedded view from messageRenderer slot\n existing.ref.context.$implicit = message;\n existing.ref.context.message = message;\n existing.ref.markForCheck();\n return;\n }\n if (existing && existing.kind === 'component' && !useCustomRenderer) {\n // Update existing MessageItemComponent in place\n this.updateMessageItemInstance(existing.ref, message, messages, index);\n return;\n }\n if (existing) {\n // Rendering kind changed (e.g. component↔embedded, or a session block was\n // overwritten with a message). Destroy + recreate.\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n this.createRenderedEntry(message, messages, index, key, useCustomRenderer, timelineIndex);\n }\n\n /**\n * Updates an existing `MessageItemComponent` in place — used on the default\n * (non-custom-renderer) path when a message's status / artifacts / agent-run /\n * etc. changes mid-stream.\n */\n private updateMessageItemInstance(\n ref: ComponentRef<MessageItemComponent>,\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number\n ): void {\n const instance = ref.instance;\n const previousMessage = instance.message;\n\n instance.message = message;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n this.applyMessageItemFeatureFlags(instance);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n // After the inputs above, for the same reason as the create path: this can force a\n // synchronous child pass, which would otherwise paint the previous refresh's agent run,\n // ratings and attachments.\n this.applyArtifactsToInstance(instance, message.ID, ref.changeDetectorRef);\n\n // Status change requires explicit markForCheck on the OnPush dynamic child.\n if (previousMessage && previousMessage.Status !== message.Status) {\n ref.changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * Forward the host-level per-message feature gates onto a MessageItemComponent\n * instance. These are static host config (not per-message data), so the same\n * values apply to every message; applied on both the create and in-place-update\n * paths so a mid-session rebind stays consistent.\n */\n private applyMessageItemFeatureFlags(instance: MessageItemComponent): void {\n instance.showAgentRunDetails = this.showAgentRunDetails;\n instance.showReactions = this.showReactions;\n instance.showMessageRating = this.showMessageRating;\n instance.allowPinning = this.allowPinning;\n instance.allowMessageEdit = this.allowMessageEdit;\n instance.allowMessageDelete = this.allowMessageDelete;\n instance.assistantDisplayName = this.assistantDisplayName;\n instance.assistantAvatarUrl = this.assistantAvatarUrl;\n }\n\n /**\n * Creates a new rendered entry — either a `MessageItemComponent` (default path)\n * or an `EmbeddedViewRef` from the consumer's `messageRenderer` slot template.\n * Stores the entry in `_renderedMessages` and stamps a back-reference on the\n * message entity.\n */\n private createRenderedEntry(\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number,\n key: string,\n useCustomRenderer: boolean,\n timelineIndex: number\n ): void {\n if (useCustomRenderer && this.messageRendererTemplate) {\n // The slot directive carries TemplateRef<unknown>; assert the contract here\n // (consumers' `let-message` bindings consume the message context shape below).\n const template = this.messageRendererTemplate as TemplateRef<MessageRendererContext>;\n const viewRef = this.messageContainerRef.createEmbeddedView<MessageRendererContext>(\n template,\n { $implicit: message, message },\n { index: timelineIndex }\n );\n this._renderedMessages.set(key, { kind: 'embedded', ref: viewRef });\n // Stamp back-ref for parity with the component path.\n (message as unknown as { _viewRef?: EmbeddedViewRef<MessageRendererContext> })._viewRef = viewRef;\n return;\n }\n\n const componentRef = this.messageContainerRef.createComponent(MessageItemComponent, { index: timelineIndex });\n const instance = componentRef.instance;\n\n instance.message = message;\n instance.conversation = this.conversation;\n instance.currentUser = this.currentUser;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n this.applyMessageItemFeatureFlags(instance);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n instance.editClicked.subscribe((msg: MJConversationDetailEntity) => this.editMessage.emit(msg));\n instance.deleteClicked.subscribe((msg: MJConversationDetailEntity) => this.deleteMessage.emit(msg));\n instance.retryClicked.subscribe((msg: MJConversationDetailEntity) => this.retryMessage.emit(msg));\n instance.testFeedbackClicked.subscribe((msg: MJConversationDetailEntity) => this.testFeedbackMessage.emit(msg));\n instance.artifactClicked.subscribe((data: {artifactId: string; versionId?: string}) => this.artifactClicked.emit(data));\n instance.messageEdited.subscribe((msg: MJConversationDetailEntity) => this.messageEdited.emit(msg));\n instance.openEntityRecord.subscribe((data: {entityName: string; compositeKey: CompositeKey}) => this.openEntityRecord.emit(data));\n instance.suggestedResponseSelected.subscribe((data: {text: string; customInput?: string}) => this.suggestedResponseSelected.emit(data));\n instance.attachmentClicked.subscribe((attachment: MessageAttachment) => this.attachmentClicked.emit(attachment));\n instance.diagnosticRequested.subscribe((messageId: string) => this.diagnosticRequested.emit(messageId));\n instance.messagePinToggled.subscribe((msg: MJConversationDetailEntity) => this.messagePinToggled.emit(msg));\n instance.beforeResponseFormSubmitted.subscribe((e: BeforeResponseFormSubmittedEventArgs) => this.beforeResponseFormSubmitted.emit(e));\n instance.afterResponseFormSubmitted.subscribe((e: AfterResponseFormSubmittedEventArgs) => this.afterResponseFormSubmitted.emit(e));\n\n if (instance.artifactActionPerformed) {\n instance.artifactActionPerformed.subscribe((data: {action: string; artifactId: string}) => {\n // Parent can handle artifact actions (save, fork, history, share)\n console.log('Artifact action:', data);\n });\n }\n\n // LAST, deliberately. It publishes the pending-artifact list and forces the child's first\n // change-detection pass, which runs ngOnInit/ngAfterViewInit — so agentRun, ratings,\n // attachments and every output subscription above must already be in place. Called earlier,\n // ngAfterViewInit saw agentRun === null and never started the run-duration timer, and the\n // first paint showed the rating control on an already-rated message.\n this.applyArtifactsToInstance(instance, message.ID, componentRef.changeDetectorRef);\n\n this._renderedMessages.set(key, { kind: 'component', ref: componentRef });\n // Preserve the existing back-ref pattern from the skip-chat performance design.\n (message as unknown as { _componentRef?: ComponentRef<MessageItemComponent> })._componentRef = componentRef;\n }\n\n /**\n * Resolves the DISTINCT artifacts for a message (one entry per artifactId at its\n * latest version), lazy-loads them all, and applies them to the rendered\n * message-item. Loads in the background so the UI never blocks.\n *\n * WHY WE SURFACE THEM ALL (design rationale — see PR discussion w/ Pranav & Ethan):\n * A single message can legitimately carry more than one DISTINCT artifact — e.g. a\n * research report PLUS a *standalone* generated infographic. This is deliberately\n * NOT in conflict with the server-side consolidation in AgentRunner\n * (Pranav, 5664b86: \"keep the report's embedded image in the report, not as a\n * duplicate artifact\"): that logic only suppresses media that is *embedded inline*\n * (base64) in another artifact's payload — a true duplicate. Genuinely standalone\n * sibling artifacts (the report uses SVG charts; the infographic is a separate JPEG)\n * are correctly kept as separate artifacts, and the UI must show every one of them.\n *\n * The earlier `artifactList[length - 1]` (\"show only the most recent\") approach\n * (EL-BC, 95492622) assumed consolidation always left exactly one artifact per\n * message; when it legitimately leaves two, that silently hid the report behind the\n * image. Grouping by artifactId (latest version each) shows all distinct artifacts\n * while still collapsing multiple *versions* of the same artifact to one card.\n */\n private applyArtifactsToInstance(\n instance: MessageItemComponent,\n messageId: string,\n childCdRef: ChangeDetectorRef\n ): void {\n const infos = this.resolveDistinctArtifacts(messageId);\n // Advanced on EVERY path, the clear included: a load that settles later compares against this,\n // and a stale response must not repaint an artifact the map has since dropped.\n const generation = (this.artifactLoadGeneration.get(instance) ?? 0) + 1;\n this.artifactLoadGeneration.set(instance, generation);\n\n // Only artifacts that still need a round trip. LazyArtifactInfo.isLoaded answers exactly this,\n // so an artifact already in hand is never announced — announcing everything and filtering\n // downstream re-flashed a placeholder above a rendered card once a second.\n const pending = infos.filter(info => !info.isLoaded);\n const dirty = this.publishPendingArtifacts(instance, infos.length === 0, pending);\n\n // zone.js 0.15: the parent's detectChanges does not reach a dynamically created child.\n if (dirty && !this.isViewDestroyed(childCdRef)) {\n childCdRef.detectChanges();\n }\n if (infos.length > 0) {\n void this.loadArtifactsInto(instance, infos, generation, childCdRef);\n }\n }\n\n /**\n * Publishes what the message should show right now, returning whether anything changed.\n * Clearing is the branch with something to erase, so it counts as dirty whenever the message\n * previously had a card or a placeholder.\n */\n private publishPendingArtifacts(\n instance: MessageItemComponent,\n clear: boolean,\n pending: readonly MessagePendingArtifactRef[]\n ): boolean {\n if (clear) {\n const hadSomething = instance.hasArtifact || instance.pendingArtifacts.length > 0;\n instance.artifacts = [];\n instance.artifact = undefined;\n instance.artifactVersion = undefined;\n instance.pendingArtifacts = [];\n return hadSomething;\n }\n const changed =\n instance.pendingArtifacts.length !== pending.length ||\n pending.some((p, i) => instance.pendingArtifacts[i]?.artifactId !== p.artifactId);\n instance.pendingArtifacts = pending;\n return changed;\n }\n\n /**\n * Loads the artifact and version rows, then hands them to the message — unless a newer refresh\n * has taken over or the view is gone (scrolled out of the timeline, conversation switched), in\n * which case the result is dropped: detectChanges on a destroyed view throws.\n */\n private async loadArtifactsInto(\n instance: MessageItemComponent,\n infos: readonly LazyArtifactInfo[],\n generation: number,\n childCdRef: ChangeDetectorRef\n ): Promise<void> {\n let refs: MessageArtifactRef[] = [];\n try {\n refs = await Promise.all(\n infos.map(info =>\n Promise.all([info.getArtifact(), info.getVersion()]).then(([artifact, version]) => ({ artifact, version }))\n )\n );\n } catch (err) {\n // Fall through with no refs: the placeholders still have to clear, or the message keeps a\n // permanent loading row.\n console.error('Failed to lazy-load artifacts:', err);\n }\n if (this.artifactLoadGeneration.get(instance) !== generation || this.isViewDestroyed(childCdRef)) {\n return;\n }\n if (refs.length > 0) {\n instance.artifacts = refs;\n // Keep the legacy single inputs pointed at the first entry for back-compat.\n instance.artifact = refs[0]?.artifact;\n instance.artifactVersion = refs[0]?.version;\n }\n instance.pendingArtifacts = [];\n childCdRef.detectChanges();\n this.cdRef.detectChanges();\n }\n\n /** Has this child view been destroyed? `ViewRef` declares `destroyed` non-optionally. */\n private isViewDestroyed(ref: ChangeDetectorRef): boolean {\n return (ref as ViewRef).destroyed;\n }\n\n /**\n * Groups a message's artifact list by artifactId, keeping the highest version of\n * each. Multiple versions of the SAME artifact collapse to one card (latest wins),\n * while genuinely distinct artifacts are all retained.\n */\n private resolveDistinctArtifacts(messageId: string): LazyArtifactInfo[] {\n const list = this.artifactMap.get(messageId);\n if (!list || list.length === 0) {\n return [];\n }\n return selectDistinctLatestArtifacts(list);\n }\n\n /**\n * Generates a unique key for a message\n * Uses ID if available, otherwise uses a temporary key\n */\n private getMessageKey(message: MJConversationDetailEntity): string {\n return message.ID && message.ID.length > 0\n ? message.ID\n : `temp_${message.__mj_CreatedAt?.getTime() || Date.now()}`;\n }\n\n /**\n * Determines whether to show the date filter dropdown\n * Only show if conversation is long and spans multiple days\n */\n private updateDateFilterVisibility(): void {\n // `messages` is the loaded WINDOW, not the conversation. The 20-message / 3-day heuristic\n // below reads it as if it were full history, so under windowing a long multi-week thread\n // opens with ~10 items, fails the length check, and never offers date navigation at all —\n // the one case where it is most useful. `HasMoreAbove` is the only windowing-safe signal\n // that more conversation exists above, so it short-circuits the heuristic.\n if (this.HasMoreAbove) {\n this.shouldShowDateFilter = true;\n return;\n }\n if (!this.messages || this.messages.length < 20) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n // Check if messages span more than 2 days\n const dates = this.messages\n .map(m => m.__mj_CreatedAt)\n .filter(d => d != null)\n .map(d => new Date(d!).setHours(0, 0, 0, 0));\n\n if (dates.length === 0) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n const uniqueDates = new Set(dates);\n const daySpan = uniqueDates.size;\n\n // Show filter if conversation has 20+ messages and spans 3+ days\n this.shouldShowDateFilter = daySpan >= 3;\n }\n\n /**\n * Scrolls the message list to the bottom\n */\n private scrollToBottom(): void {\n if (this.scrollContainer && this.scrollContainer.nativeElement) {\n Promise.resolve().then(() => {\n const element = this.scrollContainer.nativeElement;\n element.scrollTop = element.scrollHeight;\n });\n }\n }\n\n /**\n * Removes a message from the rendered list\n * Called externally when a message is deleted\n */\n public removeMessage(message: MJConversationDetailEntity): void {\n const key = this.getMessageKey(message);\n const entry = this._renderedMessages.get(key);\n if (entry) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n }\n}","<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…\" 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>"]}
|
|
1
|
+
{"version":3,"file":"message-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/message-list.component.ts","../../../../src/lib/components/message/message-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n HostBinding,\n EventEmitter,\n ViewChild,\n ViewContainerRef,\n OnInit,\n OnDestroy,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ElementRef,\n AfterViewInit,\n AfterViewChecked,\n ComponentRef,\n EmbeddedViewRef,\n ViewRef,\n TemplateRef\n} from '@angular/core';\nimport { MJConversationDetailEntity, MJConversationEntity, RatingJSON } from '@memberjunction/core-entities';\nimport { UserInfo, CompositeKey } from '@memberjunction/core';\nimport { NormalizeUUID, UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MessageItemComponent, MessageAttachment, MessageArtifactRef, MessagePendingArtifactRef } from './message-item.component';\nimport {\n BeforeResponseFormSubmittedEventArgs,\n AfterResponseFormSubmittedEventArgs,\n} from '../../events/chat-events';\nimport { RealtimeSessionTimelineCardComponent } from '../realtime/realtime-session-timeline-card.component';\nimport { LazyArtifactInfo } from '../../models/lazy-artifact-info';\nimport { SelectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';\nimport {\n BuildConversationTimeline,\n ConversationTimelineItem,\n RealtimeSessionTimelineGroup,\n RealtimeSessionTimelineMeta\n} from '../../utils/realtime-session-timeline';\nimport { MJAIAgentRunEntityExtended } from '@memberjunction/ai-core-plus';\nimport { DEFAULT_TRANSCRIPT_PAGE_SIZE } from '../../utils/conversation-detail-window';\nimport {\n ResolveDateJumpTarget,\n type DateJumpPeriod,\n type DateJumpOutcome\n} from '../../utils/date-jump';\n\n/** Context handed to the `messageRenderer` slot template per message. */\ninterface MessageRendererContext {\n $implicit: MJConversationDetailEntity;\n message: MJConversationDetailEntity;\n}\n\n/**\n * One per rendered message in the list. Three paths can produce an entry:\n * - `component` — the default `MessageItemComponent` (single message).\n * - `embedded` — an `EmbeddedViewRef` from the consumer's\n * `messageRenderer` slot template (full per-message\n * replacement, PR 2c slot system).\n * - `realtime-session` — a `RealtimeSessionTimelineCardComponent` collapsing\n * an entire past realtime session into one timeline\n * card (PR #2787 co-agent timeline). The grouping pass\n * (`BuildConversationTimeline`) emits these alongside\n * normal messages — see the timeline utility for the\n * rules.\n *\n * Discriminated by the `kind` tag for ergonomic narrowing.\n */\ntype RenderedMessageEntry =\n | { kind: 'component'; ref: ComponentRef<MessageItemComponent> }\n | { kind: 'embedded'; ref: EmbeddedViewRef<MessageRendererContext> }\n | { kind: 'realtime-session'; ref: ComponentRef<RealtimeSessionTimelineCardComponent> }\n /**\n * A timeline item that has been UNMOUNTED to keep the DOM bounded — replaced by a\n * fixed-height div so the scroll range is unchanged. Stored under the item's own\n * timeline key so it can be swapped back for the real view on scroll-back.\n */\n | { kind: 'spacer'; ref: EmbeddedViewRef<SpacerContext> };\n\n/** Context for the spacer template — the height the unmounted item occupied. */\ninterface SpacerContext {\n height: number;\n}\n\n/**\n * Container component for displaying a list of messages\n * Uses dynamic component creation (like skip-chat) to avoid Angular binding overhead\n * This dramatically improves performance when messages are added/removed\n */\n/** Dropdown label per period. Kept beside the guard so a new period cannot render blank. */\nconst DATE_JUMP_LABELS: Record<DateJumpPeriod, string> = {\n 'today': 'Today',\n 'yesterday': 'Yesterday',\n 'last-week': 'Last week',\n 'last-month': 'Last month'\n};\n\n/** Narrows the template's string to the period union — the template cannot type its own literals. */\nfunction isDateJumpPeriod(value: string): value is DateJumpPeriod {\n return Object.prototype.hasOwnProperty.call(DATE_JUMP_LABELS, value);\n}\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-message-list',\n templateUrl: './message-list.component.html',\n styleUrls: ['./message-list.component.css']\n})\nexport class MessageListComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit, AfterViewChecked {\n @Input() public messages: MJConversationDetailEntity[] = [];\n @Input() public Conversation!: MJConversationEntity | null;\n\n /** @deprecated Use {@link Conversation}. */\n @Input() public set conversation(value: MJConversationEntity | null) {\n this.Conversation = value;\n }\n /** @deprecated Use {@link Conversation}. */\n public get conversation(): MJConversationEntity | null {\n return this.Conversation;\n }\n @Input() public CurrentUser!: UserInfo;\n\n /** @deprecated Use {@link CurrentUser}. */\n @Input() public set currentUser(value: UserInfo) {\n this.CurrentUser = value;\n }\n /** @deprecated Use {@link CurrentUser}. */\n public get currentUser(): UserInfo {\n return this.CurrentUser;\n }\n @Input() public IsProcessing: boolean = false;\n\n /** @deprecated Use {@link IsProcessing}. */\n @Input() public set isProcessing(value: boolean) {\n this.IsProcessing = value;\n }\n /** @deprecated Use {@link IsProcessing}. */\n public get isProcessing(): boolean {\n return this.IsProcessing;\n }\n /** Whether the built-in \"No messages yet\" filler renders for empty conversations. Hosts with their own empty-state chrome set false. */\n @Input() public ShowEmptyFill: boolean = true;\n\n /** @deprecated Use {@link ShowEmptyFill}. */\n @Input() public set showEmptyFill(value: boolean) {\n this.ShowEmptyFill = value;\n }\n /** @deprecated Use {@link ShowEmptyFill}. */\n public get showEmptyFill(): boolean {\n return this.ShowEmptyFill;\n }\n /** Whether the sticky date header + jump-to-date dropdown render. */\n @Input() public ShowDateNavigation: boolean = true;\n\n /** @deprecated Use {@link ShowDateNavigation}. */\n @Input() public set showDateNavigation(value: boolean) {\n this.ShowDateNavigation = value;\n }\n /** @deprecated Use {@link ShowDateNavigation}. */\n public get showDateNavigation(): boolean {\n return this.ShowDateNavigation;\n }\n // Per-message feature gates — forwarded onto each MessageItemComponent instance\n // (see applyMessageItemFeatureFlags). All default true.\n @Input() public ShowAgentRunDetails: boolean = true;\n\n /** @deprecated Use {@link ShowAgentRunDetails}. */\n @Input() public set showAgentRunDetails(value: boolean) {\n this.ShowAgentRunDetails = value;\n }\n /** @deprecated Use {@link ShowAgentRunDetails}. */\n public get showAgentRunDetails(): boolean {\n return this.ShowAgentRunDetails;\n }\n @Input() public ShowReactions: boolean = true;\n\n /** @deprecated Use {@link ShowReactions}. */\n @Input() public set showReactions(value: boolean) {\n this.ShowReactions = value;\n }\n /** @deprecated Use {@link ShowReactions}. */\n public get showReactions(): boolean {\n return this.ShowReactions;\n }\n @Input() public ShowMessageRating: boolean = true;\n\n /** @deprecated Use {@link ShowMessageRating}. */\n @Input() public set showMessageRating(value: boolean) {\n this.ShowMessageRating = value;\n }\n /** @deprecated Use {@link ShowMessageRating}. */\n public get showMessageRating(): boolean {\n return this.ShowMessageRating;\n }\n @Input() public AllowPinning: boolean = true;\n\n /** @deprecated Use {@link AllowPinning}. */\n @Input() public set allowPinning(value: boolean) {\n this.AllowPinning = value;\n }\n /** @deprecated Use {@link AllowPinning}. */\n public get allowPinning(): boolean {\n return this.AllowPinning;\n }\n @Input() public AllowMessageEdit: boolean = true;\n\n /** @deprecated Use {@link AllowMessageEdit}. */\n @Input() public set allowMessageEdit(value: boolean) {\n this.AllowMessageEdit = value;\n }\n /** @deprecated Use {@link AllowMessageEdit}. */\n public get allowMessageEdit(): boolean {\n return this.AllowMessageEdit;\n }\n @Input() public AllowMessageDelete: boolean = true;\n\n /** @deprecated Use {@link AllowMessageDelete}. */\n @Input() public set allowMessageDelete(value: boolean) {\n this.AllowMessageDelete = value;\n }\n /** @deprecated Use {@link AllowMessageDelete}. */\n public get allowMessageDelete(): boolean {\n return this.AllowMessageDelete;\n }\n\n // ── Windowed-transcript paging state ────────────────────────────────────────\n // The list renders only the LOADED window, not the whole conversation. These two\n // describe what lies above it. Unused until the Phase 5 sentinel lands; wired now so\n // the host binding is in place and the component's contract is stable.\n\n /**\n * True when older pages remain above the loaded window.\n *\n * Setter rather than a plain input: flipping this creates or destroys the sentinel via\n * `@if`, and the observer has to be re-pointed at the new element. Relying on an ambient\n * `ngAfterViewChecked` tick to notice is fragile — once the list settles there may not be\n * another one.\n */\n @Input()\n public set HasMoreAbove(value: boolean) {\n if (value === this._hasMoreAbove) {\n return;\n }\n this._hasMoreAbove = value;\n // Gates the date navigator too — see updateDateFilterVisibility. Without this the button\n // would only re-evaluate on a `messages` change, so exhausting history would leave it up.\n this.updateDateFilterVisibility();\n // Deferred: the `@if` has not rendered the sentinel yet at set time.\n Promise.resolve().then(() => this.syncOlderObserver());\n }\n public get HasMoreAbove(): boolean {\n return this._hasMoreAbove;\n }\n private _hasMoreAbove = false;\n\n /** True while an older page is in flight. */\n @Input() public IsLoadingOlder: boolean = false;\n\n /**\n * The host's scrolling element, used as the sentinel observer's root.\n *\n * This component's own container does NOT scroll — hosts wrap it in their own scroller\n * (in the chat area, `.chat-messages-container`, which carries the `min-height: 0` a flex\n * child needs). Passing it in is deterministic; discovering it by walking the DOM depends\n * on layout having settled, which is not knowable from in here.\n *\n * Optional: when omitted the component falls back to walking its ancestors.\n */\n @Input()\n public set ScrollRoot(value: HTMLElement | null | undefined) {\n const next = value ?? null;\n if (next === this._scrollRoot) {\n return;\n }\n this._scrollRoot = next;\n this._scrollParent = next;\n // The root changed, so any live observer is pointed at the wrong element.\n Promise.resolve().then(() => this.syncOlderObserver());\n }\n public get ScrollRoot(): HTMLElement | null {\n return this._scrollRoot;\n }\n private _scrollRoot: HTMLElement | null = null;\n\n /**\n * Marks the host as \"someone else owns the scrolling\", which drops `overflow-y` on this\n * component's own container.\n *\n * `position: sticky` pins to the nearest ancestor with `overflow-y: auto|scroll`. When a\n * host supplies a scroller, this component's container still declared `overflow-y: auto`\n * but never actually scrolled (its content grows to fit), so the sticky date header bound\n * to a container whose `scrollTop` is permanently 0 — it rendered, then rode out of view\n * with the messages and could not be clicked.\n *\n * Driven off `_scrollRoot` rather than `resolveScrollParent()` on purpose: the DOM walk is\n * lazy and layout-dependent, and dropping `overflow-y` for a consumer that turned out to\n * have NO scrolling ancestor would leave the transcript unable to scroll or page at all.\n * The explicit input is the only signal that is safe here — a host that passes it has, by\n * definition, a scroller of its own.\n */\n @HostBinding('class.mj-list-host-scrolled')\n public get HostSuppliesScroller(): boolean {\n return this._scrollRoot !== null;\n }\n\n // ── Assistant identity overrides — static host config forwarded to every message\n // item (null = engine identity). Setters (not ngOnChanges) so an imperative\n // host — `@ViewChild(MessageListComponent).assistantDisplayName = …` — restamps\n // too, and so identity changes don't pay a check on every other input's cycle.\n // Identity can land AFTER first render (branding resolves async) or change\n // mid-session (per-conversation persona), and message items are created\n // dynamically with the overrides stamped as static config — so a change has to\n // restamp the ALREADY-rendered items or existing bubbles keep the old identity\n // until the next messages-array mutation. ──\n /** Display name shown on AI messages. Null = the engine-resolved agent name. */\n @Input()\n public set AssistantDisplayName(value: string | null) {\n if (value !== this._assistantDisplayName) {\n this._assistantDisplayName = value;\n this.restampAssistantIdentity();\n }\n }\n public get AssistantDisplayName(): string | null {\n return this._assistantDisplayName;\n }\n\n /** @deprecated Use {@link AssistantDisplayName}. */\n public get assistantDisplayName(): string | null {\n return this.AssistantDisplayName;\n }\n /** @deprecated Use {@link AssistantDisplayName}. */\n @Input() public set assistantDisplayName(value: string | null) {\n this.AssistantDisplayName = value;\n }\n private _assistantDisplayName: string | null = null;\n\n /** Image URL for the AI message avatar. Null = the agent's Font Awesome icon. */\n @Input()\n public set AssistantAvatarUrl(value: string | null) {\n if (value !== this._assistantAvatarUrl) {\n this._assistantAvatarUrl = value;\n this.restampAssistantIdentity();\n }\n }\n public get AssistantAvatarUrl(): string | null {\n return this._assistantAvatarUrl;\n }\n\n /** @deprecated Use {@link AssistantAvatarUrl}. */\n public get assistantAvatarUrl(): string | null {\n return this.AssistantAvatarUrl;\n }\n /** @deprecated Use {@link AssistantAvatarUrl}. */\n @Input() public set assistantAvatarUrl(value: string | null) {\n this.AssistantAvatarUrl = value;\n }\n private _assistantAvatarUrl: string | null = null;\n @Input() public ArtifactMap: Map<string, LazyArtifactInfo[]> = new Map();\n\n /** @deprecated Use {@link ArtifactMap}. */\n @Input() public set artifactMap(value: Map<string, LazyArtifactInfo[]>) {\n this.ArtifactMap = value;\n }\n /** @deprecated Use {@link ArtifactMap}. */\n public get artifactMap(): Map<string, LazyArtifactInfo[]> {\n return this.ArtifactMap;\n }\n @Input() public AgentRunMap: Map<string, MJAIAgentRunEntityExtended> = new Map();\n\n /** @deprecated Use {@link AgentRunMap}. */\n @Input() public set agentRunMap(value: Map<string, MJAIAgentRunEntityExtended>) {\n this.AgentRunMap = value;\n }\n /** @deprecated Use {@link AgentRunMap}. */\n public get agentRunMap(): Map<string, MJAIAgentRunEntityExtended> {\n return this.AgentRunMap;\n }\n @Input() public RatingsMap: Map<string, RatingJSON[]> = new Map();\n\n /** @deprecated Use {@link RatingsMap}. */\n @Input() public set ratingsMap(value: Map<string, RatingJSON[]>) {\n this.RatingsMap = value;\n }\n /** @deprecated Use {@link RatingsMap}. */\n public get ratingsMap(): Map<string, RatingJSON[]> {\n return this.RatingsMap;\n }\n @Input() public UserAvatarMap: Map<string, {imageUrl: string | null; iconClass: string | null}> = new Map();\n\n /** @deprecated Use {@link UserAvatarMap}. */\n @Input() public set userAvatarMap(value: Map<string, {imageUrl: string | null; iconClass: string | null}>) {\n this.UserAvatarMap = value;\n }\n /** @deprecated Use {@link UserAvatarMap}. */\n public get userAvatarMap(): Map<string, {imageUrl: string | null; iconClass: string | null}> {\n return this.UserAvatarMap;\n }\n @Input() public AttachmentsMap: Map<string, MessageAttachment[]> = new Map();\n\n /** @deprecated Use {@link AttachmentsMap}. */\n @Input() public set attachmentsMap(value: Map<string, MessageAttachment[]>) {\n this.AttachmentsMap = value;\n }\n /** @deprecated Use {@link AttachmentsMap}. */\n public get attachmentsMap(): Map<string, MessageAttachment[]> {\n return this.AttachmentsMap;\n }\n /**\n * Optional session-row enrichment for realtime SESSION BLOCKS, keyed by\n * `NormalizeUUID(sessionId)` (agent name / status / close reason). Details stamped\n * with an `AgentSessionID` collapse into one timeline card per session — see\n * `BuildConversationTimeline` — and this map dresses those cards up when present.\n */\n @Input() public SessionMetaMap: Map<string, RealtimeSessionTimelineMeta> = new Map();\n\n /** @deprecated Use {@link SessionMetaMap}. */\n @Input() public set sessionMetaMap(value: Map<string, RealtimeSessionTimelineMeta>) {\n this.SessionMetaMap = value;\n }\n /** @deprecated Use {@link SessionMetaMap}. */\n public get sessionMetaMap(): Map<string, RealtimeSessionTimelineMeta> {\n return this.SessionMetaMap;\n }\n\n /**\n * Optional per-iteration custom message renderer. When set, the list renders each\n * message via this template (full replacement) instead of the default\n * `MessageItemComponent`. Forwarded by chat-area when a consumer projects\n * `mjChatSlot=\"messageRenderer\"`. The template receives the message as\n * `$implicit` and as a named `message` context binding.\n *\n * Consumers opting into a custom renderer take full responsibility for displaying\n * the message — edit/delete/retry affordances, artifacts, ratings, attachments,\n * etc. The minimal `MJChatMessageBubbleDefaultComponent` ships as a ready-to-use\n * bubble renderer.\n */\n @Input() public MessageRendererTemplate: TemplateRef<unknown> | null = null;\n\n /** @deprecated Use {@link MessageRendererTemplate}. */\n @Input() public set messageRendererTemplate(value: TemplateRef<unknown> | null) {\n this.MessageRendererTemplate = value;\n }\n /** @deprecated Use {@link MessageRendererTemplate}. */\n public get messageRendererTemplate(): TemplateRef<unknown> | null {\n return this.MessageRendererTemplate;\n }\n\n /**\n * Optional per-message additive decoration template, projected INSIDE the default\n * `MessageItemComponent` (after the message text). Forwarded by chat-area when a\n * consumer projects `mjChatSlot=\"messageExtra\"`. Ignored when\n * `messageRendererTemplate` is set (custom renderers own all per-message content).\n */\n @Input() public MessageExtraTemplate: TemplateRef<unknown> | null = null;\n\n /** @deprecated Use {@link MessageExtraTemplate}. */\n @Input() public set messageExtraTemplate(value: TemplateRef<unknown> | null) {\n this.MessageExtraTemplate = value;\n }\n /** @deprecated Use {@link MessageExtraTemplate}. */\n public get messageExtraTemplate(): TemplateRef<unknown> | null {\n return this.MessageExtraTemplate;\n }\n\n @Output() public EditMessage = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link EditMessage}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (editMessage) keeps working. Must stay AFTER EditMessage: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public editMessage = this.EditMessage;\n @Output() public DeleteMessage = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link DeleteMessage}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (deleteMessage) keeps working. Must stay AFTER DeleteMessage: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public deleteMessage = this.DeleteMessage;\n @Output() public RetryMessage = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link RetryMessage}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (retryMessage) keeps working. Must stay AFTER RetryMessage: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public retryMessage = this.RetryMessage;\n @Output() public TestFeedbackMessage = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link TestFeedbackMessage}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (testFeedbackMessage) keeps working. Must stay AFTER TestFeedbackMessage: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public testFeedbackMessage = this.TestFeedbackMessage;\n @Output() public ArtifactClicked = new EventEmitter<{artifactId: string; versionId?: string}>();\n\n /**\n * @deprecated Use {@link ArtifactClicked}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (artifactClicked) keeps working. Must stay AFTER ArtifactClicked: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public artifactClicked = this.ArtifactClicked;\n @Output() public ReplyInThread = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link ReplyInThread}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (replyInThread) keeps working. Must stay AFTER ReplyInThread: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public replyInThread = this.ReplyInThread;\n @Output() public ViewThread = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link ViewThread}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (viewThread) keeps working. Must stay AFTER ViewThread: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public viewThread = this.ViewThread;\n @Output() public MessageEdited = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link MessageEdited}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (messageEdited) keeps working. Must stay AFTER MessageEdited: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public messageEdited = this.MessageEdited;\n @Output() public OpenEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n\n /**\n * @deprecated Use {@link OpenEntityRecord}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (openEntityRecord) keeps working. Must stay AFTER OpenEntityRecord: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public openEntityRecord = this.OpenEntityRecord;\n @Output() public SuggestedResponseSelected = new EventEmitter<{text: string; customInput?: string}>();\n\n /**\n * @deprecated Use {@link SuggestedResponseSelected}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (suggestedResponseSelected) keeps working. Must stay AFTER SuggestedResponseSelected: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public suggestedResponseSelected = this.SuggestedResponseSelected;\n @Output() public AttachmentClicked = new EventEmitter<MessageAttachment>();\n\n /**\n * @deprecated Use {@link AttachmentClicked}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (attachmentClicked) keeps working. Must stay AFTER AttachmentClicked: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public attachmentClicked = this.AttachmentClicked;\n @Output() public DiagnosticRequested = new EventEmitter<string>();\n\n /**\n * @deprecated Use {@link DiagnosticRequested}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (diagnosticRequested) keeps working. Must stay AFTER DiagnosticRequested: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public diagnosticRequested = this.DiagnosticRequested; // emits messageId\n @Output() public MessagePinToggled = new EventEmitter<MJConversationDetailEntity>();\n\n /**\n * @deprecated Use {@link MessagePinToggled}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (messagePinToggled) keeps working. Must stay AFTER MessagePinToggled: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public messagePinToggled = this.MessagePinToggled;\n /** Emitted with the `MJ: AI Agent Sessions.ID` when a realtime session block's Open affordance is clicked. */\n @Output() public RealtimeSessionOpenRequested = new EventEmitter<string>();\n\n /**\n * @deprecated Use {@link RealtimeSessionOpenRequested}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (realtimeSessionOpenRequested) keeps working. Must stay AFTER RealtimeSessionOpenRequested: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public realtimeSessionOpenRequested = this.RealtimeSessionOpenRequested;\n\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public BeforeResponseFormSubmitted = new EventEmitter<BeforeResponseFormSubmittedEventArgs>();\n\n /**\n * @deprecated Use {@link BeforeResponseFormSubmitted}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (beforeResponseFormSubmitted) keeps working. Must stay AFTER BeforeResponseFormSubmitted: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public beforeResponseFormSubmitted = this.BeforeResponseFormSubmitted;\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public AfterResponseFormSubmitted = new EventEmitter<AfterResponseFormSubmittedEventArgs>();\n\n /**\n * @deprecated Use {@link AfterResponseFormSubmitted}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (afterResponseFormSubmitted) keeps working. Must stay AFTER AfterResponseFormSubmitted: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() public afterResponseFormSubmitted = this.AfterResponseFormSubmitted;\n\n /**\n * Asks the host to load the next older page. Fired when the \"earlier messages\"\n * sentinel scrolls into view — never on a raw scroll event, so a fast scroll costs\n * one emit rather than one per pixel.\n */\n @Output() public OlderRequested = new EventEmitter<void>();\n\n /**\n * Asks the host to page older history far enough back to satisfy a date jump, then scroll.\n * Emitted instead of handled locally because paging belongs to the window store.\n */\n @Output() public DateJumpRequested = new EventEmitter<DateJumpPeriod>();\n\n @ViewChild('messageContainer', { read: ViewContainerRef }) MessageContainerRef!: ViewContainerRef;\n\n /** @deprecated Use {@link MessageContainerRef}. */\n get messageContainerRef(): ViewContainerRef {\n return this.MessageContainerRef;\n }\n /** @deprecated Use {@link MessageContainerRef}. */\n set messageContainerRef(value: ViewContainerRef) {\n this.MessageContainerRef = value;\n }\n @ViewChild('scrollContainer') ScrollContainer!: ElementRef;\n\n /** @deprecated Use {@link ScrollContainer}. */\n get scrollContainer(): ElementRef {\n return this.ScrollContainer;\n }\n /** @deprecated Use {@link ScrollContainer}. */\n set scrollContainer(value: ElementRef) {\n this.ScrollContainer = value;\n }\n /** Only present while `HasMoreAbove` is true — the `@if` creates and destroys it. */\n @ViewChild('olderSentinel') OlderSentinel?: ElementRef<HTMLElement>;\n\n /** @deprecated Use {@link OlderSentinel}. */\n get olderSentinel(): ElementRef<HTMLElement> | undefined {\n return this.OlderSentinel;\n }\n /** @deprecated Use {@link OlderSentinel}. */\n set olderSentinel(value: ElementRef<HTMLElement> | undefined) {\n this.OlderSentinel = value;\n }\n /** Template rendered in place of an unmounted timeline item. */\n @ViewChild('spacerTemplate') private spacerTemplate?: TemplateRef<SpacerContext>;\n\n /**\n * Per-message rendered entries — see `RenderedMessageEntry` for the 3-way\n * union (default MessageItemComponent / consumer messageRenderer slot\n * embedded view / collapsed realtime session timeline card).\n */\n private _renderedMessages = new Map<string, RenderedMessageEntry>();\n\n /**\n * Per-message artifact-load counter, so a stale in-flight load cannot clobber a newer one.\n * Keyed by the child instance and held weakly, so an entry lives exactly as long as its\n * component — nothing to prune when a message leaves the timeline.\n *\n * Created on first use rather than as a field initializer. `message-list-windowing.test.ts`\n * constructs this component off the prototype, which runs none of the initializers; a\n * field initializer here failed nine of its cases.\n */\n private _artifactLoadGeneration?: WeakMap<MessageItemComponent, number>;\n\n private get artifactLoadGeneration(): WeakMap<MessageItemComponent, number> {\n return (this._artifactLoadGeneration ??= new WeakMap<MessageItemComponent, number>());\n }\n private _shouldScrollToBottom = false;\n private _previousMessageCount = 0; // Track previous count to detect new messages\n\n /** Watches the \"earlier messages\" sentinel. Rebuilt whenever the sentinel comes or goes. */\n private _olderObserver?: IntersectionObserver;\n /**\n * Set when the newest render PREPENDED older content, so `ngAfterViewChecked` can hold\n * the user's reading position instead of letting the browser's pixel-based `scrollTop`\n * slide them to unfamiliar content.\n */\n private _restoreScrollAfterPrepend = false;\n /** `scrollHeight` captured immediately before a prepend render. */\n private _heightBeforePrepend = 0;\n /** Memoized result of {@link resolveScrollParent} — the host's scroller, not ours. */\n private _scrollParent: HTMLElement | null = null;\n /** What the live observer is currently watching, so a stale pairing can be detected. */\n private _observedSentinel: HTMLElement | null = null;\n private _observedRoot: HTMLElement | null = null;\n /** Guards the no-scroll-parent warning so it fires once, not every checked cycle. */\n private _warnedNoScrollParent = false;\n /** Guards the missing-spacer-template warning the same way. */\n private _warnedNoSpacerTemplate = false;\n\n // ── DOM unmount (bounded transcript) ────────────────────────────────────────\n // Paging up 20 times would otherwise leave 200 live MessageItemComponents mounted.\n // Items far from the viewport are destroyed and replaced by a height-holding spacer,\n // then remounted from `messages` (already in memory — no network) on scroll-back.\n\n /** Rendered pixel height per timeline key, captured just before an item is unmounted. */\n private _measuredHeights = new Map<string, number>();\n /** Watches spacers so an item remounts as the user scrolls back toward it. */\n private _spacerObserver?: IntersectionObserver;\n /** Which spacers the live observer is watching, so it is only rebuilt when the set changes. */\n private _observedSpacerKeys = '';\n /** Scroller the window listener is attached to, and its coalescing frame handle. */\n private _scrollListenerTarget: HTMLElement | null = null;\n private _onScroll: (() => void) | null = null;\n private _scrollFrame: number | null = null;\n\n /** Items kept mounted beyond the visible page, above and below. */\n private static readonly MOUNT_BUFFER = 5;\n /**\n * Height used for an item unmounted before it was ever measured. Only a first-render\n * fallback — a real measurement replaces it and is preferred forever after.\n */\n private static readonly ESTIMATED_MESSAGE_HEIGHT = 72;\n private static readonly ESTIMATED_SESSION_HEIGHT = 88;\n /** Frames spent waiting for a scroller to appear, and the pending rAF handle. */\n private _scrollParentRetries = 0;\n private _scrollParentRetryHandle: number | null = null;\n /** ~1s at 60fps — long enough for layout to settle, short enough to report a real fault. */\n private static readonly MAX_SCROLL_PARENT_RETRIES = 60;\n /**\n * Render key of the FIRST timeline item last time we rendered. A change here means older\n * content arrived at the head — the only reliable way to tell a prepend from an append,\n * since both grow `messages.length`.\n */\n private _previousFirstKey: string | null = null;\n\n public CurrentDateDisplay: string = 'Today';\n\n /** @deprecated Use {@link CurrentDateDisplay}. */\n public get currentDateDisplay(): string {\n return this.CurrentDateDisplay;\n }\n /** @deprecated Use {@link CurrentDateDisplay}. */\n public set currentDateDisplay(value: string) {\n this.CurrentDateDisplay = value;\n }\n public ShowDateNav: boolean = false;\n\n /** @deprecated Use {@link ShowDateNav}. */\n public get showDateNav(): boolean {\n return this.ShowDateNav;\n }\n /** @deprecated Use {@link ShowDateNav}. */\n public set showDateNav(value: boolean) {\n this.ShowDateNav = value;\n }\n public ShouldShowDateFilter: boolean = false;\n\n /** @deprecated Use {@link ShouldShowDateFilter}. */\n public get shouldShowDateFilter(): boolean {\n return this.ShouldShowDateFilter;\n }\n /** @deprecated Use {@link ShouldShowDateFilter}. */\n public set shouldShowDateFilter(value: boolean) {\n this.ShouldShowDateFilter = value;\n }\n\n constructor(private cdRef: ChangeDetectorRef, private hostRef: ElementRef<HTMLElement>) {\n super();\n }\n\n public ToggleDateNav(): void {\n this.ShowDateNav = !this.ShowDateNav;\n }\n\n /** @deprecated Use {@link ToggleDateNav}. */\n public toggleDateNav(): void {\n return this.ToggleDateNav();\n }\n\n /**\n * Handles a date-navigator selection.\n *\n * The list cannot page history itself — it is a Generic widget with no store — so it asks\n * the host, which owns the window and runs the older-page loop, then calls back into\n * {@link ScrollToDateTarget}. The label updates immediately so the dropdown feels responsive\n * while paging runs.\n */\n public JumpToDate(period: string): void {\n this.ShowDateNav = false;\n if (!isDateJumpPeriod(period)) {\n return;\n }\n this.CurrentDateDisplay = DATE_JUMP_LABELS[period];\n this.DateJumpRequested.emit(period);\n }\n\n /** @deprecated Use {@link JumpToDate}. */\n public jumpToDate(period: string): void {\n return this.JumpToDate(period);\n }\n\n /**\n * Scrolls to the start of `period` within the currently loaded messages.\n *\n * Called by the host AFTER it has paged as far back as it intends to, so whatever is loaded\n * now is the best answer available. Returns the outcome rather than failing silently — the\n * plan's explicit requirement for this path.\n */\n public ScrollToDateTarget(period: DateJumpPeriod): DateJumpOutcome {\n if (!this.messages || this.messages.length === 0) {\n return 'empty';\n }\n\n const { Detail } = ResolveDateJumpTarget(this.messages, period, new Date());\n // A miss lands the user on the oldest loaded message — where paging left them — rather\n // than leaving the viewport wherever it happened to be.\n const target = Detail ?? this.messages[0];\n const scrolled = this.scrollToDetail(target);\n if (!scrolled) {\n return 'empty';\n }\n return Detail ? 'reached' : 'oldest';\n }\n\n /**\n * Scrolls a loaded detail into view, mounted or not.\n *\n * Resolves through the TIMELINE KEY rather than querying `[data-message-id]`, because the\n * jump target is by definition far above the viewport — exactly the region this component\n * unmounts and replaces with height-holding spacers. A DOM query for the message id misses\n * every unmounted target, which made a legitimate jump report \"nothing loaded to jump to\".\n *\n * Spacers carry the same timeline key as the item they stand in for, so scrolling to the\n * key lands on the right place either way; the spacer observer then remounts the real item\n * as it enters the viewport.\n */\n private scrollToDetail(detail: MJConversationDetailEntity): boolean {\n return this.scrollToTimelineEntry(detail.ID, detail.AgentSessionID, 'start');\n }\n\n /**\n * Scrolls a LOADED message into view by id, mounted or not, and returns whether it landed.\n *\n * Public because the pins panel's \"Jump to message\" lives on the host: a pin can be far\n * above the viewport, which is exactly the region this component unmounts into spacers, so\n * the host's own `[data-message-id]` query found nothing and the button silently did\n * nothing. Resolution goes through the timeline key instead — see\n * {@link scrollToTimelineEntry}.\n *\n * Returns false when the message is not in the loaded window at all; the host decides\n * whether to page back for it or tell the user.\n */\n public ScrollToMessage(messageId: string): boolean {\n const detail = this.messages?.find(m => UUIDsEqual(m.ID, messageId));\n if (!detail) {\n return false;\n }\n return this.scrollToTimelineEntry(detail.ID, detail.AgentSessionID, 'center');\n }\n\n /**\n * The node standing for a LOADED message on screen — the mounted item, the spacer holding\n * its place while it is unmounted, or the session card a session-stamped row folds into.\n * Null when the message is not in the loaded window. Hosts that need to MEASURE a message\n * (not just scroll to it) use this instead of a `[data-message-id]` query, which fails for\n * exactly the cases listed — see {@link scrollToTimelineEntry}.\n */\n public FindTimelineElement(messageId: string): HTMLElement | null {\n const detail = this.messages?.find(m => UUIDsEqual(m.ID, messageId));\n if (!detail) {\n return null;\n }\n return this.resolveTimelineNode(detail.ID, detail.AgentSessionID) ?? null;\n }\n\n /**\n * Shared resolution for both jump paths: timeline key -> rendered node.\n *\n * Two things a `[data-message-id]` query cannot do, and both matter here:\n * - A session-stamped row folds into its session CARD, so the row itself never has a\n * node of its own; the card is what is on screen.\n * - An item far from the viewport is unmounted and replaced by a height-holding spacer,\n * which carries the SAME timeline key — so scrolling to the key lands in the right\n * place either way, and the spacer observer remounts the real item on arrival.\n */\n private scrollToTimelineEntry(\n detailId: string,\n agentSessionId: string | null,\n block: ScrollLogicalPosition\n ): boolean {\n const node = this.resolveTimelineNode(detailId, agentSessionId);\n if (!node) {\n return false;\n }\n node.scrollIntoView({ behavior: 'smooth', block });\n return true;\n }\n\n /** Timeline key -> rendered node for a detail (or the session card its stamped row folds into). */\n private resolveTimelineNode(detailId: string, agentSessionId: string | null): HTMLElement | undefined {\n const stampedSessionId = agentSessionId?.trim() || null;\n const timeline = BuildConversationTimeline(this.messages);\n const item = timeline.find(entry =>\n entry.Kind === 'session'\n ? stampedSessionId !== null && UUIDsEqual(entry.Group.SessionID, stampedSessionId)\n : UUIDsEqual(entry.Detail.ID, detailId)\n );\n return item ? this.nodeForKey(this.getTimelineKey(item)) : undefined;\n }\n\n // Track whether initial render has happened\n private _initialRenderComplete = false;\n\n ngOnInit() {\n // Initial render will happen in ngAfterViewInit when ViewContainerRef is available\n }\n\n ngAfterViewInit() {\n // ViewContainerRef is now available - perform initial render if we have messages\n if (this.messages && this.messages.length > 0 && this.MessageContainerRef && !this._initialRenderComplete) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // React to messages array changes\n // Note: On initial load, messageContainerRef may not be available yet (ngOnChanges runs before ngAfterViewInit)\n // In that case, ngAfterViewInit will handle the initial render\n if (changes['messages'] && this.messages && this.MessageContainerRef) {\n this._initialRenderComplete = true;\n // Capture the pre-render height so a prepend can be corrected for. Must happen\n // BEFORE updateMessages — afterwards the new rows are already in the layout — and\n // must read the HOST's scroller, which is the element whose height actually changes.\n this._heightBeforePrepend = this.resolveScrollParent()?.scrollHeight ?? 0;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n\n // Watch for artifactMap changes to handle newly created artifacts\n // While artifacts are pre-loaded during initial peripheral data load,\n // new artifacts can be created mid-conversation (e.g., by agent runs)\n // This ensures artifact cards appear in messages immediately without requiring a refresh\n if (changes['artifactMap'] && this.messages && this.MessageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for attachmentsMap changes to handle newly created attachments\n // This ensures media attachments (e.g., images generated by agents) appear\n // immediately without requiring a page refresh\n if (changes['attachmentsMap'] && this.messages && this.MessageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for session-meta changes so realtime session blocks pick up their\n // agent name / status chip once the (async, batched) session lookup lands\n if (changes['sessionMetaMap'] && this.messages && this.MessageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n }\n\n /**\n * Re-stamp the assistant-identity overrides onto every already-rendered message\n * item. Called from the identity setters (see the inputs above) — items are created\n * dynamically with these values stamped as static config, so without this a change\n * that arrives after first render wouldn't reach existing bubbles.\n *\n * No-op before the first render (the map is empty), so it's safe to fire during\n * Angular's initial input binding.\n */\n private restampAssistantIdentity(): void {\n for (const entry of this._renderedMessages.values()) {\n if (entry.kind === 'component') {\n this.applyMessageItemFeatureFlags(entry.ref.instance);\n entry.ref.changeDetectorRef.markForCheck();\n }\n }\n }\n\n ngAfterViewChecked() {\n // Mutually exclusive on purpose: scrolling to the bottom would undo a prepend restore.\n if (this._restoreScrollAfterPrepend) {\n this.restoreScrollAfterPrepend();\n this._restoreScrollAfterPrepend = false;\n } else if (this._shouldScrollToBottom) {\n this.scrollToBottom();\n this._shouldScrollToBottom = false;\n }\n // Measure while things are on screen, so an item has a real height recorded before it\n // ever needs a spacer — the plan's \"measure offsetHeight the first time an item is\n // mounted and remember it by key\".\n this.measureMountedItems();\n this.syncScrollListener();\n this.syncOlderObserver();\n this.syncSpacerObserver();\n }\n\n /** The rendered sentinel, read from the DOM so it does not depend on view-query timing. */\n private findSentinelElement(): HTMLElement | null {\n return this.hostRef.nativeElement.querySelector('.transcript-older-sentinel');\n }\n\n /**\n * Whether this instance is actually on screen.\n *\n * `offsetParent` is null for any element in a `display: none` subtree — which is how the\n * chat area parks the message lists of conversations you are not currently looking at.\n */\n private isHostVisible(): boolean {\n const host = this.hostRef.nativeElement;\n return host.offsetParent !== null || getComputedStyle(host).position === 'fixed';\n }\n\n /**\n * Retries {@link syncOlderObserver} on animation frames until a scroller appears.\n *\n * Bounded: after {@link MAX_SCROLL_PARENT_RETRIES} frames it gives up and logs the DOM\n * chain it walked, so a genuine host-layout problem names itself instead of presenting\n * as \"paging silently doesn't work\".\n */\n private scheduleScrollParentRetry(): void {\n if (this._scrollParentRetryHandle !== null) {\n return; // one retry loop at a time\n }\n // A HIDDEN instance can never resolve a scroller: the chat area keeps one message list\n // alive per visited conversation in a DOM cache, and a display:none subtree reports\n // every height as 0, so `scrollHeight > clientHeight` is false all the way up. Keep\n // waiting (it may be shown later) but never burn the retry budget or warn — that noise\n // would point at the wrong instance entirely.\n if (!this.isHostVisible()) {\n this._scrollParentRetryHandle = requestAnimationFrame(() => {\n this._scrollParentRetryHandle = null;\n this.syncOlderObserver();\n });\n return;\n }\n if (this._scrollParentRetries >= MessageListComponent.MAX_SCROLL_PARENT_RETRIES) {\n this.warnNoScrollParentOnce();\n return;\n }\n this._scrollParentRetries++;\n this._scrollParentRetryHandle = requestAnimationFrame(() => {\n this._scrollParentRetryHandle = null;\n this.syncOlderObserver();\n });\n }\n\n /** One-time diagnostic dump of the ancestor chain, so the failure is self-explaining. */\n private warnNoScrollParentOnce(): void {\n if (this._warnedNoScrollParent) {\n return;\n }\n this._warnedNoScrollParent = true;\n\n const chain: Array<Record<string, unknown>> = [];\n let el: HTMLElement | null =\n this.findSentinelElement() ?? this.ScrollContainer?.nativeElement ?? null;\n while (el && chain.length < 20) {\n const style = getComputedStyle(el);\n chain.push({\n el: el.className || el.tagName,\n overflowY: style.overflowY,\n scrollHeight: el.scrollHeight,\n clientHeight: el.clientHeight\n });\n el = el.parentElement;\n }\n\n console.warn(\n '[MessageList] \"Earlier messages\" is showing but no scrolling ancestor was found, so '\n + 'older pages cannot auto-load. The host must give the transcript a scrollable container '\n + '(overflow-y: auto AND a bounded height, e.g. min-height: 0 on a flex child). '\n + 'Walked from '\n + (this.OlderSentinel ? 'the sentinel' : this.ScrollContainer ? 'the list container' : 'NOTHING — both view children are undefined')\n + ':',\n chain\n );\n }\n\n /**\n * The element that ACTUALLY scrolls the transcript.\n *\n * This component's own `.message-list-container` does not scroll: the chat area wraps it\n * in `.chat-messages-container`, and that outer div is the one carrying `min-height: 0`\n * alongside `overflow-y: auto` — the pair a flex child needs before it will scroll instead\n * of growing to fit its content. Targeting the inner div means writing `scrollTop` on an\n * element whose `scrollHeight === clientHeight`, which silently does nothing, and giving\n * an IntersectionObserver a root that never scrolls.\n *\n * Walking up keeps this component agnostic about the host's markup — any consumer that\n * wraps it in its own scroller works the same way.\n */\n private resolveScrollParent(): HTMLElement | null {\n // Host-supplied root wins — no discovery, no timing dependency.\n if (this._scrollRoot?.isConnected) {\n return this._scrollRoot;\n }\n if (this._scrollParent && this._scrollParent.isConnected) {\n return this._scrollParent;\n }\n // Start from the sentinel when it exists: it is the element being observed, so it is\n // guaranteed present exactly when the walk matters. `@ViewChild('scrollContainer')`\n // resolves on Angular's own schedule and can still be undefined here, which would end\n // the walk before it began.\n let el: HTMLElement | null =\n this.findSentinelElement() ?? this.ScrollContainer?.nativeElement ?? null;\n while (el) {\n const overflowY = getComputedStyle(el).overflowY;\n if ((overflowY === 'auto' || overflowY === 'scroll') && el.scrollHeight > el.clientHeight) {\n this._scrollParent = el;\n return el;\n }\n el = el.parentElement;\n }\n return null; // nothing overflows yet — short conversation, nothing to scroll\n }\n\n /**\n * Holds the user's reading position after older content is spliced in above.\n *\n * `scrollTop` is a pixel offset from the top, so inserting content above silently shifts\n * everything down — the user ends up looking at messages they never scrolled to. Adding\n * the height delta puts the same message back under their eyes.\n */\n private restoreScrollAfterPrepend(): void {\n const el = this.resolveScrollParent();\n if (!el) {\n return;\n }\n const delta = el.scrollHeight - this._heightBeforePrepend;\n if (delta > 0) {\n el.scrollTop = el.scrollTop + delta;\n }\n }\n\n /**\n * True when the environment provides `IntersectionObserver`.\n *\n * False under SSR and in the unit-test projects. Both observer syncs are reached a\n * microtask late (see the `HasMoreAbove` setter), so a spec that stubs the global and\n * restores it synchronously has already restored it by the time the sync runs — the\n * constructor call then throws inside a `.then()` with no catch, which surfaces as an\n * unhandled rejection rather than a test failure and fails the run despite every\n * assertion passing.\n */\n private get canObserve(): boolean {\n return typeof IntersectionObserver !== 'undefined';\n }\n\n /**\n * Keeps the IntersectionObserver attached to the current sentinel element.\n *\n * The sentinel lives inside `@if (HasMoreAbove)`, so it is created and destroyed as the\n * user reaches the top of the loaded window and as older pages arrive. Runs every checked\n * cycle and is a no-op once attached.\n *\n * Observer-on-sentinel rather than a scroll listener: a fast scroll costs one callback,\n * not one per frame.\n */\n private syncOlderObserver(): void {\n if (!this.canObserve) {\n return;\n }\n if (!this.HasMoreAbove) {\n this._olderObserver?.disconnect();\n this._olderObserver = undefined;\n this._observedSentinel = null;\n this._observedRoot = null;\n return;\n }\n\n // Query the DOM rather than reading `@ViewChild('olderSentinel')`.\n //\n // The sentinel lives inside `@if`, so the view query resolves on Angular's own\n // schedule — and `updateMessages` detaches/reattaches this component's change detector\n // around every render, which makes that schedule hard to reason about. Reading the host\n // element directly is timing-independent: if the div is on the page, we find it.\n const el = this.findSentinelElement();\n if (!el) {\n this.scheduleScrollParentRetry(); // not rendered yet — look again next frame\n return;\n }\n\n // The scroll parent is not resolvable until something actually overflows, which is not\n // true on the first checked cycle. Bailing (rather than observing with a null root)\n // matters: a viewport-rooted observer never sees a sentinel clipped inside a scrolled\n // container, so it would silently never fire.\n const root = this.resolveScrollParent();\n if (!root) {\n // A scroller only becomes findable once its content overflows, which is not true on\n // the tick the sentinel first renders. Retry on animation frames rather than waiting\n // for another change-detection pass — once the list settles there may not be one.\n this.scheduleScrollParentRetry();\n return;\n }\n this._scrollParentRetries = 0;\n\n // Rebuild whenever EITHER end of the relationship changes — `@if` swaps the sentinel\n // element as HasMoreAbove toggles, and the root only becomes known once content\n // overflows. Observing a stale element or a stale root is silent, not loud.\n if (this._olderObserver && this._observedSentinel === el && this._observedRoot === root) {\n return;\n }\n this._olderObserver?.disconnect();\n\n this._olderObserver = new IntersectionObserver(\n entries => {\n // Re-check the flags at fire time: the observer can fire while a load is already\n // running, and LoadOlder's own guard shouldn't be the only thing standing between\n // a fast scroll and a burst of duplicate requests.\n if (entries.some(e => e.isIntersecting) && this.HasMoreAbove && !this.IsLoadingOlder) {\n this.OlderRequested.emit();\n }\n },\n // Root must be the REAL scroller, not this component's own container — an observer\n // rooted on a non-scrolling ancestor reports the sentinel as permanently visible.\n { root, threshold: 0.01 }\n );\n this._olderObserver.observe(el);\n this._observedSentinel = el;\n this._observedRoot = root;\n }\n\n ngOnDestroy() {\n this._olderObserver?.disconnect();\n this._olderObserver = undefined;\n this._spacerObserver?.disconnect();\n this._spacerObserver = undefined;\n if (this._scrollParentRetryHandle !== null) {\n cancelAnimationFrame(this._scrollParentRetryHandle);\n this._scrollParentRetryHandle = null;\n }\n\n // Clean up all dynamically created components AND embedded views (both have destroy()).\n this._renderedMessages.forEach((entry) => {\n if (entry) {\n entry.ref.destroy();\n }\n });\n this._renderedMessages.clear();\n\n if (this.MessageContainerRef) {\n this.MessageContainerRef.clear();\n }\n }\n\n /**\n * Called when messages array changes\n * Efficiently updates the DOM without re-rendering everything\n */\n @Input()\n set MessagesUpdate(messages: MJConversationDetailEntity[]) {\n if (messages && this.MessageContainerRef) {\n this.updateMessages(messages);\n }\n }\n\n /** @deprecated Use {@link MessagesUpdate}. */\n @Input() set messagesUpdate(value: MJConversationDetailEntity[]) {\n this.MessagesUpdate = value;\n }\n\n /**\n * Updates the message list using dynamic component creation\n * Only adds/removes changed messages for optimal performance\n *\n * REALTIME SESSIONS: details stamped with an `AgentSessionID` (turns persisted during\n * a live realtime session) do NOT render as normal chat bubbles. The timeline pass\n * (`BuildConversationTimeline`) collapses each session's stamped rows into ONE session\n * block, rendered as a `RealtimeSessionTimelineCardComponent` at the session's\n * chronological position. Everything else renders exactly as before.\n */\n private updateMessages(messages: MJConversationDetailEntity[]): void {\n // Temporarily detach change detection for performance\n this.cdRef.detach();\n\n try {\n // Build the timeline first — collapses contiguous realtime-session rows\n // into ONE session block per session, leaving normal messages in place.\n // See `BuildConversationTimeline` in `utils/realtime-session-timeline`.\n const timeline = BuildConversationTimeline(messages);\n\n // Remove rendered items (messages AND session blocks) that no longer exist\n const currentKeys = new Set(timeline.map(item => this.getTimelineKey(item)));\n this._renderedMessages.forEach((entry, key) => {\n if (!currentKeys.has(key)) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n });\n\n // Add or update timeline items in chronological order. `renderMessageItem`\n // internally branches on the slot template (messageRenderer) vs the\n // default MessageItemComponent; `renderSessionBlock` always creates a\n // RealtimeSessionTimelineCardComponent.\n // The timeline index is passed through so newly created views land at the RIGHT\n // position. `createComponent` appends by default, which would put prepended older\n // messages at the bottom of the DOM despite being the oldest content.\n // Items far from the viewport are UNMOUNTED and replaced by a height-holding spacer,\n // so paging a long way up leaves a bounded DOM rather than hundreds of live message\n // components. The tail and any in-progress message are always kept.\n const range = this.computeMountedRange(timeline);\n const lastMessageKey = this.findLastMessageKey(timeline);\n for (let i = 0; i < timeline.length; i++) {\n const item = timeline[i];\n const mounted = (i >= range.start && i <= range.end)\n || this.mustStayMounted(item, i, timeline.length);\n\n if (!mounted) {\n this.ensureSpacer(this.getTimelineKey(item), item, i);\n } else if (item.Kind === 'session') {\n this.renderSessionBlock(item.Group, i);\n } else {\n this.renderMessageItem(item.Detail, messages, this.getMessageKey(item.Detail) === lastMessageKey, i);\n }\n }\n\n // Decide where the viewport should end up.\n //\n // A raw `length > previousCount` check cannot tell an append from a prepend — paging\n // older history also grows the array, and treating that as \"someone sent a message\"\n // would snap the user to the newest message every time they scrolled up. Compare the\n // FIRST timeline key instead: if it changed, older content arrived at the head.\n const previousCount = this._previousMessageCount;\n this._previousMessageCount = messages.length;\n\n const firstKey = timeline.length > 0 ? this.getTimelineKey(timeline[0]) : null;\n const prepended = this._previousFirstKey !== null\n && firstKey !== null\n && firstKey !== this._previousFirstKey;\n this._previousFirstKey = firstKey;\n\n if (prepended) {\n this._restoreScrollAfterPrepend = true;\n } else if (messages.length > previousCount) {\n this._shouldScrollToBottom = true;\n }\n } finally {\n // Re-attach change detection\n this.cdRef.reattach();\n this.cdRef.detectChanges();\n }\n }\n\n /**\n * The span of timeline indices that stay mounted.\n *\n * Follows the tail on first paint and whenever nothing measurable is on screen. Once items\n * are rendered, the span is centred on what the reader is actually looking at — measured\n * from scroll position, plus {@link MessageListComponent.MOUNT_BUFFER} either side — so\n * scrolling back does not collapse the window to the newest messages on the next render.\n *\n * (An earlier design pinned the top of the span with a remembered key instead. It was\n * replaced by the measurement below for the reason that comment explains, and the key no\n * longer exists.)\n */\n private computeMountedRange(\n timeline: ConversationTimelineItem<MJConversationDetailEntity>[]\n ): { start: number; end: number } {\n const lastIndex = timeline.length - 1;\n const span = DEFAULT_TRANSCRIPT_PAGE_SIZE + MessageListComponent.MOUNT_BUFFER * 2;\n const tailRange = { start: Math.max(0, timeline.length - span), end: lastIndex };\n\n const root = this.resolveScrollParent();\n if (!root || this._renderedMessages.size === 0) {\n return tailRange; // first paint — follow the tail\n }\n\n // Derived from SCROLL POSITION, which nothing in the render loop feeds back into.\n //\n // Reacting to spacer intersections instead is circular: a spacer's height is an\n // estimate, so where it sits decides what is visible, which decides which spacers fire,\n // which changes what is mounted, which changes heights. That loop is what made the\n // transcript replay the same region; constraining it to one direction only traded the\n // ping-pong for dead zones that never remounted.\n const rootTop = root.getBoundingClientRect().top;\n const viewportHeight = root.clientHeight;\n let firstVisible = -1;\n let lastVisible = -1;\n\n for (let i = 0; i < timeline.length; i++) {\n const node = this.nodeForKey(this.getTimelineKey(timeline[i]));\n if (!node) {\n continue;\n }\n const rect = node.getBoundingClientRect();\n const top = rect.top - rootTop;\n const bottom = top + rect.height;\n if (bottom > 0 && firstVisible < 0) {\n firstVisible = i;\n }\n if (top < viewportHeight) {\n lastVisible = i;\n }\n }\n if (firstVisible < 0 || lastVisible < 0) {\n return tailRange;\n }\n\n return {\n start: Math.max(0, firstVisible - MessageListComponent.MOUNT_BUFFER),\n end: Math.min(lastIndex, lastVisible + MessageListComponent.MOUNT_BUFFER)\n };\n }\n\n /** The rendered DOM node for a timeline key, whatever kind of entry backs it. */\n private nodeForKey(key: string): HTMLElement | undefined {\n const entry = this._renderedMessages.get(key);\n if (!entry) {\n return undefined;\n }\n return entry.kind === 'embedded' || entry.kind === 'spacer'\n ? (entry.ref.rootNodes[0] as HTMLElement | undefined)\n : (entry.ref.location.nativeElement as HTMLElement | undefined);\n }\n\n /**\n * Items that must never be unmounted regardless of position.\n *\n * The tail carries streaming output, `isLastMessage` affordances and suggested\n * responses; an in-progress message is mid-stream and would lose its live state.\n */\n private mustStayMounted(\n item: ConversationTimelineItem<MJConversationDetailEntity>,\n index: number,\n timelineLength: number\n ): boolean {\n if (index === timelineLength - 1) {\n return true;\n }\n return item.Kind === 'message' && item.Detail.Status === 'In-Progress';\n }\n\n /**\n * Records what an entry occupied on screen, so its spacer holds exactly that much space.\n *\n * Called immediately BEFORE destroying — afterwards the node is gone. A wrong height here\n * is the failure mode that makes scrolling jump, which is the whole thing spacers exist\n * to prevent.\n */\n private rememberHeight(key: string, entry: RenderedMessageEntry): void {\n const node = entry.kind === 'embedded' || entry.kind === 'spacer'\n ? (entry.ref.rootNodes[0] as HTMLElement | undefined)\n : (entry.ref.location.nativeElement as HTMLElement | undefined);\n const height = node?.offsetHeight ?? 0;\n if (height > 0) {\n this._measuredHeights.set(key, height);\n }\n }\n\n /** Measured height when we have one, else a kind-appropriate estimate. */\n private heightFor(key: string, item: ConversationTimelineItem<MJConversationDetailEntity>): number {\n const measured = this._measuredHeights.get(key);\n if (measured !== undefined) {\n return measured;\n }\n return item.Kind === 'session'\n ? MessageListComponent.ESTIMATED_SESSION_HEIGHT\n : MessageListComponent.ESTIMATED_MESSAGE_HEIGHT;\n }\n\n /**\n * Measures every currently-mounted item.\n *\n * Runs each checked cycle so an item has a real height recorded BEFORE it scrolls far\n * enough to be unmounted — otherwise its first spacer is always a guess.\n */\n private measureMountedItems(): void {\n this._renderedMessages.forEach((entry, key) => {\n if (entry.kind === 'spacer') {\n return;\n }\n const node = entry.kind === 'embedded'\n ? (entry.ref.rootNodes[0] as HTMLElement | undefined)\n : (entry.ref.location.nativeElement as HTMLElement | undefined);\n const height = node?.offsetHeight ?? 0;\n if (height > 0) {\n this._measuredHeights.set(key, height);\n }\n });\n }\n\n\n /**\n * Replaces a mounted item with a height-holding spacer, or leaves an existing spacer\n * alone. Stored under the item's own timeline key so {@link updateMessages}'s\n * remove-stale pass and the remount path both find it.\n */\n private ensureSpacer(\n key: string,\n item: ConversationTimelineItem<MJConversationDetailEntity>,\n timelineIndex: number\n ): void {\n const existing = this._renderedMessages.get(key);\n if (existing?.kind === 'spacer') {\n return;\n }\n if (!this.spacerTemplate) {\n // Staying mounted is the safe choice, but silently doing so means the transcript\n // grows without bound and nothing says why. Report it once.\n if (!this._warnedNoSpacerTemplate) {\n this._warnedNoSpacerTemplate = true;\n console.warn(\n '[MessageList] spacerTemplate did not resolve, so off-screen messages cannot be '\n + 'unmounted and the DOM will grow with every page loaded.'\n );\n }\n return;\n }\n if (existing) {\n this.rememberHeight(key, existing);\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n const viewRef = this.MessageContainerRef.createEmbeddedView<SpacerContext>(\n this.spacerTemplate,\n { height: this.heightFor(key, item) },\n { index: timelineIndex }\n );\n this._renderedMessages.set(key, { kind: 'spacer', ref: viewRef });\n }\n\n /**\n * Re-evaluates the mounted window as the user scrolls.\n *\n * Attached once to the host's scroller. Coalesced onto an animation frame so a fast scroll\n * costs one re-render per frame rather than one per event, and skipped entirely when the\n * window has not actually moved.\n */\n private syncScrollListener(): void {\n const root = this.resolveScrollParent();\n if (!root || root === this._scrollListenerTarget) {\n return;\n }\n this.detachScrollListener();\n this._scrollListenerTarget = root;\n this._onScroll = () => {\n if (this._scrollFrame !== null) {\n return;\n }\n this._scrollFrame = requestAnimationFrame(() => {\n this._scrollFrame = null;\n if (this.messages?.length) {\n this.updateMessages(this.messages);\n }\n });\n };\n root.addEventListener('scroll', this._onScroll, { passive: true });\n }\n\n private detachScrollListener(): void {\n if (this._scrollListenerTarget && this._onScroll) {\n this._scrollListenerTarget.removeEventListener('scroll', this._onScroll);\n }\n this._scrollListenerTarget = null;\n this._onScroll = null;\n if (this._scrollFrame !== null) {\n cancelAnimationFrame(this._scrollFrame);\n this._scrollFrame = null;\n }\n }\n\n /**\n * Watches the current spacers so scrolling back toward one remounts it.\n *\n * Rebuilt on every render because spacers come and go. Remounting reads from `messages`,\n * which is already in memory — this never triggers a fetch.\n */\n private syncSpacerObserver(): void {\n if (!this.canObserve) {\n return;\n }\n const root = this.resolveScrollParent();\n if (!root) {\n this._spacerObserver?.disconnect();\n this._spacerObserver = undefined;\n this._observedSpacerKeys = '';\n return;\n }\n const spacers: Array<{ key: string; el: HTMLElement }> = [];\n this._renderedMessages.forEach((entry, key) => {\n if (entry.kind === 'spacer') {\n const el = entry.ref.rootNodes[0] as HTMLElement | undefined;\n if (el) {\n spacers.push({ key, el });\n }\n }\n });\n if (spacers.length === 0) {\n this._spacerObserver?.disconnect();\n this._spacerObserver = undefined;\n this._observedSpacerKeys = '';\n return;\n }\n\n // Rebuild ONLY when the spacer set actually changes.\n //\n // This runs every checked cycle, and a fresh IntersectionObserver delivers an initial\n // callback for everything it observes. Rebuilding unconditionally therefore re-fired\n // remountAround on every change-detection pass, which re-rendered, which triggered\n // another pass — the transcript visibly stuck, replaying the same region.\n const signature = spacers.map(s => s.key).sort().join('|');\n if (this._spacerObserver && signature === this._observedSpacerKeys) {\n return;\n }\n this._spacerObserver?.disconnect();\n this._observedSpacerKeys = signature;\n\n this._spacerObserver = new IntersectionObserver(\n entries => {\n const hit = entries.find(e => e.isIntersecting);\n if (!hit) {\n return;\n }\n // The range is computed from scroll position; a spacer coming into view just means\n // it is time to recompute. No key is threaded through, so there is no feedback loop.\n if (this.messages?.length) {\n this.updateMessages(this.messages);\n }\n },\n { root, threshold: 0.01 }\n );\n for (const s of spacers) {\n this._spacerObserver.observe(s.el);\n }\n }\n\n\n /** Stable render key for a timeline item — message ID, or a prefixed session key for session blocks. */\n private getTimelineKey(item: ConversationTimelineItem<MJConversationDetailEntity>): string {\n return item.Kind === 'session' ? this.getSessionKey(item.Group.SessionID) : this.getMessageKey(item.Detail);\n }\n\n /** Render key for a session block (case-insensitive on the session id; prefixed so it can't collide with message IDs). */\n private getSessionKey(sessionId: string): string {\n return `session:${NormalizeUUID(sessionId)}`;\n }\n\n /** The render key of the LAST normal message item in the timeline (drives `isLastMessage`), or null when none. */\n private findLastMessageKey(timeline: ConversationTimelineItem<MJConversationDetailEntity>[]): string | null {\n for (let i = timeline.length - 1; i >= 0; i--) {\n const item = timeline[i];\n if (item.Kind === 'message') {\n return this.getMessageKey(item.Detail);\n }\n }\n return null;\n }\n\n /**\n * Creates or updates the ONE timeline card a realtime session collapses to.\n * Click/Open on the card bubbles up via {@link realtimeSessionOpenRequested} so the\n * chat area can host the SESSION REVIEW overlay for it.\n */\n private renderSessionBlock(group: RealtimeSessionTimelineGroup, timelineIndex: number): void {\n const key = this.getSessionKey(group.SessionID);\n const meta = this.SessionMetaMap.get(NormalizeUUID(group.SessionID)) ?? null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'realtime-session') {\n // Update existing card in place.\n const instance = existing.ref.instance;\n instance.Group = group;\n instance.Meta = meta;\n existing.ref.changeDetectorRef.markForCheck();\n return;\n }\n\n // Different kind at this key (e.g. mode changed) — drop the old entry, fall through to create.\n if (existing) {\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n const componentRef = this.MessageContainerRef.createComponent(\n RealtimeSessionTimelineCardComponent,\n { index: timelineIndex }\n );\n componentRef.instance.Group = group;\n componentRef.instance.Meta = meta;\n // The card says \"You\" on the viewer's own call and names the caller on anyone else's, which is\n // why it takes the viewer's id rather than their name.\n componentRef.instance.CurrentUserID = this.CurrentUser?.ID ?? null;\n componentRef.instance.OpenRequested.subscribe((sessionId: string) => this.RealtimeSessionOpenRequested.emit(sessionId));\n this._renderedMessages.set(key, { kind: 'realtime-session', ref: componentRef });\n }\n\n /**\n * Creates or updates one normal chat message item. Routes to the\n * consumer-projected `messageRenderer` slot template (EmbeddedViewRef path)\n * when present, otherwise falls back to the default `MessageItemComponent`\n * dynamic-component path. Both paths flow through the shared\n * `createRenderedEntry` / `updateMessageItemInstance` helpers.\n */\n private renderMessageItem(\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n isLastMessage: boolean,\n timelineIndex: number\n ): void {\n const key = this.getMessageKey(message);\n // `index` is only used for the `isLastMessage` heuristic inside\n // updateMessageItemInstance — synthesize a value that produces the right\n // boolean (last index when `isLastMessage` is true, else 0 — any non-last\n // index works since it just affects that one comparison).\n const index = isLastMessage ? messages.length - 1 : 0;\n const useCustomRenderer = this.MessageRendererTemplate !== null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'embedded' && useCustomRenderer) {\n // Update existing embedded view from messageRenderer slot\n existing.ref.context.$implicit = message;\n existing.ref.context.message = message;\n existing.ref.markForCheck();\n return;\n }\n if (existing && existing.kind === 'component' && !useCustomRenderer) {\n // Update existing MessageItemComponent in place\n this.updateMessageItemInstance(existing.ref, message, messages, index);\n return;\n }\n if (existing) {\n // Rendering kind changed (e.g. component↔embedded, or a session block was\n // overwritten with a message). Destroy + recreate.\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n this.createRenderedEntry(message, messages, index, key, useCustomRenderer, timelineIndex);\n }\n\n /**\n * Updates an existing `MessageItemComponent` in place — used on the default\n * (non-custom-renderer) path when a message's status / artifacts / agent-run /\n * etc. changes mid-stream.\n */\n private updateMessageItemInstance(\n ref: ComponentRef<MessageItemComponent>,\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number\n ): void {\n const instance = ref.instance;\n const previousMessage = instance.message;\n\n instance.message = message;\n instance.allMessages = messages;\n instance.isProcessing = this.IsProcessing;\n instance.userAvatarMap = this.UserAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.MessageExtraTemplate;\n this.applyMessageItemFeatureFlags(instance);\n\n instance.agentRun = this.AgentRunMap.get(message.ID) || null;\n instance.ratings = this.RatingsMap.get(message.ID);\n instance.attachments = this.AttachmentsMap.get(message.ID) || [];\n\n // After the inputs above, for the same reason as the create path: this can force a\n // synchronous child pass, which would otherwise paint the previous refresh's agent run,\n // ratings and attachments.\n this.applyArtifactsToInstance(instance, message.ID, ref.changeDetectorRef);\n\n // Status change requires explicit markForCheck on the OnPush dynamic child.\n if (previousMessage && previousMessage.Status !== message.Status) {\n ref.changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * Forward the host-level per-message feature gates onto a MessageItemComponent\n * instance. These are static host config (not per-message data), so the same\n * values apply to every message; applied on both the create and in-place-update\n * paths so a mid-session rebind stays consistent.\n */\n private applyMessageItemFeatureFlags(instance: MessageItemComponent): void {\n instance.showAgentRunDetails = this.ShowAgentRunDetails;\n instance.showReactions = this.ShowReactions;\n instance.showMessageRating = this.ShowMessageRating;\n instance.allowPinning = this.AllowPinning;\n instance.allowMessageEdit = this.AllowMessageEdit;\n instance.allowMessageDelete = this.AllowMessageDelete;\n instance.assistantDisplayName = this.AssistantDisplayName;\n instance.assistantAvatarUrl = this.AssistantAvatarUrl;\n }\n\n /**\n * Creates a new rendered entry — either a `MessageItemComponent` (default path)\n * or an `EmbeddedViewRef` from the consumer's `messageRenderer` slot template.\n * Stores the entry in `_renderedMessages` and stamps a back-reference on the\n * message entity.\n */\n private createRenderedEntry(\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number,\n key: string,\n useCustomRenderer: boolean,\n timelineIndex: number\n ): void {\n if (useCustomRenderer && this.MessageRendererTemplate) {\n // The slot directive carries TemplateRef<unknown>; assert the contract here\n // (consumers' `let-message` bindings consume the message context shape below).\n const template = this.MessageRendererTemplate as TemplateRef<MessageRendererContext>;\n const viewRef = this.MessageContainerRef.createEmbeddedView<MessageRendererContext>(\n template,\n { $implicit: message, message },\n { index: timelineIndex }\n );\n this._renderedMessages.set(key, { kind: 'embedded', ref: viewRef });\n // Stamp back-ref for parity with the component path.\n (message as unknown as { _viewRef?: EmbeddedViewRef<MessageRendererContext> })._viewRef = viewRef;\n return;\n }\n\n const componentRef = this.MessageContainerRef.createComponent(MessageItemComponent, { index: timelineIndex });\n const instance = componentRef.instance;\n\n instance.message = message;\n instance.conversation = this.Conversation;\n instance.currentUser = this.CurrentUser;\n instance.allMessages = messages;\n instance.isProcessing = this.IsProcessing;\n instance.userAvatarMap = this.UserAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.MessageExtraTemplate;\n this.applyMessageItemFeatureFlags(instance);\n\n instance.agentRun = this.AgentRunMap.get(message.ID) || null;\n instance.ratings = this.RatingsMap.get(message.ID);\n instance.attachments = this.AttachmentsMap.get(message.ID) || [];\n\n instance.editClicked.subscribe((msg: MJConversationDetailEntity) => this.EditMessage.emit(msg));\n instance.deleteClicked.subscribe((msg: MJConversationDetailEntity) => this.DeleteMessage.emit(msg));\n instance.retryClicked.subscribe((msg: MJConversationDetailEntity) => this.RetryMessage.emit(msg));\n instance.testFeedbackClicked.subscribe((msg: MJConversationDetailEntity) => this.TestFeedbackMessage.emit(msg));\n instance.artifactClicked.subscribe((data: {artifactId: string; versionId?: string}) => this.ArtifactClicked.emit(data));\n instance.messageEdited.subscribe((msg: MJConversationDetailEntity) => this.MessageEdited.emit(msg));\n instance.openEntityRecord.subscribe((data: {entityName: string; compositeKey: CompositeKey}) => this.OpenEntityRecord.emit(data));\n instance.suggestedResponseSelected.subscribe((data: {text: string; customInput?: string}) => this.SuggestedResponseSelected.emit(data));\n instance.attachmentClicked.subscribe((attachment: MessageAttachment) => this.AttachmentClicked.emit(attachment));\n instance.diagnosticRequested.subscribe((messageId: string) => this.DiagnosticRequested.emit(messageId));\n instance.messagePinToggled.subscribe((msg: MJConversationDetailEntity) => this.MessagePinToggled.emit(msg));\n instance.beforeResponseFormSubmitted.subscribe((e: BeforeResponseFormSubmittedEventArgs) => this.BeforeResponseFormSubmitted.emit(e));\n instance.afterResponseFormSubmitted.subscribe((e: AfterResponseFormSubmittedEventArgs) => this.AfterResponseFormSubmitted.emit(e));\n\n if (instance.artifactActionPerformed) {\n instance.artifactActionPerformed.subscribe((data: {action: string; artifactId: string}) => {\n // Parent can handle artifact actions (save, fork, history, share)\n console.log('Artifact action:', data);\n });\n }\n\n // LAST, deliberately. It publishes the pending-artifact list and forces the child's first\n // change-detection pass, which runs ngOnInit/ngAfterViewInit — so agentRun, ratings,\n // attachments and every output subscription above must already be in place. Called earlier,\n // ngAfterViewInit saw agentRun === null and never started the run-duration timer, and the\n // first paint showed the rating control on an already-rated message.\n this.applyArtifactsToInstance(instance, message.ID, componentRef.changeDetectorRef);\n\n this._renderedMessages.set(key, { kind: 'component', ref: componentRef });\n // Preserve the existing back-ref pattern from the skip-chat performance design.\n (message as unknown as { _componentRef?: ComponentRef<MessageItemComponent> })._componentRef = componentRef;\n }\n\n /**\n * Resolves the DISTINCT artifacts for a message (one entry per artifactId at its\n * latest version), lazy-loads them all, and applies them to the rendered\n * message-item. Loads in the background so the UI never blocks.\n *\n * WHY WE SURFACE THEM ALL (design rationale — see PR discussion w/ Pranav & Ethan):\n * A single message can legitimately carry more than one DISTINCT artifact — e.g. a\n * research report PLUS a *standalone* generated infographic. This is deliberately\n * NOT in conflict with the server-side consolidation in AgentRunner\n * (Pranav, 5664b86: \"keep the report's embedded image in the report, not as a\n * duplicate artifact\"): that logic only suppresses media that is *embedded inline*\n * (base64) in another artifact's payload — a true duplicate. Genuinely standalone\n * sibling artifacts (the report uses SVG charts; the infographic is a separate JPEG)\n * are correctly kept as separate artifacts, and the UI must show every one of them.\n *\n * The earlier `artifactList[length - 1]` (\"show only the most recent\") approach\n * (EL-BC, 95492622) assumed consolidation always left exactly one artifact per\n * message; when it legitimately leaves two, that silently hid the report behind the\n * image. Grouping by artifactId (latest version each) shows all distinct artifacts\n * while still collapsing multiple *versions* of the same artifact to one card.\n */\n private applyArtifactsToInstance(\n instance: MessageItemComponent,\n messageId: string,\n childCdRef: ChangeDetectorRef\n ): void {\n const infos = this.resolveDistinctArtifacts(messageId);\n // Advanced on EVERY path, the clear included: a load that settles later compares against this,\n // and a stale response must not repaint an artifact the map has since dropped.\n const generation = (this.artifactLoadGeneration.get(instance) ?? 0) + 1;\n this.artifactLoadGeneration.set(instance, generation);\n\n // Only artifacts that still need a round trip. LazyArtifactInfo.isLoaded answers exactly this,\n // so an artifact already in hand is never announced — announcing everything and filtering\n // downstream re-flashed a placeholder above a rendered card once a second.\n const pending = infos.filter(info => !info.isLoaded);\n const dirty = this.publishPendingArtifacts(instance, infos.length === 0, pending);\n\n // zone.js 0.15: the parent's detectChanges does not reach a dynamically created child.\n if (dirty && !this.isViewDestroyed(childCdRef)) {\n childCdRef.detectChanges();\n }\n if (infos.length > 0) {\n void this.loadArtifactsInto(instance, infos, generation, childCdRef);\n }\n }\n\n /**\n * Publishes what the message should show right now, returning whether anything changed.\n * Clearing is the branch with something to erase, so it counts as dirty whenever the message\n * previously had a card or a placeholder.\n */\n private publishPendingArtifacts(\n instance: MessageItemComponent,\n clear: boolean,\n pending: readonly MessagePendingArtifactRef[]\n ): boolean {\n if (clear) {\n const hadSomething = instance.hasArtifact || instance.pendingArtifacts.length > 0;\n instance.artifacts = [];\n instance.artifact = undefined;\n instance.artifactVersion = undefined;\n instance.pendingArtifacts = [];\n return hadSomething;\n }\n const changed =\n instance.pendingArtifacts.length !== pending.length ||\n pending.some((p, i) => instance.pendingArtifacts[i]?.artifactId !== p.artifactId);\n instance.pendingArtifacts = pending;\n return changed;\n }\n\n /**\n * Loads the artifact and version rows, then hands them to the message — unless a newer refresh\n * has taken over or the view is gone (scrolled out of the timeline, conversation switched), in\n * which case the result is dropped: detectChanges on a destroyed view throws.\n */\n private async loadArtifactsInto(\n instance: MessageItemComponent,\n infos: readonly LazyArtifactInfo[],\n generation: number,\n childCdRef: ChangeDetectorRef\n ): Promise<void> {\n let refs: MessageArtifactRef[] = [];\n try {\n refs = await Promise.all(\n infos.map(info =>\n Promise.all([info.getArtifact(), info.getVersion()]).then(([artifact, version]) => ({ artifact, version }))\n )\n );\n } catch (err) {\n // Fall through with no refs: the placeholders still have to clear, or the message keeps a\n // permanent loading row.\n console.error('Failed to lazy-load artifacts:', err);\n }\n if (this.artifactLoadGeneration.get(instance) !== generation || this.isViewDestroyed(childCdRef)) {\n return;\n }\n if (refs.length > 0) {\n instance.artifacts = refs;\n // Keep the legacy single inputs pointed at the first entry for back-compat.\n instance.artifact = refs[0]?.artifact;\n instance.artifactVersion = refs[0]?.version;\n }\n instance.pendingArtifacts = [];\n childCdRef.detectChanges();\n this.cdRef.detectChanges();\n }\n\n /** Has this child view been destroyed? `ViewRef` declares `destroyed` non-optionally. */\n private isViewDestroyed(ref: ChangeDetectorRef): boolean {\n return (ref as ViewRef).destroyed;\n }\n\n /**\n * Groups a message's artifact list by artifactId, keeping the highest version of\n * each. Multiple versions of the SAME artifact collapse to one card (latest wins),\n * while genuinely distinct artifacts are all retained.\n */\n private resolveDistinctArtifacts(messageId: string): LazyArtifactInfo[] {\n const list = this.ArtifactMap.get(messageId);\n if (!list || list.length === 0) {\n return [];\n }\n return SelectDistinctLatestArtifacts(list);\n }\n\n /**\n * Generates a unique key for a message\n * Uses ID if available, otherwise uses a temporary key\n */\n private getMessageKey(message: MJConversationDetailEntity): string {\n return message.ID && message.ID.length > 0\n ? message.ID\n : `temp_${message.__mj_CreatedAt?.getTime() || Date.now()}`;\n }\n\n /**\n * Determines whether to show the date filter dropdown\n * Only show if conversation is long and spans multiple days\n */\n private updateDateFilterVisibility(): void {\n // `messages` is the loaded WINDOW, not the conversation. The 20-message / 3-day heuristic\n // below reads it as if it were full history, so under windowing a long multi-week thread\n // opens with ~10 items, fails the length check, and never offers date navigation at all —\n // the one case where it is most useful. `HasMoreAbove` is the only windowing-safe signal\n // that more conversation exists above, so it short-circuits the heuristic.\n if (this.HasMoreAbove) {\n this.ShouldShowDateFilter = true;\n return;\n }\n if (!this.messages || this.messages.length < 20) {\n this.ShouldShowDateFilter = false;\n return;\n }\n\n // Check if messages span more than 2 days\n const dates = this.messages\n .map(m => m.__mj_CreatedAt)\n .filter(d => d != null)\n .map(d => new Date(d!).setHours(0, 0, 0, 0));\n\n if (dates.length === 0) {\n this.ShouldShowDateFilter = false;\n return;\n }\n\n const uniqueDates = new Set(dates);\n const daySpan = uniqueDates.size;\n\n // Show filter if conversation has 20+ messages and spans 3+ days\n this.ShouldShowDateFilter = daySpan >= 3;\n }\n\n /**\n * Scrolls the message list to the bottom\n */\n private scrollToBottom(): void {\n if (this.ScrollContainer && this.ScrollContainer.nativeElement) {\n Promise.resolve().then(() => {\n const element = this.ScrollContainer.nativeElement;\n element.scrollTop = element.scrollHeight;\n });\n }\n }\n\n /**\n * Removes a message from the rendered list\n * Called externally when a message is deleted\n */\n public RemoveMessage(message: MJConversationDetailEntity): void {\n const key = this.getMessageKey(message);\n const entry = this._renderedMessages.get(key);\n if (entry) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n }\n\n /** @deprecated Use {@link RemoveMessage}. */\n public removeMessage(message: MJConversationDetailEntity): void {\n return this.RemoveMessage(message);\n }\n}","<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…\" 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>"]}
|