@memberjunction/ng-conversations 6.2.0-edge.0 → 6.2.0-edge.2
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 +43 -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 +1191 -124
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +2816 -785
- 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 +42 -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 +93 -21
- 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 +49 -5
- package/dist/lib/components/message/actionable-commands.component.d.ts.map +1 -1
- package/dist/lib/components/message/actionable-commands.component.js +140 -26
- 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 +613 -74
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +1390 -422
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +490 -29
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +1088 -244
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +297 -29
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +598 -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 +891 -292
- 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 +113 -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 +47 -4
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +85 -20
- 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-liveness-dom.service.d.ts +42 -0
- package/dist/lib/services/conversation-liveness-dom.service.d.ts.map +1 -0
- package/dist/lib/services/conversation-liveness-dom.service.js +74 -0
- package/dist/lib/services/conversation-liveness-dom.service.js.map +1 -0
- 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 +56 -5
- package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
- package/dist/lib/services/ui-command-handler.service.js +113 -16
- 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 +70 -0
- package/dist/lib/utils/agent-turn-routing.d.ts.map +1 -0
- package/dist/lib/utils/agent-turn-routing.js +84 -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/decision-routing.d.ts +68 -0
- package/dist/lib/utils/decision-routing.d.ts.map +1 -0
- package/dist/lib/utils/decision-routing.js +101 -0
- package/dist/lib/utils/decision-routing.js.map +1 -0
- 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 +5 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +8 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +32 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.service.js","sourceRoot":"","sources":["../../../src/lib/services/toast.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAc,MAAM,MAAM,CAAC;;AAenD,MAAM,OAAO,YAAY;IACf,aAAa,GAAG,IAAI,eAAe,CAAU,EAAE,CAAC,CAAC;IAClD,OAAO,GAAwB,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"toast.service.js","sourceRoot":"","sources":["../../../src/lib/services/toast.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport type ToastType = 'success' | 'error' | 'warning' | 'info';\n\nexport interface Toast {\n id: string;\n message: string;\n type: ToastType;\n duration: number;\n timestamp: number;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ToastService {\n private toastsSubject = new BehaviorSubject<Toast[]>([]);\n public Toasts$: Observable<Toast[]> = this.toastsSubject.asObservable();\n\n /** @deprecated Use {@link Toasts$}. */\n public get toasts$(): Observable<Toast[]> {\n return this.Toasts$;\n }\n /** @deprecated Use {@link Toasts$}. */\n public set toasts$(value: Observable<Toast[]>) {\n this.Toasts$ = value;\n }\n\n private idCounter = 0;\n\n /**\n * Show a toast notification\n */\n public Show(message: string, type: ToastType = 'info', duration: number = 3000): string {\n const toast: Toast = {\n id: `toast-${++this.idCounter}-${Date.now()}`,\n message,\n type,\n duration,\n timestamp: Date.now()\n };\n\n const currentToasts = this.toastsSubject.value;\n this.toastsSubject.next([...currentToasts, toast]);\n\n // Auto-dismiss after duration\n if (duration > 0) {\n setTimeout(() => {\n this.Dismiss(toast.id);\n }, duration);\n }\n\n return toast.id;\n }\n\n /** @deprecated Use {@link Show}. */\n public show(message: string, type: ToastType = 'info', duration: number = 3000): string {\n return this.Show(message, type, duration);\n }\n\n /**\n * Show a success toast\n */\n public Success(message: string, duration: number = 3000): string {\n return this.Show(message, 'success', duration);\n }\n\n /** @deprecated Use {@link Success}. */\n public success(message: string, duration: number = 3000): string {\n return this.Success(message, duration);\n }\n\n /**\n * Show an error toast\n */\n public Error(message: string, duration: number = 5000): string {\n return this.Show(message, 'error', duration);\n }\n\n /** @deprecated Use {@link Error}. */\n public error(message: string, duration: number = 5000): string {\n return this.Error(message, duration);\n }\n\n /**\n * Show a warning toast\n */\n public Warning(message: string, duration: number = 4000): string {\n return this.Show(message, 'warning', duration);\n }\n\n /** @deprecated Use {@link Warning}. */\n public warning(message: string, duration: number = 4000): string {\n return this.Warning(message, duration);\n }\n\n /**\n * Show an info toast\n */\n public Info(message: string, duration: number = 3000): string {\n return this.Show(message, 'info', duration);\n }\n\n /** @deprecated Use {@link Info}. */\n public info(message: string, duration: number = 3000): string {\n return this.Info(message, duration);\n }\n\n /**\n * Dismiss a specific toast by ID\n */\n public Dismiss(id: string): void {\n const currentToasts = this.toastsSubject.value;\n const filteredToasts = currentToasts.filter(t => t.id !== id);\n this.toastsSubject.next(filteredToasts);\n }\n\n /** @deprecated Use {@link Dismiss}. */\n public dismiss(id: string): void {\n return this.Dismiss(id);\n }\n\n /**\n * Clear all toasts\n */\n public Clear(): void {\n this.toastsSubject.next([]);\n }\n\n /** @deprecated Use {@link Clear}. */\n public clear(): void {\n return this.Clear();\n }\n}\n"]}
|
|
@@ -6,36 +6,83 @@ export interface ActionableCommandRequest {
|
|
|
6
6
|
command: ActionableCommand;
|
|
7
7
|
conversationId?: string | null;
|
|
8
8
|
conversationDetailId?: string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Set only on the compose:email over-length fallback: whether the draft body is now on the
|
|
11
|
+
* user's clipboard. The copy overwrites whatever the user had copied, so the host must say it
|
|
12
|
+
* happened, and must not claim it when this is false (no body, clipboard unavailable over plain
|
|
13
|
+
* HTTP, or denied by permissions policy).
|
|
14
|
+
*/
|
|
15
|
+
DraftCopiedToClipboard?: boolean;
|
|
9
16
|
}
|
|
10
17
|
/**
|
|
11
18
|
* Service for handling UI commands from agents.
|
|
12
19
|
*
|
|
13
|
-
* Generic commands (open:url
|
|
14
|
-
* App-specific commands (open:resource
|
|
20
|
+
* Generic commands (open:url, and compose:email while it fits in a mailto: URL) are handled
|
|
21
|
+
* directly by this service. App-specific commands (open:resource, and the compose:email
|
|
22
|
+
* over-length fallback) are emitted for the host application to handle.
|
|
15
23
|
*/
|
|
16
24
|
export declare class UICommandHandlerService {
|
|
17
25
|
private dataCacheService;
|
|
18
26
|
/**
|
|
19
27
|
* Event emitted when an actionable command requires host-app handling.
|
|
20
|
-
*
|
|
28
|
+
*
|
|
29
|
+
* open:resource is always emitted. compose:email is emitted ONLY as a fallback, when the draft
|
|
30
|
+
* is too long for a mailto: URL and the host must open the draft artifact instead; a draft
|
|
31
|
+
* within the limit is handled here and never reaches the host. On that fallback the host also
|
|
32
|
+
* owns telling the user why their mail client did not open, because only the host knows whether
|
|
33
|
+
* a draft artifact opened (see {@link ActionableCommandRequest.DraftCopiedToClipboard}).
|
|
34
|
+
* open:url is always handled here.
|
|
21
35
|
*/
|
|
22
|
-
|
|
36
|
+
ActionableCommandRequested: EventEmitter<ActionableCommandRequest>;
|
|
37
|
+
/** @deprecated Use {@link ActionableCommandRequested}. */
|
|
38
|
+
get actionableCommandRequested(): EventEmitter<ActionableCommandRequest>;
|
|
39
|
+
/** @deprecated Use {@link ActionableCommandRequested}. */
|
|
40
|
+
set actionableCommandRequested(value: EventEmitter<ActionableCommandRequest>);
|
|
23
41
|
/**
|
|
24
42
|
* Event emitted when an automatic command should be executed
|
|
25
43
|
* Host application should subscribe to this and handle the command appropriately
|
|
26
44
|
*/
|
|
27
|
-
|
|
45
|
+
AutomaticCommandRequested: EventEmitter<AutomaticCommand>;
|
|
46
|
+
/** @deprecated Use {@link AutomaticCommandRequested}. */
|
|
47
|
+
get automaticCommandRequested(): EventEmitter<AutomaticCommand>;
|
|
48
|
+
/** @deprecated Use {@link AutomaticCommandRequested}. */
|
|
49
|
+
set automaticCommandRequested(value: EventEmitter<AutomaticCommand>);
|
|
28
50
|
constructor(dataCacheService: DataCacheService);
|
|
29
51
|
/**
|
|
30
52
|
* Execute an actionable command (triggered by user clicking a button).
|
|
31
53
|
* Generic commands like open:url are handled directly; others are emitted to the host.
|
|
32
54
|
*/
|
|
55
|
+
ExecuteActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void>;
|
|
56
|
+
/** @deprecated Use {@link ExecuteActionableCommand}. */
|
|
33
57
|
executeActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void>;
|
|
34
58
|
/**
|
|
35
59
|
* Handle open:url commands directly by opening the URL in a browser tab.
|
|
36
60
|
* Data URIs are converted to Blob URLs because Chrome blocks window.open with data: URIs.
|
|
37
61
|
*/
|
|
38
62
|
private handleOpenUrl;
|
|
63
|
+
/**
|
|
64
|
+
* Best-effort copy of an over-length draft's body, so the text is not lost even when the host
|
|
65
|
+
* cannot open the draft artifact.
|
|
66
|
+
*
|
|
67
|
+
* Never rejects, so a clipboard that is unavailable (plain HTTP) or denied by permissions policy
|
|
68
|
+
* cannot stop the fallback. Nothing on the click path awaits before writeText is called, so it
|
|
69
|
+
* still runs inside the click's user activation; the fallback then awaits the outcome only so
|
|
70
|
+
* the host's notice can say whether the copy happened.
|
|
71
|
+
*
|
|
72
|
+
* @returns true only when the body is on the clipboard, so the host never claims a copy that
|
|
73
|
+
* did not happen.
|
|
74
|
+
*/
|
|
75
|
+
private copyDraftBody;
|
|
76
|
+
/**
|
|
77
|
+
* Open the user's own mail client with a compose:email draft's fields pre-filled, via a
|
|
78
|
+
* synthesized anchor click.
|
|
79
|
+
*
|
|
80
|
+
* NOTHING IS SENT HERE. The agent drafted; the user sends. This only opens a compose window.
|
|
81
|
+
*
|
|
82
|
+
* Deliberately not window.open: Chrome treats window.open with a non-http scheme as a popup and
|
|
83
|
+
* strands an about:blank tab behind the compose window.
|
|
84
|
+
*/
|
|
85
|
+
private openMailto;
|
|
39
86
|
/**
|
|
40
87
|
* Open a data URI by converting it to a Blob URL.
|
|
41
88
|
* Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.
|
|
@@ -45,10 +92,14 @@ export declare class UICommandHandlerService {
|
|
|
45
92
|
* Execute an automatic command (runs immediately without user interaction)
|
|
46
93
|
* Special handling: refresh:data commands execute locally, others emit to host
|
|
47
94
|
*/
|
|
95
|
+
ExecuteAutomaticCommand(command: AutomaticCommand): Promise<void>;
|
|
96
|
+
/** @deprecated Use {@link ExecuteAutomaticCommand}. */
|
|
48
97
|
executeAutomaticCommand(command: AutomaticCommand): Promise<void>;
|
|
49
98
|
/**
|
|
50
99
|
* Execute all automatic commands from an agent result
|
|
51
100
|
*/
|
|
101
|
+
ExecuteAutomaticCommands(commands: AutomaticCommand[]): Promise<void>;
|
|
102
|
+
/** @deprecated Use {@link ExecuteAutomaticCommands}. */
|
|
52
103
|
executeAutomaticCommands(commands: AutomaticCommand[]): Promise<void>;
|
|
53
104
|
/**
|
|
54
105
|
* Handle refreshing data (entity data or caches)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-command-handler.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"ui-command-handler.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAKjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;;AAExD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;GAMG;AACH,qBAGa,uBAAuB;IAsChC,OAAO,CAAC,gBAAgB;IArC1B;;;;;;;;;OASG;IACI,0BAA0B,yCAAgD;IAEjF,0DAA0D;IAC1D,IAAW,0BAA0B,2CAEpC;IACD,0DAA0D;IAC1D,IAAW,0BAA0B,CAAC,KAAK,wCAAA,EAE1C;IAED;;;OAGG;IACI,yBAAyB,iCAAwC;IAExE,yDAAyD;IACzD,IAAW,yBAAyB,mCAEnC;IACD,yDAAyD;IACzD,IAAW,yBAAyB,CAAC,KAAK,gCAAA,EAEzC;gBAGS,gBAAgB,EAAE,gBAAgB;IAG5C;;;OAGG;IACU,wBAAwB,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCpI,wDAAwD;IAC3C,wBAAwB,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpI;;;OAGG;IACH,OAAO,CAAC,aAAa;IAYrB;;;;;;;;;;;OAWG;YACW,aAAa;IAY3B;;;;;;;;OAQG;IACH,OAAO,CAAC,UAAU;IASlB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;OAGG;IACU,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9E,uDAAuD;IAC1C,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E;;OAEG;IACU,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAclF,wDAAwD;IAC3C,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlF;;;OAGG;YACW,iBAAiB;yCArNpB,uBAAuB;6CAAvB,uBAAuB;CAsOnC"}
|
|
@@ -1,24 +1,48 @@
|
|
|
1
1
|
import { Injectable, EventEmitter } from '@angular/core';
|
|
2
|
+
import { BuildMailtoURL } from '@memberjunction/ai-core-plus';
|
|
2
3
|
import * as i0 from "@angular/core";
|
|
3
4
|
import * as i1 from "./data-cache.service";
|
|
4
5
|
/**
|
|
5
6
|
* Service for handling UI commands from agents.
|
|
6
7
|
*
|
|
7
|
-
* Generic commands (open:url
|
|
8
|
-
* App-specific commands (open:resource
|
|
8
|
+
* Generic commands (open:url, and compose:email while it fits in a mailto: URL) are handled
|
|
9
|
+
* directly by this service. App-specific commands (open:resource, and the compose:email
|
|
10
|
+
* over-length fallback) are emitted for the host application to handle.
|
|
9
11
|
*/
|
|
10
12
|
export class UICommandHandlerService {
|
|
11
13
|
dataCacheService;
|
|
12
14
|
/**
|
|
13
15
|
* Event emitted when an actionable command requires host-app handling.
|
|
14
|
-
*
|
|
16
|
+
*
|
|
17
|
+
* open:resource is always emitted. compose:email is emitted ONLY as a fallback, when the draft
|
|
18
|
+
* is too long for a mailto: URL and the host must open the draft artifact instead; a draft
|
|
19
|
+
* within the limit is handled here and never reaches the host. On that fallback the host also
|
|
20
|
+
* owns telling the user why their mail client did not open, because only the host knows whether
|
|
21
|
+
* a draft artifact opened (see {@link ActionableCommandRequest.DraftCopiedToClipboard}).
|
|
22
|
+
* open:url is always handled here.
|
|
15
23
|
*/
|
|
16
|
-
|
|
24
|
+
ActionableCommandRequested = new EventEmitter();
|
|
25
|
+
/** @deprecated Use {@link ActionableCommandRequested}. */
|
|
26
|
+
get actionableCommandRequested() {
|
|
27
|
+
return this.ActionableCommandRequested;
|
|
28
|
+
}
|
|
29
|
+
/** @deprecated Use {@link ActionableCommandRequested}. */
|
|
30
|
+
set actionableCommandRequested(value) {
|
|
31
|
+
this.ActionableCommandRequested = value;
|
|
32
|
+
}
|
|
17
33
|
/**
|
|
18
34
|
* Event emitted when an automatic command should be executed
|
|
19
35
|
* Host application should subscribe to this and handle the command appropriately
|
|
20
36
|
*/
|
|
21
|
-
|
|
37
|
+
AutomaticCommandRequested = new EventEmitter();
|
|
38
|
+
/** @deprecated Use {@link AutomaticCommandRequested}. */
|
|
39
|
+
get automaticCommandRequested() {
|
|
40
|
+
return this.AutomaticCommandRequested;
|
|
41
|
+
}
|
|
42
|
+
/** @deprecated Use {@link AutomaticCommandRequested}. */
|
|
43
|
+
set automaticCommandRequested(value) {
|
|
44
|
+
this.AutomaticCommandRequested = value;
|
|
45
|
+
}
|
|
22
46
|
constructor(dataCacheService) {
|
|
23
47
|
this.dataCacheService = dataCacheService;
|
|
24
48
|
}
|
|
@@ -26,19 +50,43 @@ export class UICommandHandlerService {
|
|
|
26
50
|
* Execute an actionable command (triggered by user clicking a button).
|
|
27
51
|
* Generic commands like open:url are handled directly; others are emitted to the host.
|
|
28
52
|
*/
|
|
29
|
-
async
|
|
53
|
+
async ExecuteActionableCommand(command, origin) {
|
|
30
54
|
if (command.type === 'open:url') {
|
|
31
55
|
this.handleOpenUrl(command);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const request = {
|
|
59
|
+
command,
|
|
60
|
+
conversationId: origin?.conversationId ?? null,
|
|
61
|
+
conversationDetailId: origin?.conversationDetailId ?? null
|
|
62
|
+
};
|
|
63
|
+
if (command.type === 'compose:email') {
|
|
64
|
+
const { url, withinLimit } = BuildMailtoURL(command);
|
|
65
|
+
if (withinLimit) {
|
|
66
|
+
this.openMailto(url);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Too long for a mailto: URL. We do NOT open it: a mail client past its limit does not
|
|
70
|
+
// refuse the URL, it opens a draft with the body SILENTLY TRUNCATED and the user sends half
|
|
71
|
+
// a message without noticing. Falls through to the host, which opens the full draft
|
|
72
|
+
// artifact and tells the user what happened.
|
|
73
|
+
request.DraftCopiedToClipboard = await this.copyDraftBody(command);
|
|
74
|
+
}
|
|
75
|
+
// open:resource (and the compose:email fallback above) require app-specific navigation.
|
|
76
|
+
// compose:email is logged by TYPE ONLY: its body is free-text member correspondence, and the
|
|
77
|
+
// whole command object would otherwise land in the browser console and any console-forwarding
|
|
78
|
+
// telemetry.
|
|
79
|
+
if (command.type === 'compose:email') {
|
|
80
|
+
console.log('📤 Emitting actionable command for host app:', command.type);
|
|
32
81
|
}
|
|
33
82
|
else {
|
|
34
|
-
// open:resource requires app-specific navigation — emit for host to handle
|
|
35
83
|
console.log('📤 Emitting actionable command for host app:', command);
|
|
36
|
-
this.actionableCommandRequested.emit({
|
|
37
|
-
command,
|
|
38
|
-
conversationId: origin?.conversationId ?? null,
|
|
39
|
-
conversationDetailId: origin?.conversationDetailId ?? null
|
|
40
|
-
});
|
|
41
84
|
}
|
|
85
|
+
this.ActionableCommandRequested.emit(request);
|
|
86
|
+
}
|
|
87
|
+
/** @deprecated Use {@link ExecuteActionableCommand}. */
|
|
88
|
+
async executeActionableCommand(command, origin) {
|
|
89
|
+
return this.ExecuteActionableCommand(command, origin);
|
|
42
90
|
}
|
|
43
91
|
/**
|
|
44
92
|
* Handle open:url commands directly by opening the URL in a browser tab.
|
|
@@ -55,6 +103,47 @@ export class UICommandHandlerService {
|
|
|
55
103
|
window.open(url, target, target === '_blank' ? 'noopener,noreferrer' : undefined);
|
|
56
104
|
}
|
|
57
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Best-effort copy of an over-length draft's body, so the text is not lost even when the host
|
|
108
|
+
* cannot open the draft artifact.
|
|
109
|
+
*
|
|
110
|
+
* Never rejects, so a clipboard that is unavailable (plain HTTP) or denied by permissions policy
|
|
111
|
+
* cannot stop the fallback. Nothing on the click path awaits before writeText is called, so it
|
|
112
|
+
* still runs inside the click's user activation; the fallback then awaits the outcome only so
|
|
113
|
+
* the host's notice can say whether the copy happened.
|
|
114
|
+
*
|
|
115
|
+
* @returns true only when the body is on the clipboard, so the host never claims a copy that
|
|
116
|
+
* did not happen.
|
|
117
|
+
*/
|
|
118
|
+
async copyDraftBody(command) {
|
|
119
|
+
if (!command.body || !navigator.clipboard) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
await navigator.clipboard.writeText(command.body);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Open the user's own mail client with a compose:email draft's fields pre-filled, via a
|
|
132
|
+
* synthesized anchor click.
|
|
133
|
+
*
|
|
134
|
+
* NOTHING IS SENT HERE. The agent drafted; the user sends. This only opens a compose window.
|
|
135
|
+
*
|
|
136
|
+
* Deliberately not window.open: Chrome treats window.open with a non-http scheme as a popup and
|
|
137
|
+
* strands an about:blank tab behind the compose window.
|
|
138
|
+
*/
|
|
139
|
+
openMailto(url) {
|
|
140
|
+
const a = document.createElement('a');
|
|
141
|
+
a.href = url;
|
|
142
|
+
a.style.display = 'none';
|
|
143
|
+
document.body.appendChild(a);
|
|
144
|
+
a.click();
|
|
145
|
+
document.body.removeChild(a);
|
|
146
|
+
}
|
|
58
147
|
/**
|
|
59
148
|
* Open a data URI by converting it to a Blob URL.
|
|
60
149
|
* Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.
|
|
@@ -76,7 +165,7 @@ export class UICommandHandlerService {
|
|
|
76
165
|
* Execute an automatic command (runs immediately without user interaction)
|
|
77
166
|
* Special handling: refresh:data commands execute locally, others emit to host
|
|
78
167
|
*/
|
|
79
|
-
async
|
|
168
|
+
async ExecuteAutomaticCommand(command) {
|
|
80
169
|
console.log('Executing automatic command:', command);
|
|
81
170
|
if (command.type === 'refresh:data') {
|
|
82
171
|
// Handle data refresh locally as it's a generic operation
|
|
@@ -85,25 +174,33 @@ export class UICommandHandlerService {
|
|
|
85
174
|
else {
|
|
86
175
|
// Emit other automatic commands (like notifications) for host to handle
|
|
87
176
|
console.log('📤 Emitting automatic command for host app:', command);
|
|
88
|
-
this.
|
|
177
|
+
this.AutomaticCommandRequested.emit(command);
|
|
89
178
|
}
|
|
90
179
|
}
|
|
180
|
+
/** @deprecated Use {@link ExecuteAutomaticCommand}. */
|
|
181
|
+
async executeAutomaticCommand(command) {
|
|
182
|
+
return this.ExecuteAutomaticCommand(command);
|
|
183
|
+
}
|
|
91
184
|
/**
|
|
92
185
|
* Execute all automatic commands from an agent result
|
|
93
186
|
*/
|
|
94
|
-
async
|
|
187
|
+
async ExecuteAutomaticCommands(commands) {
|
|
95
188
|
if (!commands || commands.length === 0) {
|
|
96
189
|
return;
|
|
97
190
|
}
|
|
98
191
|
for (const command of commands) {
|
|
99
192
|
try {
|
|
100
|
-
await this.
|
|
193
|
+
await this.ExecuteAutomaticCommand(command);
|
|
101
194
|
}
|
|
102
195
|
catch (error) {
|
|
103
196
|
console.error('Error executing automatic command:', command, error);
|
|
104
197
|
}
|
|
105
198
|
}
|
|
106
199
|
}
|
|
200
|
+
/** @deprecated Use {@link ExecuteAutomaticCommands}. */
|
|
201
|
+
async executeAutomaticCommands(commands) {
|
|
202
|
+
return this.ExecuteAutomaticCommands(commands);
|
|
203
|
+
}
|
|
107
204
|
/**
|
|
108
205
|
* Handle refreshing data (entity data or caches)
|
|
109
206
|
* This is handled locally as it's a generic operation that doesn't require host app knowledge
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-command-handler.service.js","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, EventEmitter } from '@angular/core';\nimport { ActionableCommand, AutomaticCommand, RefreshDataCommand, OpenURLCommand } from '@memberjunction/ai-core-plus';\nimport { DataCacheService } from './data-cache.service';\n\nexport interface ActionableCommandRequest {\n command: ActionableCommand;\n conversationId?: string | null;\n conversationDetailId?: string | null;\n}\n\n/**\n * Service for handling UI commands from agents.\n *\n * Generic commands (open:url) are handled directly by this service.\n * App-specific commands (open:resource) are emitted for the host application to handle.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class UICommandHandlerService {\n /**\n * Event emitted when an actionable command requires host-app handling.\n * Currently only open:resource commands are emitted — open:url is handled directly.\n */\n public actionableCommandRequested = new EventEmitter<ActionableCommandRequest>();\n\n /**\n * Event emitted when an automatic command should be executed\n * Host application should subscribe to this and handle the command appropriately\n */\n public automaticCommandRequested = new EventEmitter<AutomaticCommand>();\n\n constructor(\n private dataCacheService: DataCacheService\n ) {}\n\n /**\n * Execute an actionable command (triggered by user clicking a button).\n * Generic commands like open:url are handled directly; others are emitted to the host.\n */\n public async executeActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void> {\n if (command.type === 'open:url') {\n this.handleOpenUrl(command);\n } else {\n // open:resource requires app-specific navigation — emit for host to handle\n console.log('📤 Emitting actionable command for host app:', command);\n this.actionableCommandRequested.emit({\n command,\n conversationId: origin?.conversationId ?? null,\n conversationDetailId: origin?.conversationDetailId ?? null\n });\n }\n }\n\n /**\n * Handle open:url commands directly by opening the URL in a browser tab.\n * Data URIs are converted to Blob URLs because Chrome blocks window.open with data: URIs.\n */\n private handleOpenUrl(command: OpenURLCommand): void {\n const url = command.url;\n const newTab = command.newTab !== false;\n\n if (url.startsWith('data:')) {\n this.openDataUri(url);\n } else {\n const target = newTab ? '_blank' : '_self';\n window.open(url, target, target === '_blank' ? 'noopener,noreferrer' : undefined);\n }\n }\n\n /**\n * Open a data URI by converting it to a Blob URL.\n * Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.\n */\n private openDataUri(dataUri: string): void {\n const [header, base64Data] = dataUri.split(',');\n const mimeMatch = header.match(/data:([^;]+)/);\n const mimeType = mimeMatch ? mimeMatch[1] : 'application/octet-stream';\n\n const byteString = atob(base64Data);\n const byteArray = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n byteArray[i] = byteString.charCodeAt(i);\n }\n\n const blob = new Blob([byteArray], { type: mimeType });\n const blobUrl = URL.createObjectURL(blob);\n window.open(blobUrl, '_blank');\n }\n\n /**\n * Execute an automatic command (runs immediately without user interaction)\n * Special handling: refresh:data commands execute locally, others emit to host\n */\n public async executeAutomaticCommand(command: AutomaticCommand): Promise<void> {\n console.log('Executing automatic command:', command);\n\n if (command.type === 'refresh:data') {\n // Handle data refresh locally as it's a generic operation\n await this.handleRefreshData(command);\n } else {\n // Emit other automatic commands (like notifications) for host to handle\n console.log('📤 Emitting automatic command for host app:', command);\n this.automaticCommandRequested.emit(command);\n }\n }\n\n /**\n * Execute all automatic commands from an agent result\n */\n public async executeAutomaticCommands(commands: AutomaticCommand[]): Promise<void> {\n if (!commands || commands.length === 0) {\n return;\n }\n\n for (const command of commands) {\n try {\n await this.executeAutomaticCommand(command);\n } catch (error) {\n console.error('Error executing automatic command:', command, error);\n }\n }\n }\n\n /**\n * Handle refreshing data (entity data or caches)\n * This is handled locally as it's a generic operation that doesn't require host app knowledge\n */\n private async handleRefreshData(command: RefreshDataCommand): Promise<void> {\n const { scope, entityNames, cacheName } = command;\n\n if (scope === 'entity' && entityNames && entityNames.length > 0) {\n // Refresh specific entity data\n for (const entityName of entityNames) {\n await this.dataCacheService.refreshEntity(entityName);\n }\n console.log('Refreshed entity data:', entityNames);\n } else if (scope === 'cache' && cacheName) {\n // Refresh a specific cache\n await this.dataCacheService.refreshCache(cacheName);\n console.log('Refreshed cache:', cacheName);\n } else {\n console.warn('Invalid refresh:data command parameters:', command);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ui-command-handler.service.js","sourceRoot":"","sources":["../../../src/lib/services/ui-command-handler.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, EventEmitter } from '@angular/core';\nimport {\n ActionableCommand,\n AutomaticCommand,\n RefreshDataCommand,\n OpenURLCommand,\n ComposeEmailCommand,\n BuildMailtoURL\n} from '@memberjunction/ai-core-plus';\nimport { DataCacheService } from './data-cache.service';\n\nexport interface ActionableCommandRequest {\n command: ActionableCommand;\n conversationId?: string | null;\n conversationDetailId?: string | null;\n /**\n * Set only on the compose:email over-length fallback: whether the draft body is now on the\n * user's clipboard. The copy overwrites whatever the user had copied, so the host must say it\n * happened, and must not claim it when this is false (no body, clipboard unavailable over plain\n * HTTP, or denied by permissions policy).\n */\n DraftCopiedToClipboard?: boolean;\n}\n\n/**\n * Service for handling UI commands from agents.\n *\n * Generic commands (open:url, and compose:email while it fits in a mailto: URL) are handled\n * directly by this service. App-specific commands (open:resource, and the compose:email\n * over-length fallback) are emitted for the host application to handle.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class UICommandHandlerService {\n /**\n * Event emitted when an actionable command requires host-app handling.\n *\n * open:resource is always emitted. compose:email is emitted ONLY as a fallback, when the draft\n * is too long for a mailto: URL and the host must open the draft artifact instead; a draft\n * within the limit is handled here and never reaches the host. On that fallback the host also\n * owns telling the user why their mail client did not open, because only the host knows whether\n * a draft artifact opened (see {@link ActionableCommandRequest.DraftCopiedToClipboard}).\n * open:url is always handled here.\n */\n public ActionableCommandRequested = new EventEmitter<ActionableCommandRequest>();\n\n /** @deprecated Use {@link ActionableCommandRequested}. */\n public get actionableCommandRequested() {\n return this.ActionableCommandRequested;\n }\n /** @deprecated Use {@link ActionableCommandRequested}. */\n public set actionableCommandRequested(value) {\n this.ActionableCommandRequested = value;\n }\n\n /**\n * Event emitted when an automatic command should be executed\n * Host application should subscribe to this and handle the command appropriately\n */\n public AutomaticCommandRequested = new EventEmitter<AutomaticCommand>();\n\n /** @deprecated Use {@link AutomaticCommandRequested}. */\n public get automaticCommandRequested() {\n return this.AutomaticCommandRequested;\n }\n /** @deprecated Use {@link AutomaticCommandRequested}. */\n public set automaticCommandRequested(value) {\n this.AutomaticCommandRequested = value;\n }\n\n constructor(\n private dataCacheService: DataCacheService\n ) {}\n\n /**\n * Execute an actionable command (triggered by user clicking a button).\n * Generic commands like open:url are handled directly; others are emitted to the host.\n */\n public async ExecuteActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void> {\n if (command.type === 'open:url') {\n this.handleOpenUrl(command);\n return;\n }\n\n const request: ActionableCommandRequest = {\n command,\n conversationId: origin?.conversationId ?? null,\n conversationDetailId: origin?.conversationDetailId ?? null\n };\n\n if (command.type === 'compose:email') {\n const { url, withinLimit } = BuildMailtoURL(command);\n if (withinLimit) {\n this.openMailto(url);\n return;\n }\n // Too long for a mailto: URL. We do NOT open it: a mail client past its limit does not\n // refuse the URL, it opens a draft with the body SILENTLY TRUNCATED and the user sends half\n // a message without noticing. Falls through to the host, which opens the full draft\n // artifact and tells the user what happened.\n request.DraftCopiedToClipboard = await this.copyDraftBody(command);\n }\n\n // open:resource (and the compose:email fallback above) require app-specific navigation.\n // compose:email is logged by TYPE ONLY: its body is free-text member correspondence, and the\n // whole command object would otherwise land in the browser console and any console-forwarding\n // telemetry.\n if (command.type === 'compose:email') {\n console.log('📤 Emitting actionable command for host app:', command.type);\n } else {\n console.log('📤 Emitting actionable command for host app:', command);\n }\n this.ActionableCommandRequested.emit(request);\n }\n\n /** @deprecated Use {@link ExecuteActionableCommand}. */\n public async executeActionableCommand(command: ActionableCommand, origin?: Omit<ActionableCommandRequest, 'command'>): Promise<void> {\n return this.ExecuteActionableCommand(command, origin);\n }\n\n /**\n * Handle open:url commands directly by opening the URL in a browser tab.\n * Data URIs are converted to Blob URLs because Chrome blocks window.open with data: URIs.\n */\n private handleOpenUrl(command: OpenURLCommand): void {\n const url = command.url;\n const newTab = command.newTab !== false;\n\n if (url.startsWith('data:')) {\n this.openDataUri(url);\n } else {\n const target = newTab ? '_blank' : '_self';\n window.open(url, target, target === '_blank' ? 'noopener,noreferrer' : undefined);\n }\n }\n\n /**\n * Best-effort copy of an over-length draft's body, so the text is not lost even when the host\n * cannot open the draft artifact.\n *\n * Never rejects, so a clipboard that is unavailable (plain HTTP) or denied by permissions policy\n * cannot stop the fallback. Nothing on the click path awaits before writeText is called, so it\n * still runs inside the click's user activation; the fallback then awaits the outcome only so\n * the host's notice can say whether the copy happened.\n *\n * @returns true only when the body is on the clipboard, so the host never claims a copy that\n * did not happen.\n */\n private async copyDraftBody(command: ComposeEmailCommand): Promise<boolean> {\n if (!command.body || !navigator.clipboard) {\n return false;\n }\n try {\n await navigator.clipboard.writeText(command.body);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Open the user's own mail client with a compose:email draft's fields pre-filled, via a\n * synthesized anchor click.\n *\n * NOTHING IS SENT HERE. The agent drafted; the user sends. This only opens a compose window.\n *\n * Deliberately not window.open: Chrome treats window.open with a non-http scheme as a popup and\n * strands an about:blank tab behind the compose window.\n */\n private openMailto(url: string): void {\n const a = document.createElement('a');\n a.href = url;\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n }\n\n /**\n * Open a data URI by converting it to a Blob URL.\n * Chrome blocks window.open('data:...') for security, so we create a Blob URL instead.\n */\n private openDataUri(dataUri: string): void {\n const [header, base64Data] = dataUri.split(',');\n const mimeMatch = header.match(/data:([^;]+)/);\n const mimeType = mimeMatch ? mimeMatch[1] : 'application/octet-stream';\n\n const byteString = atob(base64Data);\n const byteArray = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n byteArray[i] = byteString.charCodeAt(i);\n }\n\n const blob = new Blob([byteArray], { type: mimeType });\n const blobUrl = URL.createObjectURL(blob);\n window.open(blobUrl, '_blank');\n }\n\n /**\n * Execute an automatic command (runs immediately without user interaction)\n * Special handling: refresh:data commands execute locally, others emit to host\n */\n public async ExecuteAutomaticCommand(command: AutomaticCommand): Promise<void> {\n console.log('Executing automatic command:', command);\n\n if (command.type === 'refresh:data') {\n // Handle data refresh locally as it's a generic operation\n await this.handleRefreshData(command);\n } else {\n // Emit other automatic commands (like notifications) for host to handle\n console.log('📤 Emitting automatic command for host app:', command);\n this.AutomaticCommandRequested.emit(command);\n }\n }\n\n /** @deprecated Use {@link ExecuteAutomaticCommand}. */\n public async executeAutomaticCommand(command: AutomaticCommand): Promise<void> {\n return this.ExecuteAutomaticCommand(command);\n }\n\n /**\n * Execute all automatic commands from an agent result\n */\n public async ExecuteAutomaticCommands(commands: AutomaticCommand[]): Promise<void> {\n if (!commands || commands.length === 0) {\n return;\n }\n\n for (const command of commands) {\n try {\n await this.ExecuteAutomaticCommand(command);\n } catch (error) {\n console.error('Error executing automatic command:', command, error);\n }\n }\n }\n\n /** @deprecated Use {@link ExecuteAutomaticCommands}. */\n public async executeAutomaticCommands(commands: AutomaticCommand[]): Promise<void> {\n return this.ExecuteAutomaticCommands(commands);\n }\n\n /**\n * Handle refreshing data (entity data or caches)\n * This is handled locally as it's a generic operation that doesn't require host app knowledge\n */\n private async handleRefreshData(command: RefreshDataCommand): Promise<void> {\n const { scope, entityNames, cacheName } = command;\n\n if (scope === 'entity' && entityNames && entityNames.length > 0) {\n // Refresh specific entity data\n for (const entityName of entityNames) {\n await this.dataCacheService.refreshEntity(entityName);\n }\n console.log('Refreshed entity data:', entityNames);\n } else if (scope === 'cache' && cacheName) {\n // Refresh a specific cache\n await this.dataCacheService.refreshCache(cacheName);\n console.log('Refreshed cache:', cacheName);\n } else {\n console.warn('Invalid refresh:data command parameters:', command);\n }\n }\n}\n"]}
|
|
@@ -30,9 +30,9 @@ export interface AgentArtifactRow {
|
|
|
30
30
|
export interface AgentArtifactSummary {
|
|
31
31
|
artifactId: string;
|
|
32
32
|
artifactName: string;
|
|
33
|
-
|
|
33
|
+
ArtifactType: string;
|
|
34
34
|
/** Newest first, so `versions[0]` is the latest. */
|
|
35
|
-
|
|
35
|
+
Versions: Array<{
|
|
36
36
|
versionId: string;
|
|
37
37
|
versionNumber: number;
|
|
38
38
|
versionName: string | null;
|
|
@@ -33,12 +33,12 @@ export function GroupVersionsByArtifact(versions, artifactsById) {
|
|
|
33
33
|
summary = {
|
|
34
34
|
artifactId: version.ArtifactID,
|
|
35
35
|
artifactName: artifact.Name,
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
ArtifactType: artifact.Type,
|
|
37
|
+
Versions: []
|
|
38
38
|
};
|
|
39
39
|
byArtifact.set(version.ArtifactID, summary);
|
|
40
40
|
}
|
|
41
|
-
summary.
|
|
41
|
+
summary.Versions.push({
|
|
42
42
|
versionId: version.ID,
|
|
43
43
|
versionNumber: version.VersionNumber,
|
|
44
44
|
versionName: version.Name
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-artifact-summary.js","sourceRoot":"","sources":["../../../src/lib/utils/agent-artifact-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiCH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CACnC,QAA4C,EAC5C,aAAoD;IAEpD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAE3D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,6EAA6E;YAC7E,8EAA8E;YAC9E,wEAAwE;YACxE,SAAS;QACb,CAAC;QACD,IAAI,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,GAAG;gBACN,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,QAAQ,EAAE,EAAE;aACf,CAAC;YACF,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAClB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,IAAI;SAC5B,CAAC,CAAC;IACP,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC","sourcesContent":["/**\n * Grouping for the \"Prior Artifacts Created by This Agent\" block fed to the Check Sage Intent\n * prompt.\n *\n * PURE (no Angular, no entities, no provider) so the ordering contract below is unit-testable\n * without the service's DI — same reason `conversation-detail-window.ts` and `date-jump.ts`\n * live out here rather than on their consumers.\n */\n\n/** The version fields the grouping needs. Structural, so the RunView row type satisfies it. */\nexport interface AgentArtifactVersionRow {\n ID: string;\n ArtifactID: string;\n VersionNumber: number;\n Name: string | null;\n}\n\n/** The artifact fields the prompt prints. */\nexport interface AgentArtifactRow {\n ID: string;\n Name: string;\n Type: string;\n}\n\n/**\n * One artifact an agent produced in this conversation, with its versions newest-first.\n *\n * Deliberately narrower than the array-scan shape it replaces, which also carried `runId`,\n * `artifactDescription`, `versionDescription` and `createdAt` — none of which the intent\n * prompt ever read. Dropping them is what lets the caller resolve this without joining back\n * to agent runs, turning a four-table reconstruction into two reads.\n */\nexport interface AgentArtifactSummary {\n artifactId: string
|
|
1
|
+
{"version":3,"file":"agent-artifact-summary.js","sourceRoot":"","sources":["../../../src/lib/utils/agent-artifact-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiCH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CACnC,QAA4C,EAC5C,aAAoD;IAEpD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAE3D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,6EAA6E;YAC7E,8EAA8E;YAC9E,wEAAwE;YACxE,SAAS;QACb,CAAC;QACD,IAAI,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,GAAG;gBACN,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,YAAY,EAAE,QAAQ,CAAC,IAAI;gBAC3B,QAAQ,EAAE,EAAE;aACf,CAAC;YACF,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAClB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,IAAI;SAC5B,CAAC,CAAC;IACP,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC","sourcesContent":["/**\n * Grouping for the \"Prior Artifacts Created by This Agent\" block fed to the Check Sage Intent\n * prompt.\n *\n * PURE (no Angular, no entities, no provider) so the ordering contract below is unit-testable\n * without the service's DI — same reason `conversation-detail-window.ts` and `date-jump.ts`\n * live out here rather than on their consumers.\n */\n\n/** The version fields the grouping needs. Structural, so the RunView row type satisfies it. */\nexport interface AgentArtifactVersionRow {\n ID: string;\n ArtifactID: string;\n VersionNumber: number;\n Name: string | null;\n}\n\n/** The artifact fields the prompt prints. */\nexport interface AgentArtifactRow {\n ID: string;\n Name: string;\n Type: string;\n}\n\n/**\n * One artifact an agent produced in this conversation, with its versions newest-first.\n *\n * Deliberately narrower than the array-scan shape it replaces, which also carried `runId`,\n * `artifactDescription`, `versionDescription` and `createdAt` — none of which the intent\n * prompt ever read. Dropping them is what lets the caller resolve this without joining back\n * to agent runs, turning a four-table reconstruction into two reads.\n */\nexport interface AgentArtifactSummary {\n artifactId: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined\n artifactName: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined\n ArtifactType: string;\n /** Newest first, so `versions[0]` is the latest. */\n Versions: Array<{ versionId: string; versionNumber: number; versionName: string | null }>;\n}\n\n/**\n * Folds versions into per-artifact summaries.\n *\n * NO SORT, and that is deliberate rather than an omission. The caller reads versions\n * `__mj_CreatedAt DESC`, so inserting in arrival order leaves each artifact's versions\n * newest-first AND leaves the Map ordered by whichever artifact was touched most recently —\n * which is exactly what the explicit sort in the array-scan version used to compute. The\n * assumption is load-bearing and invisible, so it is pinned by tests.\n *\n * @param versions - Artifact versions, newest first\n * @param artifactsById - The artifact rows behind those versions\n */\nexport function GroupVersionsByArtifact(\n versions: readonly AgentArtifactVersionRow[],\n artifactsById: ReadonlyMap<string, AgentArtifactRow>\n): AgentArtifactSummary[] {\n const byArtifact = new Map<string, AgentArtifactSummary>();\n\n for (const version of versions) {\n const artifact = artifactsById.get(version.ArtifactID);\n if (!artifact) {\n // Mirrors the stored query's INNER JOIN semantics. A version can outlive the\n // artifact row the caller can read; emitting a summary with an undefined name\n // would put the string \"undefined\" straight into the classifier prompt.\n continue;\n }\n let summary = byArtifact.get(version.ArtifactID);\n if (!summary) {\n summary = {\n artifactId: version.ArtifactID,\n artifactName: artifact.Name,\n ArtifactType: artifact.Type,\n Versions: []\n };\n byArtifact.set(version.ArtifactID, summary);\n }\n summary.Versions.push({\n versionId: version.ID,\n versionNumber: version.VersionNumber,\n versionName: version.Name\n });\n }\n return [...byArtifact.values()];\n}\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure routing rules for an agent turn: which agent answers a message, and whether
|
|
3
|
+
* any does. Kept free of Angular and of I/O so the whole matrix (reply mode × mention × allowed
|
|
4
|
+
* list × route) is testable directly; `MessageInputComponent` supplies the candidates.
|
|
5
|
+
*
|
|
6
|
+
* @module @memberjunction/ng-conversations
|
|
7
|
+
*/
|
|
8
|
+
import type { AgentReplyMode, AgentTurnTarget } from '../models/agent-turn.model';
|
|
9
|
+
/** The agent each route would use for one message, before the host's rules are applied. */
|
|
10
|
+
export interface AgentTurnCandidates {
|
|
11
|
+
/** Agents the message tags, in the order they appear. */
|
|
12
|
+
MentionedAgentIds: readonly string[];
|
|
13
|
+
/** The last agent that answered in the conversation, other than the conversation manager. */
|
|
14
|
+
ContinuityAgentId: string | null;
|
|
15
|
+
/**
|
|
16
|
+
* True when a routing decision put `ContinuityAgentId` there in place of the last agent that
|
|
17
|
+
* answered. The turn is then labelled `DecisionRouted` instead of `Continuity`.
|
|
18
|
+
*/
|
|
19
|
+
ContinuityDecisionRouted?: boolean;
|
|
20
|
+
/** The agent pinned on the conversation. */
|
|
21
|
+
ConversationDefaultAgentId: string | null;
|
|
22
|
+
/** The host's `DefaultAgentId` input. */
|
|
23
|
+
HostDefaultAgentId: string | null;
|
|
24
|
+
/** MJ's conversation manager agent. */
|
|
25
|
+
ConversationManagerAgentId: string | null;
|
|
26
|
+
}
|
|
27
|
+
/** The host's rules for the chat. */
|
|
28
|
+
export interface AgentTurnRules {
|
|
29
|
+
/** When a message starts a turn. */
|
|
30
|
+
ReplyMode: AgentReplyMode;
|
|
31
|
+
/** The agents that may answer. Null allows every agent. */
|
|
32
|
+
AllowedAgentIDs: readonly string[] | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Picks the agent and route for one message, or null when no turn starts.
|
|
36
|
+
*
|
|
37
|
+
* The order is MJ's: the first tagged agent the host allows, then (under `Always` only) the last
|
|
38
|
+
* agent that answered, the conversation's pinned agent, the host's default agent, and the
|
|
39
|
+
* conversation manager. A candidate the host doesn't allow is skipped. A continuity candidate that
|
|
40
|
+
* a routing decision chose (`ContinuityDecisionRouted`) takes the `DecisionRouted` label.
|
|
41
|
+
*
|
|
42
|
+
* A continuity or default candidate that `isKnownAgent` doesn't recognise falls back to the
|
|
43
|
+
* conversation manager, as MJ always has, rather than to the next route. A tagged agent is taken
|
|
44
|
+
* as tagged.
|
|
45
|
+
*
|
|
46
|
+
* @param candidates The agent each route would use.
|
|
47
|
+
* @param rules The host's reply mode and allowed list.
|
|
48
|
+
* @param isKnownAgent True when the agent exists in the client's agent catalog.
|
|
49
|
+
*/
|
|
50
|
+
export declare function ResolveAgentTurn(candidates: AgentTurnCandidates, rules: AgentTurnRules, isKnownAgent: (agentId: string) => boolean): AgentTurnTarget | null;
|
|
51
|
+
/** A task-graph step that runs an agent, as the conversation manager emits it. */
|
|
52
|
+
interface AgentTaskStep {
|
|
53
|
+
kind: string;
|
|
54
|
+
configuration?: {
|
|
55
|
+
agentName?: string;
|
|
56
|
+
} | object;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The agent names in a task graph that the host doesn't allow. The conversation manager can
|
|
60
|
+
* answer with a multi-step workflow instead of a single delegation; each `Agent` step names the
|
|
61
|
+
* agent that runs it, so the allowed list has to hold there too.
|
|
62
|
+
*
|
|
63
|
+
* @param steps The graph's tasks.
|
|
64
|
+
* @param allowedAgentIDs The host's allowed list. Null allows every agent.
|
|
65
|
+
* @param resolveAgentId Maps an agent name to its ID, or null when no such agent exists.
|
|
66
|
+
* @returns The disallowed names, each once, in the order they appear. Empty when all are allowed.
|
|
67
|
+
*/
|
|
68
|
+
export declare function FindDisallowedTaskGraphAgents(steps: ReadonlyArray<AgentTaskStep>, allowedAgentIDs: readonly string[] | null, resolveAgentId: (agentName: string) => string | null): string[];
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=agent-turn-routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-turn-routing.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/agent-turn-routing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAkB,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElG,2FAA2F;AAC3F,MAAM,WAAW,mBAAmB;IAChC,yDAAyD;IACzD,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,6FAA6F;IAC7F,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,4CAA4C;IAC5C,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,yCAAyC;IACzC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,uCAAuC;IACvC,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC3B,oCAAoC;IACpC,SAAS,EAAE,cAAc,CAAC;IAC1B,2DAA2D;IAC3D,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC5B,UAAU,EAAE,mBAAmB,EAC/B,KAAK,EAAE,cAAc,EACrB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAC3C,eAAe,GAAG,IAAI,CAsBxB;AAUD,kFAAkF;AAClF,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;CACnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CACzC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,EACnC,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,EACzC,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACrD,MAAM,EAAE,CAYV"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure routing rules for an agent turn: which agent answers a message, and whether
|
|
3
|
+
* any does. Kept free of Angular and of I/O so the whole matrix (reply mode × mention × allowed
|
|
4
|
+
* list × route) is testable directly; `MessageInputComponent` supplies the candidates.
|
|
5
|
+
*
|
|
6
|
+
* @module @memberjunction/ng-conversations
|
|
7
|
+
*/
|
|
8
|
+
import { IsAgentAllowed } from '@memberjunction/ai-core-plus';
|
|
9
|
+
/**
|
|
10
|
+
* Picks the agent and route for one message, or null when no turn starts.
|
|
11
|
+
*
|
|
12
|
+
* The order is MJ's: the first tagged agent the host allows, then (under `Always` only) the last
|
|
13
|
+
* agent that answered, the conversation's pinned agent, the host's default agent, and the
|
|
14
|
+
* conversation manager. A candidate the host doesn't allow is skipped. A continuity candidate that
|
|
15
|
+
* a routing decision chose (`ContinuityDecisionRouted`) takes the `DecisionRouted` label.
|
|
16
|
+
*
|
|
17
|
+
* A continuity or default candidate that `isKnownAgent` doesn't recognise falls back to the
|
|
18
|
+
* conversation manager, as MJ always has, rather than to the next route. A tagged agent is taken
|
|
19
|
+
* as tagged.
|
|
20
|
+
*
|
|
21
|
+
* @param candidates The agent each route would use.
|
|
22
|
+
* @param rules The host's reply mode and allowed list.
|
|
23
|
+
* @param isKnownAgent True when the agent exists in the client's agent catalog.
|
|
24
|
+
*/
|
|
25
|
+
export function ResolveAgentTurn(candidates, rules, isKnownAgent) {
|
|
26
|
+
const mentioned = candidates.MentionedAgentIds.find(id => IsAgentAllowed(id, rules.AllowedAgentIDs));
|
|
27
|
+
if (mentioned) {
|
|
28
|
+
return { AgentId: mentioned, Route: 'Mention' };
|
|
29
|
+
}
|
|
30
|
+
if (rules.ReplyMode === 'MentionOnly') {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const implicitRoutes = [
|
|
34
|
+
[candidates.ContinuityDecisionRouted ? 'DecisionRouted' : 'Continuity', candidates.ContinuityAgentId],
|
|
35
|
+
['ConversationDefault', candidates.ConversationDefaultAgentId],
|
|
36
|
+
['HostDefault', candidates.HostDefaultAgentId],
|
|
37
|
+
];
|
|
38
|
+
for (const [route, agentId] of implicitRoutes) {
|
|
39
|
+
if (agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)) {
|
|
40
|
+
return isKnownAgent(agentId)
|
|
41
|
+
? { AgentId: agentId, Route: route }
|
|
42
|
+
: conversationManagerTarget(candidates, rules);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return conversationManagerTarget(candidates, rules);
|
|
46
|
+
}
|
|
47
|
+
/** The conversation manager's turn, when there is one and the host allows it. */
|
|
48
|
+
function conversationManagerTarget(candidates, rules) {
|
|
49
|
+
const agentId = candidates.ConversationManagerAgentId;
|
|
50
|
+
return agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)
|
|
51
|
+
? { AgentId: agentId, Route: 'ConversationManager' }
|
|
52
|
+
: null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The agent names in a task graph that the host doesn't allow. The conversation manager can
|
|
56
|
+
* answer with a multi-step workflow instead of a single delegation; each `Agent` step names the
|
|
57
|
+
* agent that runs it, so the allowed list has to hold there too.
|
|
58
|
+
*
|
|
59
|
+
* @param steps The graph's tasks.
|
|
60
|
+
* @param allowedAgentIDs The host's allowed list. Null allows every agent.
|
|
61
|
+
* @param resolveAgentId Maps an agent name to its ID, or null when no such agent exists.
|
|
62
|
+
* @returns The disallowed names, each once, in the order they appear. Empty when all are allowed.
|
|
63
|
+
*/
|
|
64
|
+
export function FindDisallowedTaskGraphAgents(steps, allowedAgentIDs, resolveAgentId) {
|
|
65
|
+
if (allowedAgentIDs == null) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
const disallowed = [];
|
|
69
|
+
for (const step of steps) {
|
|
70
|
+
const agentName = step.kind === 'Agent' ? agentNameOf(step.configuration) : null;
|
|
71
|
+
if (agentName && !IsAgentAllowed(resolveAgentId(agentName), allowedAgentIDs) && !disallowed.includes(agentName)) {
|
|
72
|
+
disallowed.push(agentName);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return disallowed;
|
|
76
|
+
}
|
|
77
|
+
/** The `agentName` of an Agent step's configuration, when it has one. */
|
|
78
|
+
function agentNameOf(configuration) {
|
|
79
|
+
if (configuration && 'agentName' in configuration && typeof configuration.agentName === 'string') {
|
|
80
|
+
return configuration.agentName;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=agent-turn-routing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-turn-routing.js","sourceRoot":"","sources":["../../../src/lib/utils/agent-turn-routing.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Pure routing rules for an agent turn: which agent answers a message, and whether\n * any does. Kept free of Angular and of I/O so the whole matrix (reply mode × mention × allowed\n * list × route) is testable directly; `MessageInputComponent` supplies the candidates.\n *\n * @module @memberjunction/ng-conversations\n */\n\nimport { IsAgentAllowed } from '@memberjunction/ai-core-plus';\nimport type { AgentReplyMode, AgentTurnRoute, AgentTurnTarget } from '../models/agent-turn.model';\n\n/** The agent each route would use for one message, before the host's rules are applied. */\nexport interface AgentTurnCandidates {\n /** Agents the message tags, in the order they appear. */\n MentionedAgentIds: readonly string[];\n /** The last agent that answered in the conversation, other than the conversation manager. */\n ContinuityAgentId: string | null;\n /**\n * True when a routing decision put `ContinuityAgentId` there in place of the last agent that\n * answered. The turn is then labelled `DecisionRouted` instead of `Continuity`.\n */\n ContinuityDecisionRouted?: boolean;\n /** The agent pinned on the conversation. */\n ConversationDefaultAgentId: string | null;\n /** The host's `DefaultAgentId` input. */\n HostDefaultAgentId: string | null;\n /** MJ's conversation manager agent. */\n ConversationManagerAgentId: string | null;\n}\n\n/** The host's rules for the chat. */\nexport interface AgentTurnRules {\n /** When a message starts a turn. */\n ReplyMode: AgentReplyMode;\n /** The agents that may answer. Null allows every agent. */\n AllowedAgentIDs: readonly string[] | null;\n}\n\n/**\n * Picks the agent and route for one message, or null when no turn starts.\n *\n * The order is MJ's: the first tagged agent the host allows, then (under `Always` only) the last\n * agent that answered, the conversation's pinned agent, the host's default agent, and the\n * conversation manager. A candidate the host doesn't allow is skipped. A continuity candidate that\n * a routing decision chose (`ContinuityDecisionRouted`) takes the `DecisionRouted` label.\n *\n * A continuity or default candidate that `isKnownAgent` doesn't recognise falls back to the\n * conversation manager, as MJ always has, rather than to the next route. A tagged agent is taken\n * as tagged.\n *\n * @param candidates The agent each route would use.\n * @param rules The host's reply mode and allowed list.\n * @param isKnownAgent True when the agent exists in the client's agent catalog.\n */\nexport function ResolveAgentTurn(\n candidates: AgentTurnCandidates,\n rules: AgentTurnRules,\n isKnownAgent: (agentId: string) => boolean\n): AgentTurnTarget | null {\n const mentioned = candidates.MentionedAgentIds.find(id => IsAgentAllowed(id, rules.AllowedAgentIDs));\n if (mentioned) {\n return { AgentId: mentioned, Route: 'Mention' };\n }\n if (rules.ReplyMode === 'MentionOnly') {\n return null;\n }\n\n const implicitRoutes: ReadonlyArray<[AgentTurnRoute, string | null]> = [\n [candidates.ContinuityDecisionRouted ? 'DecisionRouted' : 'Continuity', candidates.ContinuityAgentId],\n ['ConversationDefault', candidates.ConversationDefaultAgentId],\n ['HostDefault', candidates.HostDefaultAgentId],\n ];\n for (const [route, agentId] of implicitRoutes) {\n if (agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)) {\n return isKnownAgent(agentId)\n ? { AgentId: agentId, Route: route }\n : conversationManagerTarget(candidates, rules);\n }\n }\n return conversationManagerTarget(candidates, rules);\n}\n\n/** The conversation manager's turn, when there is one and the host allows it. */\nfunction conversationManagerTarget(candidates: AgentTurnCandidates, rules: AgentTurnRules): AgentTurnTarget | null {\n const agentId = candidates.ConversationManagerAgentId;\n return agentId && IsAgentAllowed(agentId, rules.AllowedAgentIDs)\n ? { AgentId: agentId, Route: 'ConversationManager' }\n : null;\n}\n\n/** A task-graph step that runs an agent, as the conversation manager emits it. */\ninterface AgentTaskStep {\n kind: string;\n configuration?: { agentName?: string } | object;\n}\n\n/**\n * The agent names in a task graph that the host doesn't allow. The conversation manager can\n * answer with a multi-step workflow instead of a single delegation; each `Agent` step names the\n * agent that runs it, so the allowed list has to hold there too.\n *\n * @param steps The graph's tasks.\n * @param allowedAgentIDs The host's allowed list. Null allows every agent.\n * @param resolveAgentId Maps an agent name to its ID, or null when no such agent exists.\n * @returns The disallowed names, each once, in the order they appear. Empty when all are allowed.\n */\nexport function FindDisallowedTaskGraphAgents(\n steps: ReadonlyArray<AgentTaskStep>,\n allowedAgentIDs: readonly string[] | null,\n resolveAgentId: (agentName: string) => string | null\n): string[] {\n if (allowedAgentIDs == null) {\n return [];\n }\n const disallowed: string[] = [];\n for (const step of steps) {\n const agentName = step.kind === 'Agent' ? agentNameOf(step.configuration) : null;\n if (agentName && !IsAgentAllowed(resolveAgentId(agentName), allowedAgentIDs) && !disallowed.includes(agentName)) {\n disallowed.push(agentName);\n }\n }\n return disallowed;\n}\n\n/** The `agentName` of an Agent step's configuration, when it has one. */\nfunction agentNameOf(configuration: AgentTaskStep['configuration']): string | null {\n if (configuration && 'agentName' in configuration && typeof configuration.agentName === 'string') {\n return configuration.agentName;\n }\n return null;\n}\n"]}
|