@memberjunction/ng-conversations 5.43.0 → 5.45.0
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/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts +0 -1
- 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 +56 -52
- package/dist/lib/components/active-tasks/active-tasks-panel.component.js.map +1 -1
- package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +3 -1
- package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/artifact/artifact-share-modal.component.js +52 -52
- package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.js +10 -14
- package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-share-modal.component.d.ts +3 -1
- package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-share-modal.component.js +56 -56
- package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts +3 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.js +10 -7
- package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
- package/dist/lib/components/collection/collection-view.component.d.ts +3 -1
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +29 -41
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts +4 -0
- package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.js +134 -166
- package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
- package/dist/lib/components/composer/ai-composer.component.d.ts +103 -0
- package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -0
- package/dist/lib/components/composer/ai-composer.component.js +263 -0
- package/dist/lib/components/composer/ai-composer.component.js.map +1 -0
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +76 -12
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +522 -158
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
- package/dist/lib/components/conversation/pinned-messages-panel.component.js +6 -9
- package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
- package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/library/library-full-view.component.js +20 -24
- package/dist/lib/components/library/library-full-view.component.js.map +1 -1
- package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
- package/dist/lib/components/members/members-modal.component.js +10 -11
- package/dist/lib/components/members/members-modal.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +87 -23
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +245 -158
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +11 -3
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +73 -21
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.js +6 -9
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts +4 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.js +9 -4
- package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +45 -0
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +10 -0
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts +46 -0
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/channels/client-context-channel.js +174 -0
- package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -0
- package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts +123 -0
- package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js +397 -0
- package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js.map +1 -0
- package/dist/lib/components/realtime/media/media-channel-state.d.ts +103 -0
- package/dist/lib/components/realtime/media/media-channel-state.d.ts.map +1 -0
- package/dist/lib/components/realtime/media/media-channel-state.js +143 -0
- package/dist/lib/components/realtime/media/media-channel-state.js.map +1 -0
- package/dist/lib/components/realtime/media/media-channel-tools.d.ts +24 -0
- package/dist/lib/components/realtime/media/media-channel-tools.d.ts.map +1 -0
- package/dist/lib/components/realtime/media/media-channel-tools.js +107 -0
- package/dist/lib/components/realtime/media/media-channel-tools.js.map +1 -0
- package/dist/lib/components/realtime/media/media-channel.d.ts +89 -0
- package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/media/media-channel.js +253 -0
- package/dist/lib/components/realtime/media/media-channel.js.map +1 -0
- package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts +141 -0
- package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/media/realtime-media-surface.component.js +574 -0
- package/dist/lib/components/realtime/media/realtime-media-surface.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +59 -14
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.js +277 -74
- package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +28 -27
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.js +144 -143
- package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +12 -0
- package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-picker.component.js +105 -43
- package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.d.ts +41 -7
- package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.js +216 -102
- package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +0 -2
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.js +67 -71
- package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +364 -44
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.js +839 -153
- package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-state.d.ts +5 -5
- package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts +70 -0
- package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-tab-style.js +115 -0
- package/dist/lib/components/realtime/realtime-surface-tab-style.js.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +55 -57
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js +165 -143
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +80 -71
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js +83 -113
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
- package/dist/lib/components/realtime/realtime-ui-config.d.ts +270 -0
- package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-ui-config.js +212 -0
- package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -0
- package/dist/lib/components/search/search-panel.component.d.ts +2 -0
- package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
- package/dist/lib/components/search/search-panel.component.js +92 -101
- package/dist/lib/components/search/search-panel.component.js.map +1 -1
- package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/share/share-modal.component.js +10 -11
- package/dist/lib/components/share/share-modal.component.js.map +1 -1
- package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
- package/dist/lib/components/shared/user-picker.component.js +12 -15
- package/dist/lib/components/shared/user-picker.component.js.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +11 -3
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.js +34 -10
- package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
- package/dist/lib/components/sidebar/routines-section.component.d.ts +73 -0
- package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -0
- package/dist/lib/components/sidebar/routines-section.component.js +211 -0
- package/dist/lib/components/sidebar/routines-section.component.js.map +1 -0
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +12 -0
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js +37 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +16 -5
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +51 -31
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/composer-plugins/agent-mention.provider.d.ts +16 -0
- package/dist/lib/composer-plugins/agent-mention.provider.d.ts.map +1 -0
- package/dist/lib/composer-plugins/agent-mention.provider.js +28 -0
- package/dist/lib/composer-plugins/agent-mention.provider.js.map +1 -0
- package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +20 -0
- package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -0
- package/dist/lib/composer-plugins/base-conversation-mention.provider.js +32 -0
- package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -0
- package/dist/lib/composer-plugins/load-composer-plugins.d.ts +9 -0
- package/dist/lib/composer-plugins/load-composer-plugins.d.ts.map +1 -0
- package/dist/lib/composer-plugins/load-composer-plugins.js +17 -0
- package/dist/lib/composer-plugins/load-composer-plugins.js.map +1 -0
- package/dist/lib/composer-plugins/record-mention.provider.d.ts +14 -0
- package/dist/lib/composer-plugins/record-mention.provider.d.ts.map +1 -0
- package/dist/lib/composer-plugins/record-mention.provider.js +26 -0
- package/dist/lib/composer-plugins/record-mention.provider.js.map +1 -0
- package/dist/lib/composer-plugins/skill-command.provider.d.ts +15 -0
- package/dist/lib/composer-plugins/skill-command.provider.d.ts.map +1 -0
- package/dist/lib/composer-plugins/skill-command.provider.js +27 -0
- package/dist/lib/composer-plugins/skill-command.provider.js.map +1 -0
- package/dist/lib/conversations.module.d.ts +68 -64
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js +69 -18
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/models/conversation-state.model.d.ts +6 -3
- 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/services/conversation-agent.service.d.ts +9 -2
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +26 -2
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-attachment.service.js.map +1 -1
- package/dist/lib/services/mention-autocomplete.service.d.ts +42 -19
- package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
- package/dist/lib/services/mention-autocomplete.service.js +113 -18
- package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
- package/dist/lib/services/realtime-audio-recorder.d.ts +143 -0
- package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -0
- package/dist/lib/services/realtime-audio-recorder.js +379 -0
- package/dist/lib/services/realtime-audio-recorder.js.map +1 -0
- package/dist/lib/services/realtime-pcm-wav.d.ts +75 -0
- package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -0
- package/dist/lib/services/realtime-pcm-wav.js +205 -0
- package/dist/lib/services/realtime-pcm-wav.js.map +1 -0
- package/dist/lib/services/realtime-session-review.service.d.ts +28 -1
- package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
- package/dist/lib/services/realtime-session-review.service.js +12 -3
- package/dist/lib/services/realtime-session-review.service.js.map +1 -1
- package/dist/lib/services/realtime-session.service.d.ts +210 -20
- package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
- package/dist/lib/services/realtime-session.service.js +452 -21
- package/dist/lib/services/realtime-session.service.js.map +1 -1
- package/dist/lib/services/realtime-sessions-adapter.js +1 -1
- package/dist/lib/services/realtime-sessions-adapter.js.map +1 -1
- package/dist/lib/services/ui-command-handler.service.d.ts +7 -2
- package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
- package/dist/lib/services/ui-command-handler.service.js +6 -2
- package/dist/lib/services/ui-command-handler.service.js.map +1 -1
- package/dist/lib/utils/plan-mode-preference.d.ts +62 -0
- package/dist/lib/utils/plan-mode-preference.d.ts.map +1 -0
- package/dist/lib/utils/plan-mode-preference.js +130 -0
- package/dist/lib/utils/plan-mode-preference.js.map +1 -0
- package/dist/public-api.d.ts +29 -3
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +46 -3
- package/dist/public-api.js.map +1 -1
- package/package.json +30 -26
- package/dist/__tests__/attachment-badge.test.d.ts +0 -2
- package/dist/__tests__/attachment-badge.test.d.ts.map +0 -1
- package/dist/__tests__/attachment-badge.test.js +0 -66
- package/dist/__tests__/attachment-badge.test.js.map +0 -1
- package/dist/__tests__/channel-optional-surface.test.d.ts +0 -2
- package/dist/__tests__/channel-optional-surface.test.d.ts.map +0 -1
- package/dist/__tests__/channel-optional-surface.test.js +0 -53
- package/dist/__tests__/channel-optional-surface.test.js.map +0 -1
- package/dist/__tests__/chat-events.test.d.ts +0 -14
- package/dist/__tests__/chat-events.test.d.ts.map +0 -1
- package/dist/__tests__/chat-events.test.js +0 -109
- package/dist/__tests__/chat-events.test.js.map +0 -1
- package/dist/__tests__/collections-full-view.test.d.ts +0 -2
- package/dist/__tests__/collections-full-view.test.d.ts.map +0 -1
- package/dist/__tests__/collections-full-view.test.js +0 -225
- package/dist/__tests__/collections-full-view.test.js.map +0 -1
- package/dist/__tests__/conversation-cache.test.d.ts +0 -2
- package/dist/__tests__/conversation-cache.test.d.ts.map +0 -1
- package/dist/__tests__/conversation-cache.test.js +0 -233
- package/dist/__tests__/conversation-cache.test.js.map +0 -1
- package/dist/__tests__/conversation-naming.test.d.ts +0 -2
- package/dist/__tests__/conversation-naming.test.d.ts.map +0 -1
- package/dist/__tests__/conversation-naming.test.js +0 -110
- package/dist/__tests__/conversation-naming.test.js.map +0 -1
- package/dist/__tests__/delegation-result-parser.test.d.ts +0 -2
- package/dist/__tests__/delegation-result-parser.test.d.ts.map +0 -1
- package/dist/__tests__/delegation-result-parser.test.js +0 -107
- package/dist/__tests__/delegation-result-parser.test.js.map +0 -1
- package/dist/__tests__/distinct-artifacts.test.d.ts +0 -2
- package/dist/__tests__/distinct-artifacts.test.d.ts.map +0 -1
- package/dist/__tests__/distinct-artifacts.test.js +0 -56
- package/dist/__tests__/distinct-artifacts.test.js.map +0 -1
- package/dist/__tests__/event-wiring.test.d.ts +0 -15
- package/dist/__tests__/event-wiring.test.d.ts.map +0 -1
- package/dist/__tests__/event-wiring.test.js +0 -100
- package/dist/__tests__/event-wiring.test.js.map +0 -1
- package/dist/__tests__/index.test.d.ts +0 -2
- package/dist/__tests__/index.test.d.ts.map +0 -1
- package/dist/__tests__/index.test.js +0 -7
- package/dist/__tests__/index.test.js.map +0 -1
- package/dist/__tests__/narration-template.test.d.ts +0 -2
- package/dist/__tests__/narration-template.test.d.ts.map +0 -1
- package/dist/__tests__/narration-template.test.js +0 -76
- package/dist/__tests__/narration-template.test.js.map +0 -1
- package/dist/__tests__/notification-model.test.d.ts +0 -2
- package/dist/__tests__/notification-model.test.d.ts.map +0 -1
- package/dist/__tests__/notification-model.test.js +0 -68
- package/dist/__tests__/notification-model.test.js.map +0 -1
- package/dist/__tests__/realtime-agent-picker-models.test.d.ts +0 -2
- package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-agent-picker-models.test.js +0 -49
- package/dist/__tests__/realtime-agent-picker-models.test.js.map +0 -1
- package/dist/__tests__/realtime-audio-visuals.test.d.ts +0 -2
- package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-audio-visuals.test.js +0 -123
- package/dist/__tests__/realtime-audio-visuals.test.js.map +0 -1
- package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +0 -2
- package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-delegation-card-cancel.test.js +0 -48
- package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +0 -1
- package/dist/__tests__/realtime-disclosure.test.d.ts +0 -2
- package/dist/__tests__/realtime-disclosure.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-disclosure.test.js +0 -164
- package/dist/__tests__/realtime-disclosure.test.js.map +0 -1
- package/dist/__tests__/realtime-pairing.test.d.ts +0 -2
- package/dist/__tests__/realtime-pairing.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-pairing.test.js +0 -207
- package/dist/__tests__/realtime-pairing.test.js.map +0 -1
- package/dist/__tests__/realtime-review-lifecycle.test.d.ts +0 -2
- package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-review-lifecycle.test.js +0 -154
- package/dist/__tests__/realtime-review-lifecycle.test.js.map +0 -1
- package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-cancel-usage.test.js +0 -230
- package/dist/__tests__/realtime-session-cancel-usage.test.js.map +0 -1
- package/dist/__tests__/realtime-session-channels.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-channels.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-channels.test.js +0 -252
- package/dist/__tests__/realtime-session-channels.test.js.map +0 -1
- package/dist/__tests__/realtime-session-client-tools.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-client-tools.test.js +0 -103
- package/dist/__tests__/realtime-session-client-tools.test.js.map +0 -1
- package/dist/__tests__/realtime-session-minimized.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-minimized.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-minimized.test.js +0 -32
- package/dist/__tests__/realtime-session-minimized.test.js.map +0 -1
- package/dist/__tests__/realtime-session-mint.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-mint.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-mint.test.js +0 -69
- package/dist/__tests__/realtime-session-mint.test.js.map +0 -1
- package/dist/__tests__/realtime-session-policy.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-policy.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-policy.test.js +0 -303
- package/dist/__tests__/realtime-session-policy.test.js.map +0 -1
- package/dist/__tests__/realtime-session-review.service.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-review.service.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-review.service.test.js +0 -743
- package/dist/__tests__/realtime-session-review.service.test.js.map +0 -1
- package/dist/__tests__/realtime-session-state.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-state.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-state.test.js +0 -83
- package/dist/__tests__/realtime-session-state.test.js.map +0 -1
- package/dist/__tests__/realtime-session-timeline-card.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-timeline-card.test.js +0 -106
- package/dist/__tests__/realtime-session-timeline-card.test.js.map +0 -1
- package/dist/__tests__/realtime-session-timeline.test.d.ts +0 -2
- package/dist/__tests__/realtime-session-timeline.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-session-timeline.test.js +0 -142
- package/dist/__tests__/realtime-session-timeline.test.js.map +0 -1
- package/dist/__tests__/realtime-sessions-adapter.test.d.ts +0 -19
- package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-sessions-adapter.test.js +0 -188
- package/dist/__tests__/realtime-sessions-adapter.test.js.map +0 -1
- package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +0 -2
- package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-surface-panel-prefs.test.js +0 -100
- package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +0 -1
- package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +0 -2
- package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +0 -1
- package/dist/__tests__/realtime-surface-tabs-model.test.js +0 -193
- package/dist/__tests__/realtime-surface-tabs-model.test.js.map +0 -1
- package/dist/__tests__/remote-browser-audio-player.test.d.ts +0 -2
- package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +0 -1
- package/dist/__tests__/remote-browser-audio-player.test.js +0 -137
- package/dist/__tests__/remote-browser-audio-player.test.js.map +0 -1
- package/dist/__tests__/remote-browser-channel.test.d.ts +0 -2
- package/dist/__tests__/remote-browser-channel.test.d.ts.map +0 -1
- package/dist/__tests__/remote-browser-channel.test.js +0 -585
- package/dist/__tests__/remote-browser-channel.test.js.map +0 -1
- package/dist/__tests__/search-service.test.d.ts +0 -2
- package/dist/__tests__/search-service.test.d.ts.map +0 -1
- package/dist/__tests__/search-service.test.js +0 -114
- package/dist/__tests__/search-service.test.js.map +0 -1
- package/dist/__tests__/slot-defaults.test.d.ts +0 -24
- package/dist/__tests__/slot-defaults.test.d.ts.map +0 -1
- package/dist/__tests__/slot-defaults.test.js +0 -63
- package/dist/__tests__/slot-defaults.test.js.map +0 -1
- package/dist/__tests__/toast-service.test.d.ts +0 -2
- package/dist/__tests__/toast-service.test.d.ts.map +0 -1
- package/dist/__tests__/toast-service.test.js +0 -143
- package/dist/__tests__/toast-service.test.js.map +0 -1
- package/dist/__tests__/user-authorization.test.d.ts +0 -2
- package/dist/__tests__/user-authorization.test.d.ts.map +0 -1
- package/dist/__tests__/user-authorization.test.js +0 -97
- package/dist/__tests__/user-authorization.test.js.map +0 -1
- package/dist/__tests__/voice-session-narration.test.d.ts +0 -2
- package/dist/__tests__/voice-session-narration.test.d.ts.map +0 -1
- package/dist/__tests__/voice-session-narration.test.js +0 -609
- package/dist/__tests__/voice-session-narration.test.js.map +0 -1
- package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +0 -2
- package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +0 -1
- package/dist/__tests__/whiteboard-artifact-viewer.test.js +0 -101
- package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +0 -1
- package/dist/__tests__/whiteboard-channel.test.d.ts +0 -2
- package/dist/__tests__/whiteboard-channel.test.d.ts.map +0 -1
- package/dist/__tests__/whiteboard-channel.test.js +0 -260
- package/dist/__tests__/whiteboard-channel.test.js.map +0 -1
- package/dist/__tests__/whiteboard-restore-state.test.d.ts +0 -2
- package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +0 -1
- package/dist/__tests__/whiteboard-restore-state.test.js +0 -108
- package/dist/__tests__/whiteboard-restore-state.test.js.map +0 -1
- package/dist/lib/components/mention/mention-dropdown.component.d.ts +0 -53
- package/dist/lib/components/mention/mention-dropdown.component.d.ts.map +0 -1
- package/dist/lib/components/mention/mention-dropdown.component.js +0 -276
- package/dist/lib/components/mention/mention-dropdown.component.js.map +0 -1
- package/dist/lib/components/mention/mention-editor.component.d.ts +0 -256
- package/dist/lib/components/mention/mention-editor.component.d.ts.map +0 -1
- package/dist/lib/components/mention/mention-editor.component.js +0 -1233
- package/dist/lib/components/mention/mention-editor.component.js.map +0 -1
- package/dist/lib/components/message/message-input-box.component.d.ts +0 -137
- package/dist/lib/components/message/message-input-box.component.d.ts.map +0 -1
- package/dist/lib/components/message/message-input-box.component.js +0 -321
- package/dist/lib/components/message/message-input-box.component.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-overlay.component.js","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts","../../../../src/lib/components/overlay/chat-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Floating Chat Overlay Component\n *\n * A collapsible floating panel (bottom-right corner) that wraps the\n * conversation-chat-area component. Provides a persistent, minimizable chat\n * experience across the application.\n *\n * This component is GENERIC -- it does NOT know about NavigationService,\n * Knowledge Hub, or any Explorer-specific concepts. It raises events that\n * the consuming application handles.\n *\n * Coordinates with the full Conversations workspace view through\n * ConversationBridgeService so that switching between overlay and workspace\n * preserves conversation continuity.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { takeUntil } from 'rxjs/operators';\nimport { UserInfo, Metadata, CompositeKey } from '@memberjunction/core';\nimport { MJConversationEntity, MJTaskEntity, MJEnvironmentEntityExtended, UserInfoEngine } from '@memberjunction/core-entities';\nimport { AgentClientService } from '@memberjunction/ng-agent-client';\nimport { ClientToolResultEvent } from '@memberjunction/ai-agent-client';\nimport { ConversationBridgeService, ConversationSwitchEvent } from '../../services/conversation-bridge.service';\nimport { NavigationRequest } from '@memberjunction/ng-artifacts';\nimport { PendingAttachment } from '../mention/mention-editor.component';\n\n/** Visual state of the overlay panel */\nexport type ChatOverlayState = 'collapsed' | 'expanded' | 'maximized';\n\n/** Event payload when the active conversation changes in the overlay */\nexport interface OverlayConversationSwitchedEvent {\n PreviousConversationID: string | null;\n NewConversationID: string | null;\n}\n\n/** Persisted overlay size and position preferences */\ninterface OverlayPrefs {\n width: number;\n height: number;\n /** Pixels the bubble has been dragged up from its default bottom position. Optional for back-compat with older saved prefs. */\n bubbleOffsetY?: number;\n /** When true, the bubble is hidden and only a thin sliver shows on the right edge. */\n bubbleHidden?: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-chat-agents-overlay',\n templateUrl: './chat-overlay.component.html',\n styleUrls: ['./chat-overlay.component.css']\n})\nexport class ChatAgentsOverlayComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private bridge = inject(ConversationBridgeService);\n private agentClient = inject(AgentClientService);\n private destroy$ = new Subject<void>();\n\n // --- Settings persistence ---\n private static readonly SIZE_SETTING_KEY = 'ChatOverlay.Size';\n private static readonly DEFAULT_WIDTH = 420;\n private static readonly DEFAULT_HEIGHT = 600;\n private static readonly MIN_WIDTH = 320;\n private static readonly MIN_HEIGHT = 350;\n private static readonly MAX_WIDTH = 900;\n private static readonly MAX_HEIGHT = 1000;\n\n // --- Bubble drag constants ---\n /** Default `bottom` for both bubble and panel (matches CSS 1.5rem). */\n private static readonly BASE_BOTTOM_PX = 24;\n /** Floating bubble diameter in pixels (matches CSS 3.5rem). */\n private static readonly BUBBLE_SIZE_PX = 56;\n /** Minimum gap to keep between the overlay and the viewport top edge. */\n private static readonly VIEWPORT_TOP_PADDING_PX = 16;\n /** Mousedown-to-mousemove distance that promotes a click into a drag. */\n private static readonly BUBBLE_DRAG_THRESHOLD_PX = 5;\n\n // --- Inputs ---\n\n /** Controls external visibility (e.g., parent hides overlay on chat route) */\n private _IsVisible = true;\n\n @Input()\n set IsVisible(value: boolean) {\n const prev = this._IsVisible;\n this._IsVisible = value;\n if (!value && prev && this.State !== 'collapsed') {\n this.Collapse();\n }\n this.cdr.detectChanges();\n }\n get IsVisible(): boolean {\n return this._IsVisible;\n }\n\n /** Current user info, passed through to conversation-chat-area. Auto-resolved from Metadata if not provided. */\n @Input() CurrentUser!: UserInfo;\n\n /** Environment ID, passed through to conversation-chat-area. Auto-resolved from default if not provided. */\n @Input() EnvironmentId!: string;\n\n /** Application context snapshot for AI agent awareness. Updated by the host app on navigation transitions. */\n @Input() AppContext: Record<string, unknown> | null = null;\n\n /** Greeting message shown in the empty state when no conversation is active */\n @Input() EmptyStateGreeting: string = 'How can I help you?';\n\n /**\n * Pixels reserved at the top of the viewport that the bubble and panel must not\n * cross. Set this from the host app to the height of any fixed top chrome (e.g.\n * Explorer's shell-header). Defaults to 0 — generic apps without top chrome\n * keep the full viewport available.\n */\n @Input() TopBoundaryPx: number = 0;\n\n // --- Outputs ---\n\n /** Emitted when the overlay visibility changes */\n @Output() VisibilityChanged = new EventEmitter<ChatOverlayState>();\n\n /** Emitted when a tool finishes executing in the agent client */\n @Output() ToolExecuted = new EventEmitter<ClientToolResultEvent>();\n\n /** Emitted when the active conversation changes in the overlay */\n @Output() ConversationSwitched = new EventEmitter<OverlayConversationSwitchedEvent>();\n\n /** Emitted when the user requests opening the full chat workspace */\n @Output() OpenFullChatWorkspace = new EventEmitter<string | null>();\n\n /** Emitted when navigation is requested (entity record, etc.) */\n @Output() NavigationRequested = new EventEmitter<NavigationRequest>();\n\n /** Emitted when an entity record open is requested */\n @Output() OpenEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n\n /** Emitted when a task is clicked */\n @Output() TaskClicked = new EventEmitter<MJTaskEntity>();\n\n // --- Component State ---\n\n public State: ChatOverlayState = 'collapsed';\n public UnreadCount = 0;\n\n /** Panel dimensions (persisted via UserInfoEngine) */\n public PanelWidth = ChatAgentsOverlayComponent.DEFAULT_WIDTH;\n public PanelHeight = ChatAgentsOverlayComponent.DEFAULT_HEIGHT;\n\n /**\n * Pixels the floating bubble has been dragged up from its default\n * bottom-right corner position. Always >= 0; clamping at render time\n * keeps the bubble on-screen even after a viewport resize.\n */\n public BubbleOffsetY = 0;\n\n /** True while the user is actively dragging the bubble; used to swap cursor + suppress click. */\n public IsBubbleDragging = false;\n\n /**\n * True from mousedown until mouseup on the bubble, regardless of whether the\n * gesture became a drag. Used to give immediate \"I'm being held\" feedback so\n * the user can see drag is possible even before crossing the move threshold.\n */\n public IsBubblePressed = false;\n\n /**\n * When true, the floating bubble is hidden and replaced by a thin sliver\n * flush with the right edge of the viewport. Persisted across sessions via\n * OverlayPrefs.bubbleHidden. Clicking the sliver restores the bubble.\n */\n public IsHidden = false;\n\n /** Active conversation ID managed locally */\n private _conversationId: string | null = null;\n public get ConversationId(): string | null {\n return this._conversationId;\n }\n\n /** Active conversation entity */\n public Conversation: MJConversationEntity | null = null;\n\n /** Whether a new unsaved conversation is in progress */\n public IsNewConversation = true;\n\n /** Pending message to send after conversation creation */\n public PendingMessage: string | null = null;\n\n /** Pending attachments to send after conversation creation */\n public PendingAttachments: PendingAttachment[] | null = null;\n\n /** Resize drag state */\n private isResizing = false;\n private resizeEdge: 'left' | 'top' | 'top-left' | null = null;\n private resizeStartX = 0;\n private resizeStartY = 0;\n private resizeStartWidth = 0;\n private resizeStartHeight = 0;\n\n /** Bubble drag state */\n private bubbleDragStartMouseY = 0;\n private bubbleDragStartOffset = 0;\n /** True once the pointer has moved past BUBBLE_DRAG_THRESHOLD_PX; suppresses the implicit click. */\n private bubbleDragMoved = false;\n /** ID of the pointer currently driving the drag — guards against multi-touch confusion. */\n private activeBubblePointerId: number | null = null;\n /** Element that captured the pointer; needed to release capture on end/cancel. */\n private bubbleCaptureTarget: HTMLElement | null = null;\n\n // --- Lifecycle ---\n\n ngOnInit(): void {\n this.resolveDefaults();\n this.loadPreferences();\n this.subscribeToBridgeEvents();\n this.subscribeToToolEvents();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.removeResizeListeners();\n this.removeBubbleDragListeners();\n }\n\n // --- Public Methods ---\n\n /** Toggle between collapsed and expanded states */\n public Toggle(): void {\n if (this.State === 'collapsed') {\n this.Expand();\n } else {\n this.Collapse();\n }\n }\n\n /** Expand the overlay to show the chat panel */\n public Expand(): void {\n // Expanding implies the user wants the chat visible — clear any hidden\n // state so collapse returns to the bubble, not back to the sliver.\n if (this.IsHidden) {\n this.IsHidden = false;\n this.savePreferences();\n }\n this.State = 'expanded';\n this.UnreadCount = 0;\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Collapse the overlay to the floating button */\n public Collapse(): void {\n this.State = 'collapsed';\n this.bridge.NotifyOverlayActive(false);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Toggle between expanded and maximized states */\n public ToggleMaximize(): void {\n if (this.State === 'maximized') {\n this.State = 'expanded';\n } else {\n this.State = 'maximized';\n }\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Handle the user requesting to open full chat workspace */\n public OnOpenFullChatWorkspace(): void {\n this.OpenFullChatWorkspace.emit(this._conversationId);\n this.bridge.SwitchToWorkspace(this._conversationId);\n this.Collapse();\n }\n\n /** Handle conversation creation from the chat area */\n public OnConversationCreated(event: {\n conversation: MJConversationEntity;\n pendingMessage?: string;\n pendingAttachments?: PendingAttachment[];\n }): void {\n // Set ALL state atomically before Angular change detection runs\n this.PendingMessage = event.pendingMessage || null;\n this.PendingAttachments = event.pendingAttachments || null;\n const prevId = this._conversationId;\n this._conversationId = event.conversation.ID;\n this.Conversation = event.conversation;\n this.IsNewConversation = false;\n this.bridge.SetActiveFromOverlay(event.conversation.ID);\n this.emitConversationSwitched(prevId, event.conversation.ID);\n }\n\n /** Handle pending message consumed by chat area */\n public OnPendingMessageConsumed(): void {\n this.PendingMessage = null;\n this.PendingAttachments = null;\n }\n\n /** Handle conversation rename from chat area */\n public OnConversationRenamed(_event: {conversationId: string; name: string; description: string}): void {\n // The overlay doesn't need to do anything specific here;\n // the conversation entity is updated in-place by the chat area.\n }\n\n /** Handle entity record open requests */\n public OnOpenEntityRecord(event: {entityName: string; compositeKey: CompositeKey}): void {\n this.OpenEntityRecord.emit(event);\n }\n\n /** Handle navigation requests from the chat area */\n public OnNavigationRequest(event: NavigationRequest): void {\n this.NavigationRequested.emit(event);\n }\n\n /** Handle task clicks from the chat area */\n public OnTaskClicked(task: MJTaskEntity): void {\n this.TaskClicked.emit(task);\n }\n\n /** Start a new conversation in the overlay */\n public StartNewConversation(): void {\n const prevId = this._conversationId;\n this._conversationId = null;\n this.Conversation = null;\n // Force Angular change detection by toggling off then on\n // so the setter fires even if already in new-conversation state\n this.IsNewConversation = false;\n this.cdr.detectChanges();\n this.IsNewConversation = true;\n this.bridge.SetActiveFromOverlay(null);\n this.emitConversationSwitched(prevId, null);\n this.cdr.detectChanges();\n }\n\n /**\n * Hide the floating bubble — leaves a thin sliver on the right edge as the\n * only affordance to bring it back. Invoked from the small \"×\" pill that\n * appears on hover. Stops propagation so the bubble's own click handler\n * doesn't fire and toggle the panel open.\n */\n public Hide(event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n if (this.IsHidden) return;\n this.IsHidden = true;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Restore the floating bubble after it was hidden. Triggered by clicking the sliver. */\n public Show(): void {\n if (!this.IsHidden) return;\n this.IsHidden = false;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Increment unread badge (called externally when messages arrive while collapsed) */\n public IncrementUnread(): void {\n if (this.State === 'collapsed') {\n this.UnreadCount++;\n this.cdr.detectChanges();\n }\n }\n\n // --- Resize Methods ---\n\n /** Start resizing from an edge or corner */\n public OnResizeStart(event: MouseEvent, edge: 'left' | 'top' | 'top-left'): void {\n event.preventDefault();\n event.stopPropagation();\n this.isResizing = true;\n this.resizeEdge = edge;\n this.resizeStartX = event.clientX;\n this.resizeStartY = event.clientY;\n this.resizeStartWidth = this.PanelWidth;\n this.resizeStartHeight = this.PanelHeight;\n\n document.addEventListener('mousemove', this.onResizeMove);\n document.addEventListener('mouseup', this.onResizeEnd);\n }\n\n private onResizeMove = (event: MouseEvent): void => {\n if (!this.isResizing || !this.resizeEdge) return;\n\n const deltaX = this.resizeStartX - event.clientX; // Inverted: dragging left increases width\n const deltaY = this.resizeStartY - event.clientY; // Inverted: dragging up increases height\n\n if (this.resizeEdge === 'left' || this.resizeEdge === 'top-left') {\n this.PanelWidth = this.clampWidth(this.resizeStartWidth + deltaX);\n }\n if (this.resizeEdge === 'top' || this.resizeEdge === 'top-left') {\n this.PanelHeight = this.clampHeight(this.resizeStartHeight + deltaY);\n }\n this.cdr.detectChanges();\n };\n\n private onResizeEnd = (): void => {\n if (!this.isResizing) return;\n this.isResizing = false;\n this.resizeEdge = null;\n this.removeResizeListeners();\n this.savePreferences();\n };\n\n private removeResizeListeners(): void {\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n }\n\n private clampWidth(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_WIDTH, Math.min(ChatAgentsOverlayComponent.MAX_WIDTH, value));\n }\n\n private clampHeight(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_HEIGHT, Math.min(ChatAgentsOverlayComponent.MAX_HEIGHT, value));\n }\n\n // --- Bubble Drag Methods (Pointer Events — unified mouse / touch / pen) ---\n\n /**\n * Start tracking a potential bubble drag. We don't enter drag mode until\n * the pointer moves past BUBBLE_DRAG_THRESHOLD_PX — releasing before that\n * threshold is treated as a normal click/tap and opens the chat (via Toggle()).\n *\n * Pointer Events (not mousedown) so the same code path serves desktop mouse,\n * touch on phones/tablets, and pen input. setPointerCapture keeps the gesture\n * tied to this element even if the finger or cursor strays off the bubble.\n */\n public OnBubblePointerDown(event: PointerEvent): void {\n // Mouse: respect primary-button only. Touch/pen: button is always 0, so this passes naturally.\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n // Don't start a second drag while one is in flight (e.g. second finger on touch).\n if (this.activeBubblePointerId !== null) return;\n event.preventDefault();\n\n const target = event.currentTarget as HTMLElement;\n target.setPointerCapture(event.pointerId);\n this.bubbleCaptureTarget = target;\n\n this.activeBubblePointerId = event.pointerId;\n this.bubbleDragStartMouseY = event.clientY;\n this.bubbleDragStartOffset = this.BubbleOffsetY;\n this.bubbleDragMoved = false;\n this.IsBubblePressed = true;\n this.cdr.detectChanges();\n\n document.addEventListener('pointermove', this.onBubbleDragMove);\n document.addEventListener('pointerup', this.onBubbleDragEnd);\n document.addEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n private onBubbleDragMove = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n const deltaY = this.bubbleDragStartMouseY - event.clientY; // dragging up = positive\n if (!this.bubbleDragMoved) {\n if (Math.abs(deltaY) < ChatAgentsOverlayComponent.BUBBLE_DRAG_THRESHOLD_PX) return;\n this.bubbleDragMoved = true;\n this.IsBubbleDragging = true;\n }\n this.BubbleOffsetY = this.clampBubbleOffsetY(this.bubbleDragStartOffset + deltaY);\n this.cdr.detectChanges();\n };\n\n private onBubbleDragEnd = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n this.removeBubbleDragListeners();\n\n if (this.bubbleCaptureTarget) {\n // Browser may have implicitly released capture on pointerup already (per the\n // Pointer Events spec). releasePointerCapture throws in that race; safe to ignore.\n try { this.bubbleCaptureTarget.releasePointerCapture(event.pointerId); } catch { /* noop */ }\n }\n this.bubbleCaptureTarget = null;\n this.activeBubblePointerId = null;\n\n const wasDragged = this.bubbleDragMoved;\n const wasCancelled = event.type === 'pointercancel';\n this.bubbleDragMoved = false;\n this.IsBubbleDragging = false;\n this.IsBubblePressed = false;\n if (wasDragged) {\n this.savePreferences();\n this.cdr.detectChanges();\n } else if (!wasCancelled) {\n this.Toggle();\n } else {\n this.cdr.detectChanges();\n }\n };\n\n private removeBubbleDragListeners(): void {\n document.removeEventListener('pointermove', this.onBubbleDragMove);\n document.removeEventListener('pointerup', this.onBubbleDragEnd);\n document.removeEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n /**\n * Reserved space at the top of the viewport — host-supplied chrome plus\n * the padding gap we always keep above the bubble/panel.\n */\n private get topReservedPx(): number {\n return Math.max(0, this.TopBoundaryPx) + ChatAgentsOverlayComponent.VIEWPORT_TOP_PADDING_PX;\n }\n\n /** Clamp the offset so the bubble stays fully visible below the top boundary. */\n private clampBubbleOffsetY(value: number): number {\n const maxOffset = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - ChatAgentsOverlayComponent.BASE_BOTTOM_PX\n - this.topReservedPx;\n return Math.max(0, Math.min(Math.max(0, maxOffset), value));\n }\n\n // --- Render Position Getters ---\n\n /** Effective `bottom` (px) for the floating bubble, clamped to the current viewport. */\n public get BubbleBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const max = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, max))\n );\n }\n\n /**\n * Effective `bottom` (px) for the expanded panel. Anchors to the bubble's\n * current bottom edge so the panel grows up from where the user parked the\n * bubble, but clamps downward whenever the panel would otherwise extend\n * past the viewport's top boundary — that's the \"reposition lower so the\n * chat interface stays visible\" behavior.\n */\n public get PanelBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const maxBottomForVisibility = window.innerHeight\n - this.PanelHeight\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, maxBottomForVisibility)\n );\n }\n\n // --- Private Methods ---\n\n /** Auto-resolve CurrentUser and EnvironmentId from Metadata when not provided as inputs */\n private resolveDefaults(): void {\n if (!this.CurrentUser) {\n const md = this.ProviderToUse;\n this.CurrentUser = md.CurrentUser;\n }\n if (!this.EnvironmentId) {\n this.EnvironmentId = MJEnvironmentEntityExtended.DefaultEnvironmentID;\n }\n }\n\n /** Load saved panel size and bubble position from UserInfoEngine */\n private loadPreferences(): void {\n try {\n const engine = UserInfoEngine.Instance;\n const raw = engine.GetSetting(ChatAgentsOverlayComponent.SIZE_SETTING_KEY);\n if (raw) {\n const prefs: OverlayPrefs = JSON.parse(raw);\n this.PanelWidth = this.clampWidth(prefs.width);\n this.PanelHeight = this.clampHeight(prefs.height);\n if (typeof prefs.bubbleOffsetY === 'number') {\n this.BubbleOffsetY = Math.max(0, prefs.bubbleOffsetY);\n }\n if (typeof prefs.bubbleHidden === 'boolean') {\n this.IsHidden = prefs.bubbleHidden;\n }\n }\n } catch {\n // Use defaults on error\n }\n }\n\n /** Persist panel size and bubble position to UserInfoEngine (debounced) */\n private savePreferences(): void {\n const prefs: OverlayPrefs = {\n width: this.PanelWidth,\n height: this.PanelHeight,\n bubbleOffsetY: this.BubbleOffsetY,\n bubbleHidden: this.IsHidden\n };\n UserInfoEngine.Instance.SetSettingDebounced(\n ChatAgentsOverlayComponent.SIZE_SETTING_KEY,\n JSON.stringify(prefs)\n );\n }\n\n /** Subscribe to bridge events for cross-view coordination */\n private subscribeToBridgeEvents(): void {\n this.bridge.SwitchEvent$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ConversationSwitchEvent) => {\n if (event.Target === 'overlay') {\n this.handleSwitchToOverlay(event);\n }\n });\n\n // Allow arbitrary callers (Form Builder cockpit, etc.) to ask the\n // overlay to expand. Idempotent if we're already expanded —\n // Expand() is safe to call in any state.\n this.bridge.ExpandOverlayRequested$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.State === 'collapsed') {\n this.Expand();\n }\n });\n\n this.bridge.ActiveConversationID$\n .pipe(takeUntil(this.destroy$))\n .subscribe((id: string | null) => {\n // Only update if the change came from outside (workspace)\n if (id !== this._conversationId && this.bridge.WorkspaceActive$.value) {\n const prevId = this._conversationId;\n this._conversationId = id;\n this.IsNewConversation = id === null;\n this.Conversation = null; // Will be loaded by chat area\n this.emitConversationSwitched(prevId, id);\n this.cdr.detectChanges();\n }\n });\n }\n\n /** Subscribe to agent client tool execution events */\n private subscribeToToolEvents(): void {\n this.agentClient.ToolExecuted$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ClientToolResultEvent) => {\n this.ToolExecuted.emit(event);\n });\n }\n\n /** Handle request to switch conversation to the overlay */\n private handleSwitchToOverlay(event: ConversationSwitchEvent): void {\n const prevId = this._conversationId;\n this._conversationId = event.ConversationID;\n this.IsNewConversation = event.ConversationID === null;\n this.Conversation = null; // Will be reloaded by chat area\n this.Expand();\n this.emitConversationSwitched(prevId, event.ConversationID);\n }\n\n /** Emit a conversation switched event */\n private emitConversationSwitched(prevId: string | null, newId: string | null): void {\n this.ConversationSwitched.emit({\n PreviousConversationID: prevId,\n NewConversationID: newId\n });\n }\n}\n","@if (IsVisible) {\n <!-- Floating Button (collapsed state, not hidden) -->\n @if (State === 'collapsed' && !IsHidden) {\n <div class=\"chat-overlay-bubble\"\n [class.is-pressed]=\"IsBubblePressed\"\n [class.is-dragging]=\"IsBubbleDragging\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (pointerdown)=\"OnBubblePointerDown($event)\">\n <i class=\"fa-solid fa-chevron-up chat-overlay-bubble-arrow chat-overlay-bubble-arrow-up\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-chevron-down chat-overlay-bubble-arrow chat-overlay-bubble-arrow-down\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n <!-- Hide affordance: revealed on hover. pointerdown stops drag from starting; click hides the bubble. -->\n <button type=\"button\"\n class=\"chat-overlay-bubble-close\"\n title=\"Hide chat — a thin sliver will remain on the right edge\"\n aria-label=\"Hide chat overlay\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"Hide($event)\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- Collapsed sliver — flush with the right edge when the bubble is hidden.\n Click opens the chat directly; closing returns to the bubble (not the\n sliver). To re-enter hidden mode the user clicks the × pill again. -->\n @if (State === 'collapsed' && IsHidden) {\n <button type=\"button\"\n class=\"chat-overlay-sliver\"\n title=\"Open chat\"\n aria-label=\"Open chat\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (click)=\"Expand()\">\n <i class=\"fa-solid fa-comments chat-overlay-sliver-icon\" aria-hidden=\"true\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge chat-overlay-sliver-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </button>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\"\n [style.bottom.px]=\"State === 'maximized' ? null : PanelBottomPx\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Chat Content — wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"chat-overlay.component.js","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts","../../../../src/lib/components/overlay/chat-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Floating Chat Overlay Component\n *\n * A collapsible floating panel (bottom-right corner) that wraps the\n * conversation-chat-area component. Provides a persistent, minimizable chat\n * experience across the application.\n *\n * This component is GENERIC -- it does NOT know about NavigationService,\n * Knowledge Hub, or any Explorer-specific concepts. It raises events that\n * the consuming application handles.\n *\n * Coordinates with the full Conversations workspace view through\n * ConversationBridgeService so that switching between overlay and workspace\n * preserves conversation continuity.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { takeUntil } from 'rxjs/operators';\nimport { UserInfo, Metadata, CompositeKey } from '@memberjunction/core';\nimport { MJConversationEntity, MJTaskEntity, MJEnvironmentEntityExtended, UserInfoEngine } from '@memberjunction/core-entities';\nimport { AgentClientService } from '@memberjunction/ng-agent-client';\nimport { ClientToolResultEvent } from '@memberjunction/ai-agent-client';\nimport { ConversationBridgeService, ConversationSwitchEvent } from '../../services/conversation-bridge.service';\nimport { NavigationRequest } from '@memberjunction/ng-artifacts';\nimport { PendingAttachment } from '@memberjunction/ng-composer';\n\n/** Visual state of the overlay panel */\nexport type ChatOverlayState = 'collapsed' | 'expanded' | 'maximized';\n\n/** Event payload when the active conversation changes in the overlay */\nexport interface OverlayConversationSwitchedEvent {\n PreviousConversationID: string | null;\n NewConversationID: string | null;\n}\n\n/** Persisted overlay size and position preferences */\ninterface OverlayPrefs {\n width: number;\n height: number;\n /** Pixels the bubble has been dragged up from its default bottom position. Optional for back-compat with older saved prefs. */\n bubbleOffsetY?: number;\n /** When true, the bubble is hidden and only a thin sliver shows on the right edge. */\n bubbleHidden?: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-chat-agents-overlay',\n templateUrl: './chat-overlay.component.html',\n styleUrls: ['./chat-overlay.component.css']\n})\nexport class ChatAgentsOverlayComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private bridge = inject(ConversationBridgeService);\n private agentClient = inject(AgentClientService);\n private destroy$ = new Subject<void>();\n\n // --- Settings persistence ---\n private static readonly SIZE_SETTING_KEY = 'ChatOverlay.Size';\n private static readonly DEFAULT_WIDTH = 420;\n private static readonly DEFAULT_HEIGHT = 600;\n private static readonly MIN_WIDTH = 320;\n private static readonly MIN_HEIGHT = 350;\n private static readonly MAX_WIDTH = 900;\n private static readonly MAX_HEIGHT = 1000;\n\n // --- Bubble drag constants ---\n /** Default `bottom` for both bubble and panel (matches CSS 1.5rem). */\n private static readonly BASE_BOTTOM_PX = 24;\n /** Floating bubble diameter in pixels (matches CSS 3.5rem). */\n private static readonly BUBBLE_SIZE_PX = 56;\n /** Minimum gap to keep between the overlay and the viewport top edge. */\n private static readonly VIEWPORT_TOP_PADDING_PX = 16;\n /** Mousedown-to-mousemove distance that promotes a click into a drag. */\n private static readonly BUBBLE_DRAG_THRESHOLD_PX = 5;\n\n // --- Inputs ---\n\n /** Controls external visibility (e.g., parent hides overlay on chat route) */\n private _IsVisible = true;\n\n @Input()\n set IsVisible(value: boolean) {\n const prev = this._IsVisible;\n this._IsVisible = value;\n if (!value && prev && this.State !== 'collapsed') {\n this.Collapse();\n }\n this.cdr.detectChanges();\n }\n get IsVisible(): boolean {\n return this._IsVisible;\n }\n\n /** Current user info, passed through to conversation-chat-area. Auto-resolved from Metadata if not provided. */\n @Input() CurrentUser!: UserInfo;\n\n /** Environment ID, passed through to conversation-chat-area. Auto-resolved from default if not provided. */\n @Input() EnvironmentId!: string;\n\n /** Application context snapshot for AI agent awareness. Updated by the host app on navigation transitions. */\n @Input() AppContext: Record<string, unknown> | null = null;\n\n /** Greeting message shown in the empty state when no conversation is active */\n @Input() EmptyStateGreeting: string = 'How can I help you?';\n\n /**\n * Pixels reserved at the top of the viewport that the bubble and panel must not\n * cross. Set this from the host app to the height of any fixed top chrome (e.g.\n * Explorer's shell-header). Defaults to 0 — generic apps without top chrome\n * keep the full viewport available.\n */\n @Input() TopBoundaryPx: number = 0;\n\n // --- Outputs ---\n\n /** Emitted when the overlay visibility changes */\n @Output() VisibilityChanged = new EventEmitter<ChatOverlayState>();\n\n /** Emitted when a tool finishes executing in the agent client */\n @Output() ToolExecuted = new EventEmitter<ClientToolResultEvent>();\n\n /** Emitted when the active conversation changes in the overlay */\n @Output() ConversationSwitched = new EventEmitter<OverlayConversationSwitchedEvent>();\n\n /** Emitted when the user requests opening the full chat workspace */\n @Output() OpenFullChatWorkspace = new EventEmitter<string | null>();\n\n /** Emitted when navigation is requested (entity record, etc.) */\n @Output() NavigationRequested = new EventEmitter<NavigationRequest>();\n\n /** Emitted when an entity record open is requested */\n @Output() OpenEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n\n /** Emitted when a task is clicked */\n @Output() TaskClicked = new EventEmitter<MJTaskEntity>();\n\n // --- Component State ---\n\n public State: ChatOverlayState = 'collapsed';\n public UnreadCount = 0;\n\n /** Panel dimensions (persisted via UserInfoEngine) */\n public PanelWidth = ChatAgentsOverlayComponent.DEFAULT_WIDTH;\n public PanelHeight = ChatAgentsOverlayComponent.DEFAULT_HEIGHT;\n\n /**\n * Pixels the floating bubble has been dragged up from its default\n * bottom-right corner position. Always >= 0; clamping at render time\n * keeps the bubble on-screen even after a viewport resize.\n */\n public BubbleOffsetY = 0;\n\n /** True while the user is actively dragging the bubble; used to swap cursor + suppress click. */\n public IsBubbleDragging = false;\n\n /**\n * True from mousedown until mouseup on the bubble, regardless of whether the\n * gesture became a drag. Used to give immediate \"I'm being held\" feedback so\n * the user can see drag is possible even before crossing the move threshold.\n */\n public IsBubblePressed = false;\n\n /**\n * When true, the floating bubble is hidden and replaced by a thin sliver\n * flush with the right edge of the viewport. Persisted across sessions via\n * OverlayPrefs.bubbleHidden. Clicking the sliver restores the bubble.\n */\n public IsHidden = false;\n\n /** Active conversation ID managed locally */\n private _conversationId: string | null = null;\n public get ConversationId(): string | null {\n return this._conversationId;\n }\n\n /** Active conversation entity */\n public Conversation: MJConversationEntity | null = null;\n\n /** Whether a new unsaved conversation is in progress */\n public IsNewConversation = true;\n\n /** Pending message to send after conversation creation */\n public PendingMessage: string | null = null;\n /** The conversation {@link PendingMessage} is destined for — pins the auto-send to that\n * conversation's input so a fast conversation-swap can't redirect it elsewhere. */\n public PendingMessageConversationId: string | null = null;\n\n /** Pending attachments to send after conversation creation */\n public PendingAttachments: PendingAttachment[] | null = null;\n\n /** Resize drag state */\n private isResizing = false;\n private resizeEdge: 'left' | 'top' | 'top-left' | null = null;\n private resizeStartX = 0;\n private resizeStartY = 0;\n private resizeStartWidth = 0;\n private resizeStartHeight = 0;\n\n /** Bubble drag state */\n private bubbleDragStartMouseY = 0;\n private bubbleDragStartOffset = 0;\n /** True once the pointer has moved past BUBBLE_DRAG_THRESHOLD_PX; suppresses the implicit click. */\n private bubbleDragMoved = false;\n /** ID of the pointer currently driving the drag — guards against multi-touch confusion. */\n private activeBubblePointerId: number | null = null;\n /** Element that captured the pointer; needed to release capture on end/cancel. */\n private bubbleCaptureTarget: HTMLElement | null = null;\n\n // --- Lifecycle ---\n\n ngOnInit(): void {\n this.resolveDefaults();\n this.loadPreferences();\n this.subscribeToBridgeEvents();\n this.subscribeToToolEvents();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.removeResizeListeners();\n this.removeBubbleDragListeners();\n }\n\n // --- Public Methods ---\n\n /** Toggle between collapsed and expanded states */\n public Toggle(): void {\n if (this.State === 'collapsed') {\n this.Expand();\n } else {\n this.Collapse();\n }\n }\n\n /** Expand the overlay to show the chat panel */\n public Expand(): void {\n // Expanding implies the user wants the chat visible — clear any hidden\n // state so collapse returns to the bubble, not back to the sliver.\n if (this.IsHidden) {\n this.IsHidden = false;\n this.savePreferences();\n }\n this.State = 'expanded';\n this.UnreadCount = 0;\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Collapse the overlay to the floating button */\n public Collapse(): void {\n this.State = 'collapsed';\n this.bridge.NotifyOverlayActive(false);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Toggle between expanded and maximized states */\n public ToggleMaximize(): void {\n if (this.State === 'maximized') {\n this.State = 'expanded';\n } else {\n this.State = 'maximized';\n }\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Handle the user requesting to open full chat workspace */\n public OnOpenFullChatWorkspace(): void {\n this.OpenFullChatWorkspace.emit(this._conversationId);\n this.bridge.SwitchToWorkspace(this._conversationId);\n this.Collapse();\n }\n\n /** Handle conversation creation from the chat area */\n public OnConversationCreated(event: {\n conversation: MJConversationEntity;\n pendingMessage?: string;\n pendingAttachments?: PendingAttachment[];\n }): void {\n // Set ALL state atomically before Angular change detection runs\n this.PendingMessage = event.pendingMessage || null;\n this.PendingAttachments = event.pendingAttachments || null;\n this.PendingMessageConversationId = event.conversation.ID;\n const prevId = this._conversationId;\n this._conversationId = event.conversation.ID;\n this.Conversation = event.conversation;\n this.IsNewConversation = false;\n this.bridge.SetActiveFromOverlay(event.conversation.ID);\n this.emitConversationSwitched(prevId, event.conversation.ID);\n }\n\n /** Handle pending message consumed by chat area */\n public OnPendingMessageConsumed(): void {\n this.PendingMessage = null;\n this.PendingAttachments = null;\n this.PendingMessageConversationId = null;\n }\n\n /** Handle conversation rename from chat area */\n public OnConversationRenamed(_event: {conversationId: string; name: string; description: string}): void {\n // The overlay doesn't need to do anything specific here;\n // the conversation entity is updated in-place by the chat area.\n }\n\n /** Handle entity record open requests */\n public OnOpenEntityRecord(event: {entityName: string; compositeKey: CompositeKey}): void {\n this.OpenEntityRecord.emit(event);\n }\n\n /** Handle navigation requests from the chat area */\n public OnNavigationRequest(event: NavigationRequest): void {\n this.NavigationRequested.emit(event);\n }\n\n /** Handle task clicks from the chat area */\n public OnTaskClicked(task: MJTaskEntity): void {\n this.TaskClicked.emit(task);\n }\n\n /** Start a new conversation in the overlay */\n public StartNewConversation(): void {\n const prevId = this._conversationId;\n this._conversationId = null;\n this.Conversation = null;\n // Force Angular change detection by toggling off then on\n // so the setter fires even if already in new-conversation state\n this.IsNewConversation = false;\n this.cdr.detectChanges();\n this.IsNewConversation = true;\n this.bridge.SetActiveFromOverlay(null);\n this.emitConversationSwitched(prevId, null);\n this.cdr.detectChanges();\n }\n\n /**\n * Hide the floating bubble — leaves a thin sliver on the right edge as the\n * only affordance to bring it back. Invoked from the small \"×\" pill that\n * appears on hover. Stops propagation so the bubble's own click handler\n * doesn't fire and toggle the panel open.\n */\n public Hide(event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n if (this.IsHidden) return;\n this.IsHidden = true;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Restore the floating bubble after it was hidden. Triggered by clicking the sliver. */\n public Show(): void {\n if (!this.IsHidden) return;\n this.IsHidden = false;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Increment unread badge (called externally when messages arrive while collapsed) */\n public IncrementUnread(): void {\n if (this.State === 'collapsed') {\n this.UnreadCount++;\n this.cdr.detectChanges();\n }\n }\n\n // --- Resize Methods ---\n\n /** Start resizing from an edge or corner */\n public OnResizeStart(event: MouseEvent, edge: 'left' | 'top' | 'top-left'): void {\n event.preventDefault();\n event.stopPropagation();\n this.isResizing = true;\n this.resizeEdge = edge;\n this.resizeStartX = event.clientX;\n this.resizeStartY = event.clientY;\n this.resizeStartWidth = this.PanelWidth;\n this.resizeStartHeight = this.PanelHeight;\n\n document.addEventListener('mousemove', this.onResizeMove);\n document.addEventListener('mouseup', this.onResizeEnd);\n }\n\n private onResizeMove = (event: MouseEvent): void => {\n if (!this.isResizing || !this.resizeEdge) return;\n\n const deltaX = this.resizeStartX - event.clientX; // Inverted: dragging left increases width\n const deltaY = this.resizeStartY - event.clientY; // Inverted: dragging up increases height\n\n if (this.resizeEdge === 'left' || this.resizeEdge === 'top-left') {\n this.PanelWidth = this.clampWidth(this.resizeStartWidth + deltaX);\n }\n if (this.resizeEdge === 'top' || this.resizeEdge === 'top-left') {\n this.PanelHeight = this.clampHeight(this.resizeStartHeight + deltaY);\n }\n this.cdr.detectChanges();\n };\n\n private onResizeEnd = (): void => {\n if (!this.isResizing) return;\n this.isResizing = false;\n this.resizeEdge = null;\n this.removeResizeListeners();\n this.savePreferences();\n };\n\n private removeResizeListeners(): void {\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n }\n\n private clampWidth(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_WIDTH, Math.min(ChatAgentsOverlayComponent.MAX_WIDTH, value));\n }\n\n private clampHeight(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_HEIGHT, Math.min(ChatAgentsOverlayComponent.MAX_HEIGHT, value));\n }\n\n // --- Bubble Drag Methods (Pointer Events — unified mouse / touch / pen) ---\n\n /**\n * Start tracking a potential bubble drag. We don't enter drag mode until\n * the pointer moves past BUBBLE_DRAG_THRESHOLD_PX — releasing before that\n * threshold is treated as a normal click/tap and opens the chat (via Toggle()).\n *\n * Pointer Events (not mousedown) so the same code path serves desktop mouse,\n * touch on phones/tablets, and pen input. setPointerCapture keeps the gesture\n * tied to this element even if the finger or cursor strays off the bubble.\n */\n public OnBubblePointerDown(event: PointerEvent): void {\n // Mouse: respect primary-button only. Touch/pen: button is always 0, so this passes naturally.\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n // Don't start a second drag while one is in flight (e.g. second finger on touch).\n if (this.activeBubblePointerId !== null) return;\n event.preventDefault();\n\n const target = event.currentTarget as HTMLElement;\n target.setPointerCapture(event.pointerId);\n this.bubbleCaptureTarget = target;\n\n this.activeBubblePointerId = event.pointerId;\n this.bubbleDragStartMouseY = event.clientY;\n this.bubbleDragStartOffset = this.BubbleOffsetY;\n this.bubbleDragMoved = false;\n this.IsBubblePressed = true;\n this.cdr.detectChanges();\n\n document.addEventListener('pointermove', this.onBubbleDragMove);\n document.addEventListener('pointerup', this.onBubbleDragEnd);\n document.addEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n private onBubbleDragMove = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n const deltaY = this.bubbleDragStartMouseY - event.clientY; // dragging up = positive\n if (!this.bubbleDragMoved) {\n if (Math.abs(deltaY) < ChatAgentsOverlayComponent.BUBBLE_DRAG_THRESHOLD_PX) return;\n this.bubbleDragMoved = true;\n this.IsBubbleDragging = true;\n }\n this.BubbleOffsetY = this.clampBubbleOffsetY(this.bubbleDragStartOffset + deltaY);\n this.cdr.detectChanges();\n };\n\n private onBubbleDragEnd = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n this.removeBubbleDragListeners();\n\n if (this.bubbleCaptureTarget) {\n // Browser may have implicitly released capture on pointerup already (per the\n // Pointer Events spec). releasePointerCapture throws in that race; safe to ignore.\n try { this.bubbleCaptureTarget.releasePointerCapture(event.pointerId); } catch { /* noop */ }\n }\n this.bubbleCaptureTarget = null;\n this.activeBubblePointerId = null;\n\n const wasDragged = this.bubbleDragMoved;\n const wasCancelled = event.type === 'pointercancel';\n this.bubbleDragMoved = false;\n this.IsBubbleDragging = false;\n this.IsBubblePressed = false;\n if (wasDragged) {\n this.savePreferences();\n this.cdr.detectChanges();\n } else if (!wasCancelled) {\n this.Toggle();\n } else {\n this.cdr.detectChanges();\n }\n };\n\n private removeBubbleDragListeners(): void {\n document.removeEventListener('pointermove', this.onBubbleDragMove);\n document.removeEventListener('pointerup', this.onBubbleDragEnd);\n document.removeEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n /**\n * Reserved space at the top of the viewport — host-supplied chrome plus\n * the padding gap we always keep above the bubble/panel.\n */\n private get topReservedPx(): number {\n return Math.max(0, this.TopBoundaryPx) + ChatAgentsOverlayComponent.VIEWPORT_TOP_PADDING_PX;\n }\n\n /** Clamp the offset so the bubble stays fully visible below the top boundary. */\n private clampBubbleOffsetY(value: number): number {\n const maxOffset = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - ChatAgentsOverlayComponent.BASE_BOTTOM_PX\n - this.topReservedPx;\n return Math.max(0, Math.min(Math.max(0, maxOffset), value));\n }\n\n // --- Render Position Getters ---\n\n /** Effective `bottom` (px) for the floating bubble, clamped to the current viewport. */\n public get BubbleBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const max = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, max))\n );\n }\n\n /**\n * Effective `bottom` (px) for the expanded panel. Anchors to the bubble's\n * current bottom edge so the panel grows up from where the user parked the\n * bubble, but clamps downward whenever the panel would otherwise extend\n * past the viewport's top boundary — that's the \"reposition lower so the\n * chat interface stays visible\" behavior.\n */\n public get PanelBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const maxBottomForVisibility = window.innerHeight\n - this.PanelHeight\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, maxBottomForVisibility)\n );\n }\n\n // --- Private Methods ---\n\n /** Auto-resolve CurrentUser and EnvironmentId from Metadata when not provided as inputs */\n private resolveDefaults(): void {\n if (!this.CurrentUser) {\n const md = this.ProviderToUse;\n this.CurrentUser = md.CurrentUser;\n }\n if (!this.EnvironmentId) {\n this.EnvironmentId = MJEnvironmentEntityExtended.DefaultEnvironmentID;\n }\n }\n\n /** Load saved panel size and bubble position from UserInfoEngine */\n private loadPreferences(): void {\n try {\n const engine = UserInfoEngine.Instance;\n const raw = engine.GetSetting(ChatAgentsOverlayComponent.SIZE_SETTING_KEY);\n if (raw) {\n const prefs: OverlayPrefs = JSON.parse(raw);\n this.PanelWidth = this.clampWidth(prefs.width);\n this.PanelHeight = this.clampHeight(prefs.height);\n if (typeof prefs.bubbleOffsetY === 'number') {\n this.BubbleOffsetY = Math.max(0, prefs.bubbleOffsetY);\n }\n if (typeof prefs.bubbleHidden === 'boolean') {\n this.IsHidden = prefs.bubbleHidden;\n }\n }\n } catch {\n // Use defaults on error\n }\n }\n\n /** Persist panel size and bubble position to UserInfoEngine (debounced) */\n private savePreferences(): void {\n const prefs: OverlayPrefs = {\n width: this.PanelWidth,\n height: this.PanelHeight,\n bubbleOffsetY: this.BubbleOffsetY,\n bubbleHidden: this.IsHidden\n };\n UserInfoEngine.Instance.SetSettingDebounced(\n ChatAgentsOverlayComponent.SIZE_SETTING_KEY,\n JSON.stringify(prefs)\n );\n }\n\n /** Subscribe to bridge events for cross-view coordination */\n private subscribeToBridgeEvents(): void {\n this.bridge.SwitchEvent$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ConversationSwitchEvent) => {\n if (event.Target === 'overlay') {\n this.handleSwitchToOverlay(event);\n }\n });\n\n // Allow arbitrary callers (Form Builder cockpit, etc.) to ask the\n // overlay to expand. Idempotent if we're already expanded —\n // Expand() is safe to call in any state.\n this.bridge.ExpandOverlayRequested$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.State === 'collapsed') {\n this.Expand();\n }\n });\n\n this.bridge.ActiveConversationID$\n .pipe(takeUntil(this.destroy$))\n .subscribe((id: string | null) => {\n // Only update if the change came from outside (workspace)\n if (id !== this._conversationId && this.bridge.WorkspaceActive$.value) {\n const prevId = this._conversationId;\n this._conversationId = id;\n this.IsNewConversation = id === null;\n this.Conversation = null; // Will be loaded by chat area\n this.emitConversationSwitched(prevId, id);\n this.cdr.detectChanges();\n }\n });\n }\n\n /** Subscribe to agent client tool execution events */\n private subscribeToToolEvents(): void {\n this.agentClient.ToolExecuted$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ClientToolResultEvent) => {\n this.ToolExecuted.emit(event);\n });\n }\n\n /** Handle request to switch conversation to the overlay */\n private handleSwitchToOverlay(event: ConversationSwitchEvent): void {\n const prevId = this._conversationId;\n this._conversationId = event.ConversationID;\n this.IsNewConversation = event.ConversationID === null;\n this.Conversation = null; // Will be reloaded by chat area\n this.Expand();\n this.emitConversationSwitched(prevId, event.ConversationID);\n }\n\n /** Emit a conversation switched event */\n private emitConversationSwitched(prevId: string | null, newId: string | null): void {\n this.ConversationSwitched.emit({\n PreviousConversationID: prevId,\n NewConversationID: newId\n });\n }\n}\n","@if (IsVisible) {\n <!-- Floating Button (collapsed state, not hidden) -->\n @if (State === 'collapsed' && !IsHidden) {\n <div class=\"chat-overlay-bubble\"\n [class.is-pressed]=\"IsBubblePressed\"\n [class.is-dragging]=\"IsBubbleDragging\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (pointerdown)=\"OnBubblePointerDown($event)\">\n <i class=\"fa-solid fa-chevron-up chat-overlay-bubble-arrow chat-overlay-bubble-arrow-up\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-chevron-down chat-overlay-bubble-arrow chat-overlay-bubble-arrow-down\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n <!-- Hide affordance: revealed on hover. pointerdown stops drag from starting; click hides the bubble. -->\n <button type=\"button\"\n class=\"chat-overlay-bubble-close\"\n title=\"Hide chat — a thin sliver will remain on the right edge\"\n aria-label=\"Hide chat overlay\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"Hide($event)\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- Collapsed sliver — flush with the right edge when the bubble is hidden.\n Click opens the chat directly; closing returns to the bubble (not the\n sliver). To re-enter hidden mode the user clicks the × pill again. -->\n @if (State === 'collapsed' && IsHidden) {\n <button type=\"button\"\n class=\"chat-overlay-sliver\"\n title=\"Open chat\"\n aria-label=\"Open chat\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (click)=\"Expand()\">\n <i class=\"fa-solid fa-comments chat-overlay-sliver-icon\" aria-hidden=\"true\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge chat-overlay-sliver-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </button>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\"\n [style.bottom.px]=\"State === 'maximized' ? null : PanelBottomPx\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Chat Content — wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [pendingMessageConversationId]=\"PendingMessageConversationId\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n"]}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Type } from '@angular/core';
|
|
2
|
+
import type { Observable } from 'rxjs';
|
|
3
|
+
import { IMetadataProvider } from '@memberjunction/core';
|
|
2
4
|
import { JSONValue, RealtimeToolDefinition } from '@memberjunction/ai';
|
|
5
|
+
import type { AppContextSnapshot } from '@memberjunction/ai-core-plus';
|
|
3
6
|
/**
|
|
4
7
|
* Host services handed to a {@link BaseRealtimeChannelClient} at {@link BaseRealtimeChannelClient.Initialize}.
|
|
5
8
|
*
|
|
@@ -17,6 +20,15 @@ import { JSONValue, RealtimeToolDefinition } from '@memberjunction/ai';
|
|
|
17
20
|
export interface RealtimeChannelContext {
|
|
18
21
|
/** Display name of the agent the live session fronts (e.g. `"Sage"`), fixed at session start. */
|
|
19
22
|
AgentName: string;
|
|
23
|
+
/**
|
|
24
|
+
* The MJ metadata provider the live session runs on — the SAME `IMetadataProvider` instance that
|
|
25
|
+
* authenticates the session (NOT necessarily the global default). A channel whose surface renders
|
|
26
|
+
* MemberJunction-backed data (e.g. the Media channel streaming an `MJ: Files` record through
|
|
27
|
+
* `mj-storage-media-player`) threads THIS provider into its surface / GraphQL calls so it stays
|
|
28
|
+
* multi-provider safe. `null` only in degenerate/early states; channels fall back to the global
|
|
29
|
+
* default when absent.
|
|
30
|
+
*/
|
|
31
|
+
Provider: IMetadataProvider | null;
|
|
20
32
|
/**
|
|
21
33
|
* Feeds a background context note into the live realtime model (no spoken reply is
|
|
22
34
|
* requested) — the PERCEPTION direction of the channel: serialized state deltas flow here
|
|
@@ -83,6 +95,31 @@ export interface RealtimeChannelContext {
|
|
|
83
95
|
* @returns The operation's `data` payload, or `null` on any failure / when no session is live.
|
|
84
96
|
*/
|
|
85
97
|
ExecuteServerAction<TResult>(query: string, variables: Record<string, JSONValue>): Promise<TResult | null>;
|
|
98
|
+
/**
|
|
99
|
+
* OPTIONAL — the live app-context stream (where the user is, what they see, and the available
|
|
100
|
+
* client-tool + agent manifest), pushed by the host (Explorer) at session start and on subsequent
|
|
101
|
+
* changes. The headless `ClientContextChannel` subscribes to this and streams deltas to the model
|
|
102
|
+
* via {@link SendContextNote}. Absent on hosts that don't supply app context (e.g. custom apps);
|
|
103
|
+
* channels must read it null-safely.
|
|
104
|
+
*/
|
|
105
|
+
AppContext$?: Observable<AppContextSnapshot | null>;
|
|
106
|
+
/**
|
|
107
|
+
* OPTIONAL — executes a host-registered surface CLIENT TOOL by name (the handlers the host wired
|
|
108
|
+
* from the active surface's `SetAgentClientTools`). The headless `ClientContextChannel`'s
|
|
109
|
+
* `ContextTool` proxy routes the model's `{ action, params }` here so a surface tool runs in the
|
|
110
|
+
* browser with no server round-trip. Best-effort and tolerant — resolves to a structured result
|
|
111
|
+
* (never throws); `Success: false` for an unknown tool or a thrown handler. Absent on hosts that
|
|
112
|
+
* register no client tools.
|
|
113
|
+
*
|
|
114
|
+
* @param name The client-tool name (the model's `action`).
|
|
115
|
+
* @param params The tool parameters (the model's `params`).
|
|
116
|
+
* @returns A structured result the channel serializes back to the model.
|
|
117
|
+
*/
|
|
118
|
+
ExecuteClientTool?(name: string, params: Record<string, unknown>): Promise<{
|
|
119
|
+
Success: boolean;
|
|
120
|
+
Result?: unknown;
|
|
121
|
+
ErrorMessage?: string;
|
|
122
|
+
}>;
|
|
86
123
|
}
|
|
87
124
|
/**
|
|
88
125
|
* The first-run INTRO content for an interactive channel — the concise "what is this surface
|
|
@@ -168,6 +205,14 @@ export declare abstract class BaseRealtimeChannelClient<TSurface extends object
|
|
|
168
205
|
abstract get TabTitle(): string;
|
|
169
206
|
/** Font Awesome icon class for the channel's tab (e.g. `'fa-solid fa-chalkboard'`). */
|
|
170
207
|
abstract get TabIcon(): string;
|
|
208
|
+
/**
|
|
209
|
+
* OPTIONAL accent color for the channel's tab (a CSS color string, e.g. an `hsl()` /
|
|
210
|
+
* token). When a plugin supplies one, the overlay paints the tab's dot + active underline
|
|
211
|
+
* with it; when omitted (the default `null`), the overlay derives a stable, deterministic
|
|
212
|
+
* color from the {@link ChannelName} so every channel still reads as a distinct, colored
|
|
213
|
+
* surface. A channel only overrides this to enforce a specific brand accent.
|
|
214
|
+
*/
|
|
215
|
+
get TabColor(): string | null;
|
|
171
216
|
/**
|
|
172
217
|
* The channel's CLIENT-EXECUTED tool declarations, aggregated by the session service
|
|
173
218
|
* into the `clientTools` set declared to the realtime model at session mint. The server
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-realtime-channel-client.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/base-realtime-channel-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEvE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,sBAAsB;IACrC,iGAAiG;IACjG,SAAS,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IAEhC;;;;;;;OAOG;IACH,qBAAqB,CAAC,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD;;;;;;;OAOG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1E;;;;;;;OAOG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;;;;;;;;;;;;;OAgBG;IACH,mBAAmB,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"base-realtime-channel-client.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/base-realtime-channel-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,6 +47,16 @@ export class BaseRealtimeChannelClient {
|
|
|
47
47
|
* `null` outside that window — guard with `?.` in any code that can run early/late.
|
|
48
48
|
*/
|
|
49
49
|
Context = null;
|
|
50
|
+
/**
|
|
51
|
+
* OPTIONAL accent color for the channel's tab (a CSS color string, e.g. an `hsl()` /
|
|
52
|
+
* token). When a plugin supplies one, the overlay paints the tab's dot + active underline
|
|
53
|
+
* with it; when omitted (the default `null`), the overlay derives a stable, deterministic
|
|
54
|
+
* color from the {@link ChannelName} so every channel still reads as a distinct, colored
|
|
55
|
+
* surface. A channel only overrides this to enforce a specific brand accent.
|
|
56
|
+
*/
|
|
57
|
+
get TabColor() {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
50
60
|
/**
|
|
51
61
|
* The Angular component the overlay creates dynamically as this channel's tab pane, or `null`
|
|
52
62
|
* for a **server-only** channel that renders no MJ surface (its surface, if any, lives on the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-realtime-channel-client.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/base-realtime-channel-client.ts"],"names":[],"mappings":"AAmHA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,OAAgB,yBAAyB;IAC7C;;;OAGG;IACO,OAAO,GAAkC,IAAI,CAAC;IAwCxD;;;;;;;;;;;;;OAaG;IACI,mBAAmB;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACI,UAAU;QACf,OAAO,IAAI,CAAC,mBAAmB,EAAE,IAAI,IAAI,CAAC;IAC5C,CAAC;IAED;;;;;;;;;;OAUG;IACI,oBAAoB;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAYD;;;;;OAKG;IACI,aAAa;QAClB,8BAA8B;IAChC,CAAC;IAED;;;;OAIG;IACI,UAAU,CAAC,GAA2B;QAC3C,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACO,YAAY;QACpB,iCAAiC;IACnC,CAAC;IAED;;;;OAIG;IACO,sBAAsB,GAAG,IAAI,CAAC;IAC9B,uBAAuB,GAAG,GAAG,CAAC;IAExC;;;;;;;;;;;;;OAaG;IACO,KAAK,CAAC,qBAAqB;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,IAAI,IAAI,CAAC;QACvD,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC7D,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE,MAAM,IAAI,UAAU,EAAE,CAAC;YAChF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;YACtE,sEAAsE;YACtE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;YACvC,IAAI,EAAE,EAAE,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,EAAE,cAAc,IAAI,IAAI,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACI,cAAc;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;OAUG;IACI,YAAY,CAAC,SAAiB;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACI,gBAAgB;QACrB,oDAAoD;IACtD,CAAC;IAED;;;;;OAKG;IACI,OAAO;QACZ,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;CACF","sourcesContent":["import type { Type } from '@angular/core';\nimport { JSONValue, RealtimeToolDefinition } from '@memberjunction/ai';\n\n/**\n * Host services handed to a {@link BaseRealtimeChannelClient} at {@link BaseRealtimeChannelClient.Initialize}.\n *\n * The context is the plugin's ONLY line back to the live session — channels never talk to\n * `RealtimeSessionService` (or any host component) directly, which is what keeps them drop-in\n * plugins. Every member is host-implemented:\n *\n * - the SESSION SERVICE supplies {@link SendContextNote} (perception feed into the live\n * model), {@link RequestSave} (debounced state-of-record persistence onto the session's\n * `MJ: AI Agent Session Channels` row) and {@link AgentName};\n * - the OVERLAY SHELL wires {@link SetFocusMode} (through the service's focus stream) so a\n * channel surface can request the focus layout — main call column collapsed, surface\n * panel filling the overlay, floating call pill riding on top.\n */\nexport interface RealtimeChannelContext {\n /** Display name of the agent the live session fronts (e.g. `\"Sage\"`), fixed at session start. */\n AgentName: string;\n\n /**\n * Feeds a background context note into the live realtime model (no spoken reply is\n * requested) — the PERCEPTION direction of the channel: serialized state deltas flow here\n * so the agent stays aware of what's on the surface. No-op when the session isn't live.\n */\n SendContextNote(text: string): void;\n\n /**\n * Asks the host to persist `stateJson` as this channel's state of record. The host\n * DEBOUNCES (a change burst becomes one save) and flushes any pending save at session\n * teardown — the plugin just calls this on every state mutation and never schedules\n * timers itself. Best-effort: persistence failures are logged host-side, never thrown.\n */\n RequestSave(stateJson: string): void;\n\n /**\n * Requests (or releases) the FOCUS layout for this channel's surface: the overlay\n * collapses the main call column so the surface owns the screen, with a compact floating\n * call pill keeping mute / thread / end reachable. Any channel may request it; the host\n * tracks which channel holds focus and routes the pill's \"exit\" back to it via\n * {@link BaseRealtimeChannelClient.RequestFocusExit}.\n */\n SetFocusMode(on: boolean): void;\n\n /**\n * Asks the live model to SPEAK a response to the supplied instructions RIGHT NOW —\n * the channel's \"react to this\" path, e.g. a widget submission the user expects an\n * audible reaction to ({@link SendContextNote} deliberately never triggers speech).\n * Rides the realtime client's spoken-update channel, so on some providers the spoken\n * reply is narration-kind (ephemeral, not persisted as a caption). OPTIONAL member:\n * older host contexts may not supply it — plugins must call it null-safely.\n */\n RequestSpokenResponse?(instructions: string): void;\n\n /**\n * Persists a snapshot of the channel's state as a first-class versioned artifact\n * (`MJ: Artifacts` + version, linked into conversation history when possible) — e.g. the\n * whiteboard's \"Save to artifacts\". Distinct from {@link RealtimeChannelContext.RequestSave},\n * which maintains the session's rolling state of record. Best-effort: resolves to the\n * created Artifact ID, or `null` on failure (logged host-side, never thrown). Works during\n * the call AND right after it ends (the host retains the session id for late saves).\n */\n SaveAsArtifact(name: string, contentJson: string): Promise<string | null>;\n\n /**\n * The live `MJ: AI Agent Sessions` id this channel belongs to, or `null` before the\n * session has minted / after it has torn down. A channel whose tools or surface drive a\n * SERVER-SIDE resource (e.g. the Remote Browser channel's server-hosted browser) passes\n * this as the `agentSessionID` argument to its own GraphQL resolvers via\n * {@link ExecuteServerAction}. Most channels (whiteboard, shared doc) keep all state\n * client-side and never read it.\n */\n AgentSessionID: string | null;\n\n /**\n * Executes a CHANNEL-SPECIFIC GraphQL operation against the session's MJ server — the\n * escape hatch for channels backed by a SERVER-SIDE resource that the generic\n * {@link RequestSave} / {@link SaveAsArtifact} contract doesn't cover (e.g. the Remote\n * Browser channel driving a server-hosted browser through its own\n * `ExecuteRemoteBrowserAction` mutation + `RemoteBrowserSnapshot` query).\n *\n * The host runs the operation through the SAME provider the live session uses, so the\n * request rides the authenticated session. Best-effort and tolerant: a transport or\n * server error resolves to `null` (logged host-side) rather than throwing, so a channel\n * can map the failure to a model-readable result string without `try/catch`.\n *\n * @typeParam TResult The expected shape of the GraphQL operation's data payload.\n * @param query The GraphQL query/mutation document.\n * @param variables The operation variables (all JSON-serializable).\n * @returns The operation's `data` payload, or `null` on any failure / when no session is live.\n */\n ExecuteServerAction<TResult>(query: string, variables: Record<string, JSONValue>): Promise<TResult | null>;\n}\n\n/**\n * The first-run INTRO content for an interactive channel — the concise \"what is this surface\n * and how do I use it\" copy the overlay shows the very first time a user opens this channel's\n * tab (persisted \"seen\" per user, so it's shown ONCE per channel per user).\n *\n * A channel opts in by overriding {@link BaseRealtimeChannelClient.GetOnboardingDetails}; the\n * default returns `null`, so the base Voice/text channel (which has no plugin at all) AND any\n * plugin that doesn't override it show nothing.\n */\nexport interface ChannelOnboardingDetails {\n /** Short title, usually the surface name (e.g. `\"Whiteboard\"`). */\n Heading: string;\n /** One or two sentences: what the surface is and what the user can expect to see on it. */\n Description: string;\n /** Optional quick-tip bullets (kept to 2-3 short, scannable lines). */\n Tips?: string[];\n /** Optional Font Awesome icon class for the intro panel (e.g. `'fa-solid fa-chalkboard'`). */\n IconClass?: string;\n}\n\n/**\n * Base class for CLIENT-SIDE interactive-channel plugins (per\n * `plans/ai-agent-sessions.md` → \"Interactive Channels\" / \"Pluggable Channel Interfaces\").\n *\n * An interactive channel is a bidirectional surface the session's single realtime agent\n * both PERCEIVES and ACTS UPON (whiteboard, shared doc, map, …). A concrete plugin\n * contributes everything the channel needs, so the session service / call overlay carry\n * ZERO channel-specific wiring:\n *\n * 1. a CLIENT-EXECUTED TOOL SET ({@link GetToolDefinitions}, declared to the realtime\n * model at session mint) plus the local executor ({@link ApplyAgentTool}) the host\n * routes `{@link ToolNamePrefix}*` calls to — the ACTION direction;\n * 2. a STATE→CONTEXT SERIALIZER policy — the plugin owns its state engine and pushes\n * coalesced deltas through {@link RealtimeChannelContext.SendContextNote} — the\n * PERCEPTION direction;\n * 3. an OPTIONAL ANGULAR SURFACE ({@link GetSurfaceComponent}) the overlay creates dynamically\n * in a channel tab, handed back through {@link BindSurface} so the plugin wires its own\n * inputs/outputs (the host never knows the component's API). A channel may be **server-only**\n * (no rendered surface) — e.g. a bridge-contributed meeting-controls or native-whiteboard\n * channel whose surface lives on the external platform, not in MJ. Such a channel returns\n * `null` from {@link GetSurfaceComponent} ({@link HasSurface} is `false`) and the overlay\n * simply skips its tab while still wiring its tools + perception;\n * 4. a STATE OF RECORD ({@link SerializeState}, persisted via\n * {@link RealtimeChannelContext.RequestSave} under {@link ChannelName}).\n *\n * ### Registration & resolution (mirrors the realtime model drivers)\n * Concrete plugins are `@RegisterClass(BaseRealtimeChannelClient, '<ClientPluginClass>')`\n * and are resolved at session start from the `MJ: AI Agent Channels` registry: each ACTIVE\n * row's `ClientPluginClass` is the ClassFactory key (exactly how `BaseRealtimeClient`\n * drivers resolve by provider key). Ship a `Load<YourChannel>()` no-op alongside the class\n * and call it from a static code path to defeat tree-shaking.\n *\n * ### Lifecycle — ONE INSTANCE PER SESSION (not a singleton)\n * `ClassFactory.CreateInstance` → {@link Initialize}(ctx) → zero or more\n * {@link BindSurface}/{@link UnbindSurface} cycles (the surface pane is created/destroyed\n * with the overlay's tab panel, e.g. collapse/expand) → {@link Dispose} at teardown.\n * {@link ApplyAgentTool} MUST work with NO surface bound (apply to the state engine\n * directly; skip the UI garnish) — tool calls can arrive while the panel is collapsed.\n *\n * @typeParam TSurface The plugin's Angular surface component type. The host only ever\n * sees the default (`object`) — the typed parameter exists so concrete plugins get a\n * fully typed {@link BindSurface} without casts.\n */\nexport abstract class BaseRealtimeChannelClient<TSurface extends object = object> {\n /**\n * The host context, available from {@link Initialize} until {@link Dispose}.\n * `null` outside that window — guard with `?.` in any code that can run early/late.\n */\n protected Context: RealtimeChannelContext | null = null;\n\n /**\n * The channel definition name — MUST match the `MJ: AI Agent Channels` row's `Name`\n * (e.g. `'Whiteboard'`). Used as the persistence key for {@link SerializeState} saves\n * and as the channel tab's stable key.\n */\n public abstract get ChannelName(): string;\n\n /**\n * The shared name prefix of every tool this channel exposes (e.g. `'Whiteboard_'`).\n * The host registers ONE local-execution route per plugin: tool calls whose name starts\n * with this prefix go to {@link ApplyAgentTool} instead of the server relay.\n */\n public abstract get ToolNamePrefix(): string;\n\n /** Label for the channel's tab on the overlay's surface panel (e.g. `'Whiteboard'`). */\n public abstract get TabTitle(): string;\n\n /** Font Awesome icon class for the channel's tab (e.g. `'fa-solid fa-chalkboard'`). */\n public abstract get TabIcon(): string;\n\n /**\n * The channel's CLIENT-EXECUTED tool declarations, aggregated by the session service\n * into the `clientTools` set declared to the realtime model at session mint. The server\n * only DECLARES these — execution stays in the browser via {@link ApplyAgentTool}.\n */\n public abstract GetToolDefinitions(): RealtimeToolDefinition[];\n\n /**\n * Executes ONE agent tool call locally (the ACTION direction) and returns the result\n * JSON string fed back to the model as the `tool_response`. Called for every tool whose\n * name starts with {@link ToolNamePrefix}. Must work both WITH a bound surface (apply +\n * UI garnish) and WITHOUT one (apply to the state engine directly — the tab pane may not\n * exist, e.g. the surface panel is collapsed). Should not throw: return a\n * `{ success: false, error }` payload so the model can narrate the failure (the host\n * additionally wraps anything thrown).\n */\n public abstract ApplyAgentTool(toolName: string, argsJson: string): string | Promise<string>;\n\n /**\n * The Angular component the overlay creates dynamically as this channel's tab pane, or `null`\n * for a **server-only** channel that renders no MJ surface (its surface, if any, lives on the\n * external platform — e.g. a bridge-contributed native whiteboard or meeting-controls channel).\n *\n * When this returns `null`, the overlay renders NO tab for the channel and never calls\n * {@link BindSurface}/{@link UnbindSurface} — but the channel's tools ({@link GetToolDefinitions} /\n * {@link ApplyAgentTool}) and perception ({@link RealtimeChannelContext.SendContextNote}) still run.\n * A created surface instance is handed straight back via {@link BindSurface}; the host treats it as\n * opaque.\n *\n * Default: `null` (server-only). A channel with a rendered surface overrides this to return its\n * component type.\n */\n public GetSurfaceComponent(): Type<TSurface> | null {\n return null;\n }\n\n /**\n * Whether this channel has a rendered MJ surface ({@link GetSurfaceComponent} returns non-null).\n * The overlay uses this to decide whether to register a surface tab; server-only channels are\n * `false`. Override only if surface availability must be decided WITHOUT constructing the type\n * (the default calls {@link GetSurfaceComponent} once).\n */\n public HasSurface(): boolean {\n return this.GetSurfaceComponent() != null;\n }\n\n /**\n * The channel's FIRST-RUN INTRO content, or `null` when the channel offers no onboarding.\n * The overlay shows this once per channel per user — the first time the user opens this\n * channel's surface tab — and remembers \"seen\" via the user's settings (NOT localStorage),\n * so it never re-appears on later sessions or other devices.\n *\n * Default: `null` (no intro). The base Voice/text channel has no plugin at all, so it never\n * shows an intro; an interactive channel with a surface worth explaining (whiteboard, remote\n * browser, …) overrides this to return its {@link ChannelOnboardingDetails}. A plugin that\n * doesn't override it simply shows nothing — onboarding is strictly opt-in.\n */\n public GetOnboardingDetails(): ChannelOnboardingDetails | null {\n return null;\n }\n\n /**\n * Called by the host right after it created the surface component (and BEFORE the\n * component's first change detection, so inputs set here are visible in its `ngOnInit`).\n * The plugin — which knows its own component type — sets inputs (state engine, agent\n * name, …) and subscribes outputs here, wiring perception/garnish flows back through\n * {@link Context}. May be called again with a NEW instance after an\n * {@link UnbindSurface} (the pane is destroyed/recreated with the tab panel).\n */\n public abstract BindSurface(instance: TSurface): void;\n\n /**\n * Called by the host when the surface component is being destroyed (tab panel\n * collapsed / overlay torn down). Drop the instance reference and unsubscribe any\n * output subscriptions — after this, {@link ApplyAgentTool} runs in its no-surface\n * mode. Default: no-op.\n */\n public UnbindSurface(): void {\n // default: nothing to release\n }\n\n /**\n * Binds the host context and invokes the {@link OnInitialize} hook. Called exactly once\n * per session, right after ClassFactory instantiation and before any tool call or\n * surface bind.\n */\n public Initialize(ctx: RealtimeChannelContext): void {\n this.Context = ctx;\n this.OnInitialize();\n }\n\n /**\n * Subclass hook invoked from {@link Initialize} once {@link Context} is bound — wire\n * state-engine subscriptions (e.g. state change → `Context.RequestSave(...)`) here.\n * Default: no-op.\n */\n protected OnInitialize(): void {\n // default: nothing to initialize\n }\n\n /**\n * Max time {@link ResolveAgentSessionId} waits for the session id to bind before giving up, and the\n * poll interval it re-checks on. Protected so tests can shrink the wait; production keeps the\n * defaults (the real mint race is sub-second, 8s is generous headroom).\n */\n protected SessionIdWaitTimeoutMs = 8000;\n protected SessionIdWaitIntervalMs = 200;\n\n /**\n * Resolves the live {@link RealtimeChannelContext.AgentSessionID}, briefly WAITING for it when it\n * isn't bound yet rather than giving up instantly. `AgentSessionID` is a live getter over the\n * session service's current id: it reads `null` in the window BEFORE the session mints (the\n * realtime model can fire a tool call the very first beat it connects, before `mintSession`\n * resolves) and again AFTER teardown. Server-backed tool paths (e.g. the Remote Browser channel's\n * `browser_*` tools) call this instead of reading `Context?.AgentSessionID` synchronously, so a tool\n * invoked a beat early WAITS for the session to come live — defense-in-depth against the\n * \"session id missing\" race — instead of returning a hard failure to the model.\n *\n * Returns the id as soon as it's non-null (the common path resolves immediately, no delay), or\n * `null` if it's still unbound after {@link SessionIdWaitTimeoutMs} — or the channel was\n * {@link Dispose}d in the meantime (`Context` goes null, so we stop waiting on a torn-down session).\n */\n protected async ResolveAgentSessionId(): Promise<string | null> {\n const immediate = this.Context?.AgentSessionID ?? null;\n if (immediate) {\n return immediate;\n }\n const intervalMs = Math.max(1, this.SessionIdWaitIntervalMs);\n for (let waited = 0; waited < this.SessionIdWaitTimeoutMs; waited += intervalMs) {\n await new Promise<void>((resolve) => setTimeout(resolve, intervalMs));\n // Context goes null on Dispose() — the session is gone, stop waiting.\n if (!this.Context) {\n return null;\n }\n const id = this.Context.AgentSessionID;\n if (id) {\n return id;\n }\n }\n return this.Context?.AgentSessionID ?? null;\n }\n\n /**\n * Serializes the channel's current state of record (the payload persisted on the\n * session's channel row), or `null` when the channel keeps no persistent state.\n * Default: `null`.\n */\n public SerializeState(): string | null {\n return null;\n }\n\n /**\n * Restores a PRIOR session's saved channel state (the payload a previous session\n * persisted via {@link SerializeState} / {@link RealtimeChannelContext.RequestSave}).\n * Invoked by the session host AFTER {@link Initialize} and BEFORE any surface binding,\n * when a prior session's saved state exists for this channel.\n *\n * Returns `true` when the state was applied; `false` when the channel ignored it —\n * either because it keeps no persistent state (this default) or because the payload was\n * malformed/incompatible. Implementations MUST be tolerant: never throw on bad input,\n * just return `false` and start fresh.\n */\n public RestoreState(stateJson: string): boolean {\n return false;\n }\n\n /**\n * The focus pill's \"exit\" affordance, routed by the overlay to the channel that holds\n * focus. Implementations should leave focus mode through their OWN surface (so surface\n * toggles stay in sync), ultimately emitting `Context.SetFocusMode(false)`. The overlay\n * defensively clears its layout flag as well, so a no-op default is safe.\n */\n public RequestFocusExit(): void {\n // default: the overlay's defensive clear handles it\n }\n\n /**\n * Tears the plugin down at session end: release the surface binding, unsubscribe\n * state-engine subscriptions, then drop the context. Subclasses overriding this MUST\n * call `super.Dispose()`. Any final state save has already been flushed by the host\n * (the debounced {@link RealtimeChannelContext.RequestSave} pipeline) before disposal.\n */\n public Dispose(): void {\n this.UnbindSurface();\n this.Context = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base-realtime-channel-client.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/base-realtime-channel-client.ts"],"names":[],"mappings":"AA0JA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,OAAgB,yBAAyB;IAC7C;;;OAGG;IACO,OAAO,GAAkC,IAAI,CAAC;IAsBxD;;;;;;OAMG;IACH,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAoBD;;;;;;;;;;;;;OAaG;IACI,mBAAmB;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACI,UAAU;QACf,OAAO,IAAI,CAAC,mBAAmB,EAAE,IAAI,IAAI,CAAC;IAC5C,CAAC;IAED;;;;;;;;;;OAUG;IACI,oBAAoB;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAYD;;;;;OAKG;IACI,aAAa;QAClB,8BAA8B;IAChC,CAAC;IAED;;;;OAIG;IACI,UAAU,CAAC,GAA2B;QAC3C,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACO,YAAY;QACpB,iCAAiC;IACnC,CAAC;IAED;;;;OAIG;IACO,sBAAsB,GAAG,IAAI,CAAC;IAC9B,uBAAuB,GAAG,GAAG,CAAC;IAExC;;;;;;;;;;;;;OAaG;IACO,KAAK,CAAC,qBAAqB;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,IAAI,IAAI,CAAC;QACvD,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC7D,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE,MAAM,IAAI,UAAU,EAAE,CAAC;YAChF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;YACtE,sEAAsE;YACtE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;YACvC,IAAI,EAAE,EAAE,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,EAAE,cAAc,IAAI,IAAI,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACI,cAAc;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;OAUG;IACI,YAAY,CAAC,SAAiB;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACI,gBAAgB;QACrB,oDAAoD;IACtD,CAAC;IAED;;;;;OAKG;IACI,OAAO;QACZ,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;CACF","sourcesContent":["import type { Type } from '@angular/core';\nimport type { Observable } from 'rxjs';\nimport { IMetadataProvider } from '@memberjunction/core';\nimport { JSONValue, RealtimeToolDefinition } from '@memberjunction/ai';\nimport type { AppContextSnapshot } from '@memberjunction/ai-core-plus';\n\n/**\n * Host services handed to a {@link BaseRealtimeChannelClient} at {@link BaseRealtimeChannelClient.Initialize}.\n *\n * The context is the plugin's ONLY line back to the live session — channels never talk to\n * `RealtimeSessionService` (or any host component) directly, which is what keeps them drop-in\n * plugins. Every member is host-implemented:\n *\n * - the SESSION SERVICE supplies {@link SendContextNote} (perception feed into the live\n * model), {@link RequestSave} (debounced state-of-record persistence onto the session's\n * `MJ: AI Agent Session Channels` row) and {@link AgentName};\n * - the OVERLAY SHELL wires {@link SetFocusMode} (through the service's focus stream) so a\n * channel surface can request the focus layout — main call column collapsed, surface\n * panel filling the overlay, floating call pill riding on top.\n */\nexport interface RealtimeChannelContext {\n /** Display name of the agent the live session fronts (e.g. `\"Sage\"`), fixed at session start. */\n AgentName: string;\n\n /**\n * The MJ metadata provider the live session runs on — the SAME `IMetadataProvider` instance that\n * authenticates the session (NOT necessarily the global default). A channel whose surface renders\n * MemberJunction-backed data (e.g. the Media channel streaming an `MJ: Files` record through\n * `mj-storage-media-player`) threads THIS provider into its surface / GraphQL calls so it stays\n * multi-provider safe. `null` only in degenerate/early states; channels fall back to the global\n * default when absent.\n */\n Provider: IMetadataProvider | null;\n\n /**\n * Feeds a background context note into the live realtime model (no spoken reply is\n * requested) — the PERCEPTION direction of the channel: serialized state deltas flow here\n * so the agent stays aware of what's on the surface. No-op when the session isn't live.\n */\n SendContextNote(text: string): void;\n\n /**\n * Asks the host to persist `stateJson` as this channel's state of record. The host\n * DEBOUNCES (a change burst becomes one save) and flushes any pending save at session\n * teardown — the plugin just calls this on every state mutation and never schedules\n * timers itself. Best-effort: persistence failures are logged host-side, never thrown.\n */\n RequestSave(stateJson: string): void;\n\n /**\n * Requests (or releases) the FOCUS layout for this channel's surface: the overlay\n * collapses the main call column so the surface owns the screen, with a compact floating\n * call pill keeping mute / thread / end reachable. Any channel may request it; the host\n * tracks which channel holds focus and routes the pill's \"exit\" back to it via\n * {@link BaseRealtimeChannelClient.RequestFocusExit}.\n */\n SetFocusMode(on: boolean): void;\n\n /**\n * Asks the live model to SPEAK a response to the supplied instructions RIGHT NOW —\n * the channel's \"react to this\" path, e.g. a widget submission the user expects an\n * audible reaction to ({@link SendContextNote} deliberately never triggers speech).\n * Rides the realtime client's spoken-update channel, so on some providers the spoken\n * reply is narration-kind (ephemeral, not persisted as a caption). OPTIONAL member:\n * older host contexts may not supply it — plugins must call it null-safely.\n */\n RequestSpokenResponse?(instructions: string): void;\n\n /**\n * Persists a snapshot of the channel's state as a first-class versioned artifact\n * (`MJ: Artifacts` + version, linked into conversation history when possible) — e.g. the\n * whiteboard's \"Save to artifacts\". Distinct from {@link RealtimeChannelContext.RequestSave},\n * which maintains the session's rolling state of record. Best-effort: resolves to the\n * created Artifact ID, or `null` on failure (logged host-side, never thrown). Works during\n * the call AND right after it ends (the host retains the session id for late saves).\n */\n SaveAsArtifact(name: string, contentJson: string): Promise<string | null>;\n\n /**\n * The live `MJ: AI Agent Sessions` id this channel belongs to, or `null` before the\n * session has minted / after it has torn down. A channel whose tools or surface drive a\n * SERVER-SIDE resource (e.g. the Remote Browser channel's server-hosted browser) passes\n * this as the `agentSessionID` argument to its own GraphQL resolvers via\n * {@link ExecuteServerAction}. Most channels (whiteboard, shared doc) keep all state\n * client-side and never read it.\n */\n AgentSessionID: string | null;\n\n /**\n * Executes a CHANNEL-SPECIFIC GraphQL operation against the session's MJ server — the\n * escape hatch for channels backed by a SERVER-SIDE resource that the generic\n * {@link RequestSave} / {@link SaveAsArtifact} contract doesn't cover (e.g. the Remote\n * Browser channel driving a server-hosted browser through its own\n * `ExecuteRemoteBrowserAction` mutation + `RemoteBrowserSnapshot` query).\n *\n * The host runs the operation through the SAME provider the live session uses, so the\n * request rides the authenticated session. Best-effort and tolerant: a transport or\n * server error resolves to `null` (logged host-side) rather than throwing, so a channel\n * can map the failure to a model-readable result string without `try/catch`.\n *\n * @typeParam TResult The expected shape of the GraphQL operation's data payload.\n * @param query The GraphQL query/mutation document.\n * @param variables The operation variables (all JSON-serializable).\n * @returns The operation's `data` payload, or `null` on any failure / when no session is live.\n */\n ExecuteServerAction<TResult>(query: string, variables: Record<string, JSONValue>): Promise<TResult | null>;\n\n /**\n * OPTIONAL — the live app-context stream (where the user is, what they see, and the available\n * client-tool + agent manifest), pushed by the host (Explorer) at session start and on subsequent\n * changes. The headless `ClientContextChannel` subscribes to this and streams deltas to the model\n * via {@link SendContextNote}. Absent on hosts that don't supply app context (e.g. custom apps);\n * channels must read it null-safely.\n */\n AppContext$?: Observable<AppContextSnapshot | null>;\n\n /**\n * OPTIONAL — executes a host-registered surface CLIENT TOOL by name (the handlers the host wired\n * from the active surface's `SetAgentClientTools`). The headless `ClientContextChannel`'s\n * `ContextTool` proxy routes the model's `{ action, params }` here so a surface tool runs in the\n * browser with no server round-trip. Best-effort and tolerant — resolves to a structured result\n * (never throws); `Success: false` for an unknown tool or a thrown handler. Absent on hosts that\n * register no client tools.\n *\n * @param name The client-tool name (the model's `action`).\n * @param params The tool parameters (the model's `params`).\n * @returns A structured result the channel serializes back to the model.\n */\n ExecuteClientTool?(\n name: string,\n params: Record<string, unknown>\n ): Promise<{ Success: boolean; Result?: unknown; ErrorMessage?: string }>;\n}\n\n/**\n * The first-run INTRO content for an interactive channel — the concise \"what is this surface\n * and how do I use it\" copy the overlay shows the very first time a user opens this channel's\n * tab (persisted \"seen\" per user, so it's shown ONCE per channel per user).\n *\n * A channel opts in by overriding {@link BaseRealtimeChannelClient.GetOnboardingDetails}; the\n * default returns `null`, so the base Voice/text channel (which has no plugin at all) AND any\n * plugin that doesn't override it show nothing.\n */\nexport interface ChannelOnboardingDetails {\n /** Short title, usually the surface name (e.g. `\"Whiteboard\"`). */\n Heading: string;\n /** One or two sentences: what the surface is and what the user can expect to see on it. */\n Description: string;\n /** Optional quick-tip bullets (kept to 2-3 short, scannable lines). */\n Tips?: string[];\n /** Optional Font Awesome icon class for the intro panel (e.g. `'fa-solid fa-chalkboard'`). */\n IconClass?: string;\n}\n\n/**\n * Base class for CLIENT-SIDE interactive-channel plugins (per\n * `plans/ai-agent-sessions.md` → \"Interactive Channels\" / \"Pluggable Channel Interfaces\").\n *\n * An interactive channel is a bidirectional surface the session's single realtime agent\n * both PERCEIVES and ACTS UPON (whiteboard, shared doc, map, …). A concrete plugin\n * contributes everything the channel needs, so the session service / call overlay carry\n * ZERO channel-specific wiring:\n *\n * 1. a CLIENT-EXECUTED TOOL SET ({@link GetToolDefinitions}, declared to the realtime\n * model at session mint) plus the local executor ({@link ApplyAgentTool}) the host\n * routes `{@link ToolNamePrefix}*` calls to — the ACTION direction;\n * 2. a STATE→CONTEXT SERIALIZER policy — the plugin owns its state engine and pushes\n * coalesced deltas through {@link RealtimeChannelContext.SendContextNote} — the\n * PERCEPTION direction;\n * 3. an OPTIONAL ANGULAR SURFACE ({@link GetSurfaceComponent}) the overlay creates dynamically\n * in a channel tab, handed back through {@link BindSurface} so the plugin wires its own\n * inputs/outputs (the host never knows the component's API). A channel may be **server-only**\n * (no rendered surface) — e.g. a bridge-contributed meeting-controls or native-whiteboard\n * channel whose surface lives on the external platform, not in MJ. Such a channel returns\n * `null` from {@link GetSurfaceComponent} ({@link HasSurface} is `false`) and the overlay\n * simply skips its tab while still wiring its tools + perception;\n * 4. a STATE OF RECORD ({@link SerializeState}, persisted via\n * {@link RealtimeChannelContext.RequestSave} under {@link ChannelName}).\n *\n * ### Registration & resolution (mirrors the realtime model drivers)\n * Concrete plugins are `@RegisterClass(BaseRealtimeChannelClient, '<ClientPluginClass>')`\n * and are resolved at session start from the `MJ: AI Agent Channels` registry: each ACTIVE\n * row's `ClientPluginClass` is the ClassFactory key (exactly how `BaseRealtimeClient`\n * drivers resolve by provider key). Ship a `Load<YourChannel>()` no-op alongside the class\n * and call it from a static code path to defeat tree-shaking.\n *\n * ### Lifecycle — ONE INSTANCE PER SESSION (not a singleton)\n * `ClassFactory.CreateInstance` → {@link Initialize}(ctx) → zero or more\n * {@link BindSurface}/{@link UnbindSurface} cycles (the surface pane is created/destroyed\n * with the overlay's tab panel, e.g. collapse/expand) → {@link Dispose} at teardown.\n * {@link ApplyAgentTool} MUST work with NO surface bound (apply to the state engine\n * directly; skip the UI garnish) — tool calls can arrive while the panel is collapsed.\n *\n * @typeParam TSurface The plugin's Angular surface component type. The host only ever\n * sees the default (`object`) — the typed parameter exists so concrete plugins get a\n * fully typed {@link BindSurface} without casts.\n */\nexport abstract class BaseRealtimeChannelClient<TSurface extends object = object> {\n /**\n * The host context, available from {@link Initialize} until {@link Dispose}.\n * `null` outside that window — guard with `?.` in any code that can run early/late.\n */\n protected Context: RealtimeChannelContext | null = null;\n\n /**\n * The channel definition name — MUST match the `MJ: AI Agent Channels` row's `Name`\n * (e.g. `'Whiteboard'`). Used as the persistence key for {@link SerializeState} saves\n * and as the channel tab's stable key.\n */\n public abstract get ChannelName(): string;\n\n /**\n * The shared name prefix of every tool this channel exposes (e.g. `'Whiteboard_'`).\n * The host registers ONE local-execution route per plugin: tool calls whose name starts\n * with this prefix go to {@link ApplyAgentTool} instead of the server relay.\n */\n public abstract get ToolNamePrefix(): string;\n\n /** Label for the channel's tab on the overlay's surface panel (e.g. `'Whiteboard'`). */\n public abstract get TabTitle(): string;\n\n /** Font Awesome icon class for the channel's tab (e.g. `'fa-solid fa-chalkboard'`). */\n public abstract get TabIcon(): string;\n\n /**\n * OPTIONAL accent color for the channel's tab (a CSS color string, e.g. an `hsl()` /\n * token). When a plugin supplies one, the overlay paints the tab's dot + active underline\n * with it; when omitted (the default `null`), the overlay derives a stable, deterministic\n * color from the {@link ChannelName} so every channel still reads as a distinct, colored\n * surface. A channel only overrides this to enforce a specific brand accent.\n */\n public get TabColor(): string | null {\n return null;\n }\n\n /**\n * The channel's CLIENT-EXECUTED tool declarations, aggregated by the session service\n * into the `clientTools` set declared to the realtime model at session mint. The server\n * only DECLARES these — execution stays in the browser via {@link ApplyAgentTool}.\n */\n public abstract GetToolDefinitions(): RealtimeToolDefinition[];\n\n /**\n * Executes ONE agent tool call locally (the ACTION direction) and returns the result\n * JSON string fed back to the model as the `tool_response`. Called for every tool whose\n * name starts with {@link ToolNamePrefix}. Must work both WITH a bound surface (apply +\n * UI garnish) and WITHOUT one (apply to the state engine directly — the tab pane may not\n * exist, e.g. the surface panel is collapsed). Should not throw: return a\n * `{ success: false, error }` payload so the model can narrate the failure (the host\n * additionally wraps anything thrown).\n */\n public abstract ApplyAgentTool(toolName: string, argsJson: string): string | Promise<string>;\n\n /**\n * The Angular component the overlay creates dynamically as this channel's tab pane, or `null`\n * for a **server-only** channel that renders no MJ surface (its surface, if any, lives on the\n * external platform — e.g. a bridge-contributed native whiteboard or meeting-controls channel).\n *\n * When this returns `null`, the overlay renders NO tab for the channel and never calls\n * {@link BindSurface}/{@link UnbindSurface} — but the channel's tools ({@link GetToolDefinitions} /\n * {@link ApplyAgentTool}) and perception ({@link RealtimeChannelContext.SendContextNote}) still run.\n * A created surface instance is handed straight back via {@link BindSurface}; the host treats it as\n * opaque.\n *\n * Default: `null` (server-only). A channel with a rendered surface overrides this to return its\n * component type.\n */\n public GetSurfaceComponent(): Type<TSurface> | null {\n return null;\n }\n\n /**\n * Whether this channel has a rendered MJ surface ({@link GetSurfaceComponent} returns non-null).\n * The overlay uses this to decide whether to register a surface tab; server-only channels are\n * `false`. Override only if surface availability must be decided WITHOUT constructing the type\n * (the default calls {@link GetSurfaceComponent} once).\n */\n public HasSurface(): boolean {\n return this.GetSurfaceComponent() != null;\n }\n\n /**\n * The channel's FIRST-RUN INTRO content, or `null` when the channel offers no onboarding.\n * The overlay shows this once per channel per user — the first time the user opens this\n * channel's surface tab — and remembers \"seen\" via the user's settings (NOT localStorage),\n * so it never re-appears on later sessions or other devices.\n *\n * Default: `null` (no intro). The base Voice/text channel has no plugin at all, so it never\n * shows an intro; an interactive channel with a surface worth explaining (whiteboard, remote\n * browser, …) overrides this to return its {@link ChannelOnboardingDetails}. A plugin that\n * doesn't override it simply shows nothing — onboarding is strictly opt-in.\n */\n public GetOnboardingDetails(): ChannelOnboardingDetails | null {\n return null;\n }\n\n /**\n * Called by the host right after it created the surface component (and BEFORE the\n * component's first change detection, so inputs set here are visible in its `ngOnInit`).\n * The plugin — which knows its own component type — sets inputs (state engine, agent\n * name, …) and subscribes outputs here, wiring perception/garnish flows back through\n * {@link Context}. May be called again with a NEW instance after an\n * {@link UnbindSurface} (the pane is destroyed/recreated with the tab panel).\n */\n public abstract BindSurface(instance: TSurface): void;\n\n /**\n * Called by the host when the surface component is being destroyed (tab panel\n * collapsed / overlay torn down). Drop the instance reference and unsubscribe any\n * output subscriptions — after this, {@link ApplyAgentTool} runs in its no-surface\n * mode. Default: no-op.\n */\n public UnbindSurface(): void {\n // default: nothing to release\n }\n\n /**\n * Binds the host context and invokes the {@link OnInitialize} hook. Called exactly once\n * per session, right after ClassFactory instantiation and before any tool call or\n * surface bind.\n */\n public Initialize(ctx: RealtimeChannelContext): void {\n this.Context = ctx;\n this.OnInitialize();\n }\n\n /**\n * Subclass hook invoked from {@link Initialize} once {@link Context} is bound — wire\n * state-engine subscriptions (e.g. state change → `Context.RequestSave(...)`) here.\n * Default: no-op.\n */\n protected OnInitialize(): void {\n // default: nothing to initialize\n }\n\n /**\n * Max time {@link ResolveAgentSessionId} waits for the session id to bind before giving up, and the\n * poll interval it re-checks on. Protected so tests can shrink the wait; production keeps the\n * defaults (the real mint race is sub-second, 8s is generous headroom).\n */\n protected SessionIdWaitTimeoutMs = 8000;\n protected SessionIdWaitIntervalMs = 200;\n\n /**\n * Resolves the live {@link RealtimeChannelContext.AgentSessionID}, briefly WAITING for it when it\n * isn't bound yet rather than giving up instantly. `AgentSessionID` is a live getter over the\n * session service's current id: it reads `null` in the window BEFORE the session mints (the\n * realtime model can fire a tool call the very first beat it connects, before `mintSession`\n * resolves) and again AFTER teardown. Server-backed tool paths (e.g. the Remote Browser channel's\n * `browser_*` tools) call this instead of reading `Context?.AgentSessionID` synchronously, so a tool\n * invoked a beat early WAITS for the session to come live — defense-in-depth against the\n * \"session id missing\" race — instead of returning a hard failure to the model.\n *\n * Returns the id as soon as it's non-null (the common path resolves immediately, no delay), or\n * `null` if it's still unbound after {@link SessionIdWaitTimeoutMs} — or the channel was\n * {@link Dispose}d in the meantime (`Context` goes null, so we stop waiting on a torn-down session).\n */\n protected async ResolveAgentSessionId(): Promise<string | null> {\n const immediate = this.Context?.AgentSessionID ?? null;\n if (immediate) {\n return immediate;\n }\n const intervalMs = Math.max(1, this.SessionIdWaitIntervalMs);\n for (let waited = 0; waited < this.SessionIdWaitTimeoutMs; waited += intervalMs) {\n await new Promise<void>((resolve) => setTimeout(resolve, intervalMs));\n // Context goes null on Dispose() — the session is gone, stop waiting.\n if (!this.Context) {\n return null;\n }\n const id = this.Context.AgentSessionID;\n if (id) {\n return id;\n }\n }\n return this.Context?.AgentSessionID ?? null;\n }\n\n /**\n * Serializes the channel's current state of record (the payload persisted on the\n * session's channel row), or `null` when the channel keeps no persistent state.\n * Default: `null`.\n */\n public SerializeState(): string | null {\n return null;\n }\n\n /**\n * Restores a PRIOR session's saved channel state (the payload a previous session\n * persisted via {@link SerializeState} / {@link RealtimeChannelContext.RequestSave}).\n * Invoked by the session host AFTER {@link Initialize} and BEFORE any surface binding,\n * when a prior session's saved state exists for this channel.\n *\n * Returns `true` when the state was applied; `false` when the channel ignored it —\n * either because it keeps no persistent state (this default) or because the payload was\n * malformed/incompatible. Implementations MUST be tolerant: never throw on bad input,\n * just return `false` and start fresh.\n */\n public RestoreState(stateJson: string): boolean {\n return false;\n }\n\n /**\n * The focus pill's \"exit\" affordance, routed by the overlay to the channel that holds\n * focus. Implementations should leave focus mode through their OWN surface (so surface\n * toggles stay in sync), ultimately emitting `Context.SetFocusMode(false)`. The overlay\n * defensively clears its layout flag as well, so a no-op default is safe.\n */\n public RequestFocusExit(): void {\n // default: the overlay's defensive clear handles it\n }\n\n /**\n * Tears the plugin down at session end: release the surface binding, unsubscribe\n * state-engine subscriptions, then drop the context. Subclasses overriding this MUST\n * call `super.Dispose()`. Any final state save has already been flushed by the host\n * (the debounced {@link RealtimeChannelContext.RequestSave} pipeline) before disposal.\n */\n public Dispose(): void {\n this.UnbindSurface();\n this.Context = null;\n }\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { RealtimeToolDefinition } from '@memberjunction/ai';
|
|
2
|
+
import { BaseRealtimeChannelClient } from './base-realtime-channel-client';
|
|
3
|
+
/** The stable name of the single proxy tool this channel registers with the realtime provider. */
|
|
4
|
+
export declare const CONTEXT_TOOL_NAME = "ContextTool";
|
|
5
|
+
/**
|
|
6
|
+
* The headless Client Context channel client. One instance per realtime session (created by the
|
|
7
|
+
* session service from the `MJ: AI Agent Channels` registry — never construct directly).
|
|
8
|
+
*/
|
|
9
|
+
export declare class ClientContextChannel extends BaseRealtimeChannelClient<object> {
|
|
10
|
+
/** Subscription to the host app-context stream (perception); cleared on {@link Dispose}. */
|
|
11
|
+
private appContextSub;
|
|
12
|
+
/** Matches the seeded `MJ: AI Agent Channels` row's `Name`. */
|
|
13
|
+
get ChannelName(): string;
|
|
14
|
+
/** Routing prefix — the single `ContextTool` matches `ContextTool`.startsWith(prefix). */
|
|
15
|
+
get ToolNamePrefix(): string;
|
|
16
|
+
/** Headless — never rendered, but the abstract contract requires a label/icon. */
|
|
17
|
+
get TabTitle(): string;
|
|
18
|
+
get TabIcon(): string;
|
|
19
|
+
/** Declares the single stable proxy tool. */
|
|
20
|
+
GetToolDefinitions(): RealtimeToolDefinition[];
|
|
21
|
+
/**
|
|
22
|
+
* Routes a `ContextTool({ action, params })` call to the host's registered surface client tool.
|
|
23
|
+
* Tolerant: malformed args, a missing host executor, or an unknown/throwing tool all serialize to
|
|
24
|
+
* a structured `{ success: false, output }` the model narrates (never throws).
|
|
25
|
+
*/
|
|
26
|
+
ApplyAgentTool(toolName: string, argsJson: string): Promise<string>;
|
|
27
|
+
/** Headless — no surface to bind. */
|
|
28
|
+
BindSurface(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Subscribes to the host's live app-context stream and streams each change to the model as a
|
|
31
|
+
* compact context note (the perception half). Null-safe — hosts that supply no `AppContext$`
|
|
32
|
+
* (custom apps) simply get no streaming, and the session-start prompt injection still applies.
|
|
33
|
+
*/
|
|
34
|
+
protected OnInitialize(): void;
|
|
35
|
+
/** Tolerantly parses the `{ action, params }` arguments. */
|
|
36
|
+
private parseArgs;
|
|
37
|
+
/** Unsubscribes the app-context stream and tears down. */
|
|
38
|
+
Dispose(): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Tree-shaking prevention for {@link ClientContextChannel}'s `@RegisterClass` registration. Called
|
|
42
|
+
* from a static code path in `conversations.module.ts` so the registration always executes —
|
|
43
|
+
* mirroring every other realtime channel client.
|
|
44
|
+
*/
|
|
45
|
+
export declare function LoadClientContextChannel(): void;
|
|
46
|
+
//# sourceMappingURL=client-context-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-context-channel.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/client-context-channel.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAI5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,kGAAkG;AAClG,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AA0B/C;;;GAGG;AACH,qBACa,oBAAqB,SAAQ,yBAAyB,CAAC,MAAM,CAAC;IACzE,4FAA4F;IAC5F,OAAO,CAAC,aAAa,CAA6B;IAElD,+DAA+D;IAC/D,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED,0FAA0F;IAC1F,IAAW,cAAc,IAAI,MAAM,CAElC;IAED,kFAAkF;IAClF,IAAW,QAAQ,IAAI,MAAM,CAE5B;IACD,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,6CAA6C;IACtC,kBAAkB,IAAI,sBAAsB,EAAE;IAIrD;;;;OAIG;IACU,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBhF,qCAAqC;IAC9B,WAAW,IAAI,IAAI;IAI1B;;;;OAIG;cACgB,YAAY,IAAI,IAAI;IAkBvC,4DAA4D;IAC5D,OAAO,CAAC,SAAS;IAcjB,0DAA0D;IAC1C,OAAO,IAAI,IAAI;CAKhC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|