@memberjunction/ng-conversations 5.40.2 → 5.41.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/README.md +57 -0
- package/dist/__tests__/channel-optional-surface.test.d.ts +2 -0
- package/dist/__tests__/channel-optional-surface.test.d.ts.map +1 -0
- package/dist/__tests__/channel-optional-surface.test.js +53 -0
- package/dist/__tests__/channel-optional-surface.test.js.map +1 -0
- package/dist/__tests__/chat-events.test.d.ts +14 -0
- package/dist/__tests__/chat-events.test.d.ts.map +1 -0
- package/dist/__tests__/chat-events.test.js +109 -0
- package/dist/__tests__/chat-events.test.js.map +1 -0
- package/dist/__tests__/conversation-naming.test.d.ts +2 -0
- package/dist/__tests__/conversation-naming.test.d.ts.map +1 -0
- package/dist/__tests__/conversation-naming.test.js +110 -0
- package/dist/__tests__/conversation-naming.test.js.map +1 -0
- package/dist/__tests__/delegation-result-parser.test.d.ts +2 -0
- package/dist/__tests__/delegation-result-parser.test.d.ts.map +1 -0
- package/dist/__tests__/delegation-result-parser.test.js +107 -0
- package/dist/__tests__/delegation-result-parser.test.js.map +1 -0
- package/dist/__tests__/event-wiring.test.d.ts +15 -0
- package/dist/__tests__/event-wiring.test.d.ts.map +1 -0
- package/dist/__tests__/event-wiring.test.js +100 -0
- package/dist/__tests__/event-wiring.test.js.map +1 -0
- package/dist/__tests__/narration-template.test.d.ts +2 -0
- package/dist/__tests__/narration-template.test.d.ts.map +1 -0
- package/dist/__tests__/narration-template.test.js +76 -0
- package/dist/__tests__/narration-template.test.js.map +1 -0
- package/dist/__tests__/realtime-agent-picker-models.test.d.ts +2 -0
- package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-agent-picker-models.test.js +49 -0
- package/dist/__tests__/realtime-agent-picker-models.test.js.map +1 -0
- package/dist/__tests__/realtime-audio-visuals.test.d.ts +2 -0
- package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-audio-visuals.test.js +123 -0
- package/dist/__tests__/realtime-audio-visuals.test.js.map +1 -0
- package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +2 -0
- package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-delegation-card-cancel.test.js +48 -0
- package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +1 -0
- package/dist/__tests__/realtime-disclosure.test.d.ts +2 -0
- package/dist/__tests__/realtime-disclosure.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-disclosure.test.js +164 -0
- package/dist/__tests__/realtime-disclosure.test.js.map +1 -0
- package/dist/__tests__/realtime-pairing.test.d.ts +2 -0
- package/dist/__tests__/realtime-pairing.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-pairing.test.js +207 -0
- package/dist/__tests__/realtime-pairing.test.js.map +1 -0
- package/dist/__tests__/realtime-review-lifecycle.test.d.ts +2 -0
- package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-review-lifecycle.test.js +154 -0
- package/dist/__tests__/realtime-review-lifecycle.test.js.map +1 -0
- package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-cancel-usage.test.js +230 -0
- package/dist/__tests__/realtime-session-cancel-usage.test.js.map +1 -0
- package/dist/__tests__/realtime-session-channels.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-channels.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-channels.test.js +252 -0
- package/dist/__tests__/realtime-session-channels.test.js.map +1 -0
- package/dist/__tests__/realtime-session-client-tools.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-client-tools.test.js +103 -0
- package/dist/__tests__/realtime-session-client-tools.test.js.map +1 -0
- package/dist/__tests__/realtime-session-minimized.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-minimized.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-minimized.test.js +32 -0
- package/dist/__tests__/realtime-session-minimized.test.js.map +1 -0
- package/dist/__tests__/realtime-session-mint.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-mint.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-mint.test.js +69 -0
- package/dist/__tests__/realtime-session-mint.test.js.map +1 -0
- package/dist/__tests__/realtime-session-policy.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-policy.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-policy.test.js +303 -0
- package/dist/__tests__/realtime-session-policy.test.js.map +1 -0
- package/dist/__tests__/realtime-session-review.service.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-review.service.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-review.service.test.js +743 -0
- package/dist/__tests__/realtime-session-review.service.test.js.map +1 -0
- package/dist/__tests__/realtime-session-state.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-state.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-state.test.js +83 -0
- package/dist/__tests__/realtime-session-state.test.js.map +1 -0
- package/dist/__tests__/realtime-session-timeline-card.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-timeline-card.test.js +106 -0
- package/dist/__tests__/realtime-session-timeline-card.test.js.map +1 -0
- package/dist/__tests__/realtime-session-timeline.test.d.ts +2 -0
- package/dist/__tests__/realtime-session-timeline.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-session-timeline.test.js +142 -0
- package/dist/__tests__/realtime-session-timeline.test.js.map +1 -0
- package/dist/__tests__/realtime-sessions-adapter.test.d.ts +19 -0
- package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-sessions-adapter.test.js +188 -0
- package/dist/__tests__/realtime-sessions-adapter.test.js.map +1 -0
- package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +2 -0
- package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-surface-panel-prefs.test.js +100 -0
- package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +1 -0
- package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +2 -0
- package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +1 -0
- package/dist/__tests__/realtime-surface-tabs-model.test.js +193 -0
- package/dist/__tests__/realtime-surface-tabs-model.test.js.map +1 -0
- package/dist/__tests__/remote-browser-audio-player.test.d.ts +2 -0
- package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +1 -0
- package/dist/__tests__/remote-browser-audio-player.test.js +137 -0
- package/dist/__tests__/remote-browser-audio-player.test.js.map +1 -0
- package/dist/__tests__/remote-browser-channel.test.d.ts +2 -0
- package/dist/__tests__/remote-browser-channel.test.d.ts.map +1 -0
- package/dist/__tests__/remote-browser-channel.test.js +423 -0
- package/dist/__tests__/remote-browser-channel.test.js.map +1 -0
- package/dist/__tests__/slot-defaults.test.d.ts +24 -0
- package/dist/__tests__/slot-defaults.test.d.ts.map +1 -0
- package/dist/__tests__/slot-defaults.test.js +63 -0
- package/dist/__tests__/slot-defaults.test.js.map +1 -0
- package/dist/__tests__/user-authorization.test.d.ts +2 -0
- package/dist/__tests__/user-authorization.test.d.ts.map +1 -0
- package/dist/__tests__/user-authorization.test.js +97 -0
- package/dist/__tests__/user-authorization.test.js.map +1 -0
- package/dist/__tests__/voice-session-narration.test.d.ts +2 -0
- package/dist/__tests__/voice-session-narration.test.d.ts.map +1 -0
- package/dist/__tests__/voice-session-narration.test.js +609 -0
- package/dist/__tests__/voice-session-narration.test.js.map +1 -0
- package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +2 -0
- package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +1 -0
- package/dist/__tests__/whiteboard-artifact-viewer.test.js +101 -0
- package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +1 -0
- package/dist/__tests__/whiteboard-channel.test.d.ts +2 -0
- package/dist/__tests__/whiteboard-channel.test.d.ts.map +1 -0
- package/dist/__tests__/whiteboard-channel.test.js +260 -0
- package/dist/__tests__/whiteboard-channel.test.js.map +1 -0
- package/dist/__tests__/whiteboard-restore-state.test.d.ts +2 -0
- package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +1 -0
- package/dist/__tests__/whiteboard-restore-state.test.js +108 -0
- package/dist/__tests__/whiteboard-restore-state.test.js.map +1 -0
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +205 -3
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +911 -342
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/mention/mention-dropdown.component.js +35 -17
- package/dist/lib/components/mention/mention-dropdown.component.js.map +1 -1
- package/dist/lib/components/mention/mention-editor.component.d.ts +4 -0
- package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
- package/dist/lib/components/mention/mention-editor.component.js +43 -19
- package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
- package/dist/lib/components/message/message-input-box.component.d.ts +17 -1
- package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input-box.component.js +73 -15
- package/dist/lib/components/message/message-input-box.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +142 -6
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +328 -82
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +28 -3
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +180 -108
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +81 -2
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +252 -87
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +282 -0
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -0
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +158 -0
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -0
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts +25 -0
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js +140 -0
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js.map +1 -0
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +35 -0
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +58 -0
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +63 -0
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-activity-rail.component.js +260 -0
- package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +117 -0
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-agent-banner.component.js +504 -0
- package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +168 -0
- package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-agent-picker.component.js +556 -0
- package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +97 -0
- package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-audio-visuals.js +139 -0
- package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -0
- package/dist/lib/components/realtime/realtime-channel-strip.component.d.ts +29 -0
- package/dist/lib/components/realtime/realtime-channel-strip.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-channel-strip.component.js +69 -0
- package/dist/lib/components/realtime/realtime-channel-strip.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-composer.component.d.ts +65 -0
- package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-composer.component.js +256 -0
- package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +71 -0
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-delegation-card.component.js +324 -0
- package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-disclosure.d.ts +135 -0
- package/dist/lib/components/realtime/realtime-disclosure.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-disclosure.js +188 -0
- package/dist/lib/components/realtime/realtime-disclosure.js.map +1 -0
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +491 -0
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-session-overlay.component.js +1274 -0
- package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-session-state.d.ts +191 -0
- package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-session-state.js +244 -0
- package/dist/lib/components/realtime/realtime-session-state.js.map +1 -0
- package/dist/lib/components/realtime/realtime-session-thread.component.d.ts +56 -0
- package/dist/lib/components/realtime/realtime-session-thread.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-session-thread.component.js +246 -0
- package/dist/lib/components/realtime/realtime-session-thread.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +51 -0
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +193 -0
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-panel-prefs.d.ts +77 -0
- package/dist/lib/components/realtime/realtime-surface-panel-prefs.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-panel-prefs.js +114 -0
- package/dist/lib/components/realtime/realtime-surface-panel-prefs.js.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +173 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js +496 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +181 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js +223 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.d.ts +163 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.d.ts.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.js +309 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-audio-player.js.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +168 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +524 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +346 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +851 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts +86 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts.map +1 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js +210 -0
- package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js.map +1 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.d.ts +48 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.js +180 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-artifact-viewer.component.js.map +1 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +119 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +274 -0
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -0
- package/dist/lib/components/slots/mj-chat-agent-presence-default.component.d.ts +11 -0
- package/dist/lib/components/slots/mj-chat-agent-presence-default.component.d.ts.map +1 -0
- package/dist/lib/components/slots/mj-chat-agent-presence-default.component.js +98 -0
- package/dist/lib/components/slots/mj-chat-agent-presence-default.component.js.map +1 -0
- package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.d.ts +9 -0
- package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.d.ts.map +1 -0
- package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.js +35 -0
- package/dist/lib/components/slots/mj-chat-demonstration-surface-default.component.js.map +1 -0
- package/dist/lib/components/slots/mj-chat-empty-state-default.component.d.ts +28 -0
- package/dist/lib/components/slots/mj-chat-empty-state-default.component.d.ts.map +1 -0
- package/dist/lib/components/slots/mj-chat-empty-state-default.component.js +104 -0
- package/dist/lib/components/slots/mj-chat-empty-state-default.component.js.map +1 -0
- package/dist/lib/components/slots/mj-chat-header-default.component.d.ts +11 -0
- package/dist/lib/components/slots/mj-chat-header-default.component.d.ts.map +1 -0
- package/dist/lib/components/slots/mj-chat-header-default.component.js +103 -0
- package/dist/lib/components/slots/mj-chat-header-default.component.js.map +1 -0
- package/dist/lib/components/slots/mj-chat-message-bubble-default.component.d.ts +15 -0
- package/dist/lib/components/slots/mj-chat-message-bubble-default.component.d.ts.map +1 -0
- package/dist/lib/components/slots/mj-chat-message-bubble-default.component.js +73 -0
- package/dist/lib/components/slots/mj-chat-message-bubble-default.component.js.map +1 -0
- package/dist/lib/components/slots/mj-chat-message-extra-default.component.d.ts +9 -0
- package/dist/lib/components/slots/mj-chat-message-extra-default.component.d.ts.map +1 -0
- package/dist/lib/components/slots/mj-chat-message-extra-default.component.js +34 -0
- package/dist/lib/components/slots/mj-chat-message-extra-default.component.js.map +1 -0
- package/dist/lib/components/slots/slot-interfaces.d.ts +95 -0
- package/dist/lib/components/slots/slot-interfaces.d.ts.map +1 -0
- package/dist/lib/components/slots/slot-interfaces.js +18 -0
- package/dist/lib/components/slots/slot-interfaces.js.map +1 -0
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -0
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +28 -4
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/conversations.module.d.ts +12 -1
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js +93 -5
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/directives/chat-slot.directive.d.ts +44 -0
- package/dist/lib/directives/chat-slot.directive.d.ts.map +1 -0
- package/dist/lib/directives/chat-slot.directive.js +54 -0
- package/dist/lib/directives/chat-slot.directive.js.map +1 -0
- package/dist/lib/events/chat-events.d.ts +137 -0
- package/dist/lib/events/chat-events.d.ts.map +1 -0
- package/dist/lib/events/chat-events.js +189 -0
- package/dist/lib/events/chat-events.js.map +1 -0
- package/dist/lib/models/conversation-state.model.d.ts +2 -1
- 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/artifact-state.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-state.service.js +23 -6
- package/dist/lib/services/artifact-state.service.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +60 -74
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +100 -313
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-bridge.service.d.ts +11 -70
- package/dist/lib/services/conversation-bridge.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-bridge.service.js +51 -85
- package/dist/lib/services/conversation-bridge.service.js.map +1 -1
- package/dist/lib/services/conversation-naming.d.ts +63 -0
- package/dist/lib/services/conversation-naming.d.ts.map +1 -0
- package/dist/lib/services/conversation-naming.js +58 -0
- package/dist/lib/services/conversation-naming.js.map +1 -0
- package/dist/lib/services/conversation-streaming.service.d.ts +24 -154
- package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-streaming.service.js +39 -361
- package/dist/lib/services/conversation-streaming.service.js.map +1 -1
- package/dist/lib/services/conversations-runtime-bootstrap.service.d.ts +10 -0
- package/dist/lib/services/conversations-runtime-bootstrap.service.d.ts.map +1 -0
- package/dist/lib/services/conversations-runtime-bootstrap.service.js +104 -0
- package/dist/lib/services/conversations-runtime-bootstrap.service.js.map +1 -0
- package/dist/lib/services/delegation-result-parser.d.ts +45 -0
- package/dist/lib/services/delegation-result-parser.d.ts.map +1 -0
- package/dist/lib/services/delegation-result-parser.js +48 -0
- package/dist/lib/services/delegation-result-parser.js.map +1 -0
- package/dist/lib/services/mention-autocomplete.service.d.ts +19 -4
- package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
- package/dist/lib/services/mention-autocomplete.service.js +65 -4
- package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
- package/dist/lib/services/mention-parser.service.d.ts +8 -53
- package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
- package/dist/lib/services/mention-parser.service.js +32 -243
- package/dist/lib/services/mention-parser.service.js.map +1 -1
- package/dist/lib/services/narration-template.d.ts +42 -0
- package/dist/lib/services/narration-template.d.ts.map +1 -0
- package/dist/lib/services/narration-template.js +73 -0
- package/dist/lib/services/narration-template.js.map +1 -0
- package/dist/lib/services/realtime-pairing.d.ts +120 -0
- package/dist/lib/services/realtime-pairing.d.ts.map +1 -0
- package/dist/lib/services/realtime-pairing.js +150 -0
- package/dist/lib/services/realtime-pairing.js.map +1 -0
- package/dist/lib/services/realtime-session-review.service.d.ts +233 -0
- package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -0
- package/dist/lib/services/realtime-session-review.service.js +417 -0
- package/dist/lib/services/realtime-session-review.service.js.map +1 -0
- package/dist/lib/services/realtime-session.service.d.ts +739 -0
- package/dist/lib/services/realtime-session.service.d.ts.map +1 -0
- package/dist/lib/services/realtime-session.service.js +1647 -0
- package/dist/lib/services/realtime-session.service.js.map +1 -0
- package/dist/lib/services/realtime-sessions-adapter.d.ts +54 -0
- package/dist/lib/services/realtime-sessions-adapter.d.ts.map +1 -0
- package/dist/lib/services/realtime-sessions-adapter.js +154 -0
- package/dist/lib/services/realtime-sessions-adapter.js.map +1 -0
- package/dist/lib/services/user-authorization.d.ts +67 -0
- package/dist/lib/services/user-authorization.d.ts.map +1 -0
- package/dist/lib/services/user-authorization.js +66 -0
- package/dist/lib/services/user-authorization.js.map +1 -0
- package/dist/lib/utils/realtime-session-timeline.d.ts +84 -0
- package/dist/lib/utils/realtime-session-timeline.d.ts.map +1 -0
- package/dist/lib/utils/realtime-session-timeline.js +94 -0
- package/dist/lib/utils/realtime-session-timeline.js.map +1 -0
- package/dist/public-api.d.ts +41 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +50 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +27 -24
- package/dist/__tests__/conversation-bridge.service.test.d.ts +0 -2
- package/dist/__tests__/conversation-bridge.service.test.d.ts.map +0 -1
- package/dist/__tests__/conversation-bridge.service.test.js +0 -98
- package/dist/__tests__/conversation-bridge.service.test.js.map +0 -1
- package/dist/__tests__/mention-parser.test.d.ts +0 -2
- package/dist/__tests__/mention-parser.test.d.ts.map +0 -1
- package/dist/__tests__/mention-parser.test.js +0 -154
- package/dist/__tests__/mention-parser.test.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-session-review.service.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-session-review.service.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';\nimport { Subject } from 'rxjs';\nimport { IMetadataProvider, RunView, RunViewParams } from '@memberjunction/core';\nimport type {\n VoiceCaption,\n VoiceDelegationNarration,\n VoiceDelegationProgress,\n VoiceDelegationResult\n} from '../lib/services/realtime-session.service';\nimport {\n BuildReviewDelegationCard,\n BuildReviewThreadItems,\n MAX_REVIEW_LEGS,\n MergeChainChannelStates,\n RealtimeSessionReview,\n RealtimeSessionReviewLeg,\n RealtimeSessionReviewRun,\n RealtimeSessionReviewService\n} from '../lib/services/realtime-session-review.service';\nimport { RealtimeSessionState, RealtimeThreadItem } from '../lib/components/realtime/realtime-session-state';\n\n/**\n * SESSION REVIEW data layer: the stateless loader that batch-loads a past\n * `MJ: AI Agent Sessions` row + its persisted caption turns + delegated runs (minus the\n * co-agent observability run) + saved channel states, the pure review→thread-item mapping,\n * and `RealtimeSessionState`'s historical population path.\n */\n\n// ── Row builders (the 'simple' result shapes the service consumes) ───────────\n\ninterface FakeResult {\n Success: boolean;\n ErrorMessage?: string;\n Results: object[];\n}\n\nfunction sessionRow(overrides: Record<string, string | null> = {}): object {\n return {\n ID: 'SESSION-1',\n AgentID: 'AGENT-CO',\n Agent: 'Realtime Co-Agent',\n Status: 'Closed',\n ConversationID: 'CONV-1',\n Config: JSON.stringify({ targetAgentID: 'AGENT-TARGET', coAgentRunID: 'RUN-CO' }),\n LastActiveAt: '2026-06-10T10:30:00Z',\n ClosedAt: '2026-06-10T10:31:00Z',\n CloseReason: 'Explicit',\n __mj_CreatedAt: '2026-06-10T10:00:00Z',\n ...overrides\n };\n}\n\nfunction detailRow(role: 'AI' | 'Error' | 'User', message: string | null, at: string, hidden = false): object {\n return { ID: `D-${at}`, Role: role, Message: message, HiddenToUser: hidden, __mj_CreatedAt: at };\n}\n\nfunction runRow(id: string, overrides: Record<string, string | boolean | null> = {}): object {\n return {\n ID: id,\n AgentID: 'AGENT-X',\n Agent: 'Sage',\n Status: 'Completed',\n Success: true,\n Message: 'Did the thing',\n ErrorMessage: null,\n FinalStep: 'Success',\n StartedAt: '2026-06-10T10:05:00Z',\n CompletedAt: '2026-06-10T10:06:00Z',\n ...overrides\n };\n}\n\nfunction channelRow(channel: string | null, config: string | null): object {\n return { ID: `CH-${channel ?? 'x'}`, Channel: channel, Config: config };\n}\n\n// ── RunViews mock plumbing (suite convention: spy on RunView.FromMetadataProvider) ──\n\nlet capturedParams: RunViewParams[] = [];\n/** EVERY RunViews call's params, in call order (chain walks issue several calls). */\nlet capturedCalls: RunViewParams[][] = [];\n\nfunction mockRunViews(results: FakeResult[]): void {\n const runViewsFn = vi.fn(async (params: RunViewParams[]) => {\n capturedParams = params;\n capturedCalls.push(params);\n return results;\n });\n vi.spyOn(RunView, 'FromMetadataProvider').mockReturnValue({ RunViews: runViewsFn } as unknown as RunView);\n}\n\n/**\n * Sequenced RunViews mock: call N returns `sequence[N]` (the last entry repeats when the\n * sequence runs out). Lets chain-walk tests serve different rows per leg / per artifact query.\n */\nfunction mockRunViewsSequence(sequence: FakeResult[][]): void {\n let call = 0;\n const runViewsFn = vi.fn(async (params: RunViewParams[]) => {\n capturedParams = params;\n capturedCalls.push(params);\n const results = sequence[Math.min(call, sequence.length - 1)];\n call++;\n return results;\n });\n vi.spyOn(RunView, 'FromMetadataProvider').mockReturnValue({ RunViews: runViewsFn } as unknown as RunView);\n}\n\nfunction ok(rows: object[]): FakeResult {\n return { Success: true, Results: rows };\n}\n\nfunction failed(): FakeResult {\n return { Success: false, ErrorMessage: 'boom', Results: [] };\n}\n\nconst provider = {} as unknown as IMetadataProvider;\n\ndescribe('RealtimeSessionReviewService', () => {\n let service: RealtimeSessionReviewService;\n\n beforeEach(() => {\n service = new RealtimeSessionReviewService();\n capturedParams = [];\n capturedCalls = [];\n });\n\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n describe('LoadSessionReview — null paths', () => {\n it('returns null when the session row does not exist', async () => {\n mockRunViews([ok([]), ok([]), ok([]), ok([])]);\n const review = await service.LoadSessionReview('SESSION-MISSING', provider);\n expect(review).toBeNull();\n });\n\n it('returns null when the session query itself fails', async () => {\n mockRunViews([failed(), ok([]), ok([]), ok([])]);\n expect(await service.LoadSessionReview('SESSION-1', provider)).toBeNull();\n });\n\n it('returns null for an empty / whitespace id without querying', async () => {\n const spy = vi.spyOn(RunView, 'FromMetadataProvider');\n expect(await service.LoadSessionReview(' ', provider)).toBeNull();\n expect(spy).not.toHaveBeenCalled();\n });\n\n it('returns null (never throws) when the batch load rejects', async () => {\n vi.spyOn(RunView, 'FromMetadataProvider').mockReturnValue({\n RunViews: vi.fn(async () => {\n throw new Error('network down');\n })\n } as unknown as RunView);\n const errSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);\n expect(await service.LoadSessionReview('SESSION-1', provider)).toBeNull();\n expect(errSpy).toHaveBeenCalled();\n });\n });\n\n describe('LoadSessionReview — query shape', () => {\n it('issues ONE batched RunViews call covering session, details, runs, and channels', async () => {\n mockRunViews([ok([sessionRow()]), ok([]), ok([]), ok([])]);\n await service.LoadSessionReview('SESSION-1', provider);\n expect(capturedParams.map(p => p.EntityName)).toEqual([\n 'MJ: AI Agent Sessions',\n 'MJ: Conversation Details',\n 'MJ: AI Agent Runs',\n 'MJ: AI Agent Session Channels'\n ]);\n for (const p of capturedParams) {\n expect(p.ResultType).toBe('simple');\n expect(p.Fields?.length).toBeGreaterThan(0);\n }\n });\n\n it('escapes single quotes in the session id used in filters', async () => {\n mockRunViews([ok([]), ok([]), ok([]), ok([])]);\n await service.LoadSessionReview(\"abc'def\", provider);\n expect(capturedParams[0].ExtraFilter).toBe(\"ID='abc''def'\");\n expect(capturedParams[1].ExtraFilter).toBe(\"AgentSessionID='abc''def'\");\n });\n\n it('orders turns and runs chronologically at the database', async () => {\n mockRunViews([ok([sessionRow()]), ok([]), ok([]), ok([])]);\n await service.LoadSessionReview('SESSION-1', provider);\n expect(capturedParams[1].OrderBy).toBe('__mj_CreatedAt ASC');\n expect(capturedParams[2].OrderBy).toBe('StartedAt ASC');\n });\n });\n\n describe('LoadSessionReview — session mapping', () => {\n it('maps identity, lifecycle, and the Config targetAgentID', async () => {\n mockRunViews([ok([sessionRow()]), ok([]), ok([]), ok([])]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review).not.toBeNull();\n expect(review?.SessionID).toBe('SESSION-1');\n expect(review?.AgentID).toBe('AGENT-CO');\n expect(review?.AgentName).toBe('Realtime Co-Agent');\n expect(review?.TargetAgentID).toBe('AGENT-TARGET');\n expect(review?.ConversationID).toBe('CONV-1');\n expect(review?.Status).toBe('Closed');\n expect(review?.CloseReason).toBe('Explicit');\n expect(review?.StartedAt?.toISOString()).toBe('2026-06-10T10:00:00.000Z');\n expect(review?.ClosedAt?.toISOString()).toBe('2026-06-10T10:31:00.000Z');\n });\n\n it('falls back to the session AgentID when the Config carries no targetAgentID', async () => {\n mockRunViews([ok([sessionRow({ Config: '{}' })]), ok([]), ok([]), ok([])]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.TargetAgentID).toBe('AGENT-CO');\n });\n\n it('tolerates malformed Config JSON (fallback target, no run exclusion)', async () => {\n mockRunViews([ok([sessionRow({ Config: '{not json' })]), ok([]), ok([runRow('RUN-CO')]), ok([])]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.TargetAgentID).toBe('AGENT-CO');\n expect(review?.DelegatedRuns.map(r => r.RunID)).toEqual(['RUN-CO']);\n });\n\n it('degrades failed sub-queries to empty collections (review still loads)', async () => {\n mockRunViews([ok([sessionRow()]), failed(), failed(), failed()]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review).not.toBeNull();\n expect(review?.Turns).toEqual([]);\n expect(review?.DelegatedRuns).toEqual([]);\n expect(review?.ChannelStates).toEqual([]);\n });\n });\n\n describe('LoadSessionReview — turn mapping', () => {\n it('maps visible User/AI rows in order, translating AI → Assistant', async () => {\n mockRunViews([\n ok([sessionRow()]),\n ok([\n detailRow('User', 'Hello there', '2026-06-10T10:01:00Z'),\n detailRow('AI', 'Hi! How can I help?', '2026-06-10T10:01:30Z')\n ]),\n ok([]),\n ok([])\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.Turns).toHaveLength(2);\n expect(review?.Turns[0]).toMatchObject({ Role: 'User', Text: 'Hello there' });\n expect(review?.Turns[1]).toMatchObject({ Role: 'Assistant', Text: 'Hi! How can I help?' });\n expect(review?.Turns[0].At?.toISOString()).toBe('2026-06-10T10:01:00.000Z');\n });\n\n it('skips Error rows, hidden rows, and empty messages', async () => {\n mockRunViews([\n ok([sessionRow()]),\n ok([\n detailRow('Error', 'something broke', '2026-06-10T10:01:00Z'),\n detailRow('User', 'visible', '2026-06-10T10:02:00Z'),\n detailRow('AI', 'secret', '2026-06-10T10:03:00Z', true),\n detailRow('AI', ' ', '2026-06-10T10:04:00Z'),\n detailRow('AI', null, '2026-06-10T10:05:00Z')\n ]),\n ok([]),\n ok([])\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.Turns.map(t => t.Text)).toEqual(['visible']);\n });\n });\n\n describe('LoadSessionReview — delegated-run mapping', () => {\n it(\"EXCLUDES the co-agent observability run named in the session Config's coAgentRunID\", async () => {\n mockRunViews([\n ok([sessionRow()]),\n ok([]),\n ok([runRow('RUN-CO'), runRow('RUN-1'), runRow('RUN-2')]),\n ok([])\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.DelegatedRuns.map(r => r.RunID)).toEqual(['RUN-1', 'RUN-2']);\n });\n\n it('matches the co-agent run id case-insensitively (SQL Server vs PostgreSQL casing)', async () => {\n mockRunViews([\n ok([sessionRow({ Config: JSON.stringify({ coAgentRunID: 'run-co' }) })]),\n ok([]),\n ok([runRow('RUN-CO'), runRow('RUN-1')]),\n ok([])\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.DelegatedRuns.map(r => r.RunID)).toEqual(['RUN-1']);\n });\n\n it('maps the run preview fields (status, success, messages, timing)', async () => {\n mockRunViews([\n ok([sessionRow()]),\n ok([]),\n ok([runRow('RUN-1', { Status: 'Failed', Success: false, Message: null, ErrorMessage: 'it failed', FinalStep: 'Failed' })]),\n ok([])\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n const run = review?.DelegatedRuns[0];\n expect(run).toMatchObject({\n RunID: 'RUN-1',\n AgentName: 'Sage',\n Status: 'Failed',\n Success: false,\n ErrorMessage: 'it failed',\n FinalStep: 'Failed'\n });\n expect(run?.StartedAt?.toISOString()).toBe('2026-06-10T10:05:00.000Z');\n expect(run?.CompletedAt?.toISOString()).toBe('2026-06-10T10:06:00.000Z');\n });\n });\n\n describe('LoadSessionReview — channel-state extraction', () => {\n it('maps named channel rows to {ChannelName, StateJson} and skips unnamed rows', async () => {\n mockRunViews([\n ok([sessionRow()]),\n ok([]),\n ok([]),\n ok([\n channelRow('Whiteboard', '{\"items\":[]}'),\n channelRow('Voice', null),\n channelRow(null, '{\"orphan\":true}')\n ])\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.ChannelStates).toEqual([\n { ChannelName: 'Whiteboard', StateJson: '{\"items\":[]}' },\n { ChannelName: 'Voice', StateJson: null }\n ]);\n });\n });\n\n describe('LoadSessionReview — session-chain walk (lastSessionId legs)', () => {\n it('surfaces a SINGLE leg (no extra queries) when the session has no LastSessionID', async () => {\n mockRunViews([ok([sessionRow()]), ok([]), ok([]), ok([])]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.Legs).toHaveLength(1);\n expect(review?.Legs[0].SessionID).toBe('SESSION-1');\n expect(capturedCalls).toHaveLength(1);\n });\n\n it('walks the chain BACKWARDS and orders legs (and flattened turns) chronologically', async () => {\n mockRunViewsSequence([\n // Call 1: the reviewed (newest) leg — points back at SESSION-A.\n [\n ok([sessionRow({ ID: 'SESSION-B', LastSessionID: 'SESSION-A', __mj_CreatedAt: '2026-06-10T11:00:00Z' })]),\n ok([detailRow('User', 'second leg turn', '2026-06-10T11:01:00Z')]),\n ok([]),\n ok([])\n ],\n // Call 2: the PRIOR leg.\n [\n ok([sessionRow({ ID: 'SESSION-A', CloseReason: 'Janitor', __mj_CreatedAt: '2026-06-10T10:00:00Z' })]),\n ok([detailRow('User', 'first leg turn', '2026-06-10T10:01:00Z')]),\n ok([])\n ],\n // Call 3: artifact junction query — none.\n [ok([])]\n ]);\n\n const review = await service.LoadSessionReview('SESSION-B', provider);\n\n expect(review?.Legs.map(l => l.SessionID)).toEqual(['SESSION-A', 'SESSION-B']);\n expect(review?.Legs[0].CloseReason).toBe('Janitor');\n expect(review?.Turns.map(t => t.Text)).toEqual(['first leg turn', 'second leg turn']);\n // Prior-leg query carries NO channel query (channel state is latest-leg-only).\n expect(capturedCalls[1].map(p => p.EntityName)).toEqual([\n 'MJ: AI Agent Sessions',\n 'MJ: Conversation Details',\n 'MJ: AI Agent Runs'\n ]);\n });\n\n it('excludes each leg\\'s OWN co-agent observability run (per-leg Config)', async () => {\n mockRunViewsSequence([\n [\n ok([sessionRow({ ID: 'SESSION-B', LastSessionID: 'SESSION-A', Config: JSON.stringify({ coAgentRunID: 'RUN-CO-B' }) })]),\n ok([]),\n ok([runRow('RUN-CO-B'), runRow('RUN-B1')]),\n ok([])\n ],\n [\n ok([sessionRow({ ID: 'SESSION-A', Config: JSON.stringify({ coAgentRunID: 'RUN-CO-A' }) })]),\n ok([]),\n ok([runRow('RUN-CO-A'), runRow('RUN-A1')])\n ]\n ]);\n const review = await service.LoadSessionReview('SESSION-B', provider);\n expect(review?.DelegatedRuns.map(r => r.RunID)).toEqual(['RUN-A1', 'RUN-B1']);\n });\n\n it(`caps the walk at ${MAX_REVIEW_LEGS} legs even when the chain is longer`, async () => {\n // Every leg load returns a session that points at yet another prior session.\n let n = 0;\n const legResult = (): FakeResult[] => {\n n++;\n return [\n ok([sessionRow({ ID: `SESSION-${n}`, LastSessionID: `SESSION-${n + 1}` })]),\n ok([]),\n ok([]),\n ok([])\n ];\n };\n mockRunViewsSequence(Array.from({ length: 10 }, legResult));\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.Legs).toHaveLength(MAX_REVIEW_LEGS);\n });\n\n it('NEVER loops on a cyclic chain (A→B→A) — the cycle guard stops the walk', async () => {\n const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);\n mockRunViewsSequence([\n [ok([sessionRow({ ID: 'SESSION-A', LastSessionID: 'SESSION-B' })]), ok([]), ok([]), ok([])],\n // SESSION-B points BACK at SESSION-A (already visited).\n [ok([sessionRow({ ID: 'SESSION-B', LastSessionID: 'SESSION-A' })]), ok([]), ok([])]\n ]);\n const review = await service.LoadSessionReview('SESSION-A', provider);\n expect(review?.Legs.map(l => l.SessionID)).toEqual(['SESSION-B', 'SESSION-A']);\n expect(warnSpy).toHaveBeenCalled();\n });\n\n it('matches the cycle guard case-insensitively (SQL Server vs PostgreSQL casing)', async () => {\n mockRunViewsSequence([\n [ok([sessionRow({ ID: 'SESSION-A', LastSessionID: 'SESSION-B' })]), ok([]), ok([]), ok([])],\n [ok([sessionRow({ ID: 'SESSION-B', LastSessionID: 'session-a' })]), ok([]), ok([])]\n ]);\n const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);\n const review = await service.LoadSessionReview('SESSION-A', provider);\n expect(review?.Legs).toHaveLength(2);\n expect(warnSpy).toHaveBeenCalled();\n });\n\n it('ends the walk (review still loads) when a prior leg cannot be found', async () => {\n mockRunViewsSequence([\n [ok([sessionRow({ ID: 'SESSION-B', LastSessionID: 'SESSION-GONE' })]), ok([]), ok([]), ok([])],\n [ok([]), ok([]), ok([])] // prior session row missing\n ]);\n const review = await service.LoadSessionReview('SESSION-B', provider);\n expect(review?.Legs.map(l => l.SessionID)).toEqual(['SESSION-B']);\n });\n\n it('trims an older leg to the NEWEST rows when the 500-detail budget runs out, and stops walking', async () => {\n const manyDetails = Array.from({ length: 498 }, (_, i) =>\n detailRow('User', `turn ${i}`, `2026-06-10T11:00:${String(i % 60).padStart(2, '0')}Z`)\n );\n mockRunViewsSequence([\n [ok([sessionRow({ ID: 'SESSION-C', LastSessionID: 'SESSION-B' })]), ok(manyDetails), ok([]), ok([])],\n [\n ok([sessionRow({ ID: 'SESSION-B', LastSessionID: 'SESSION-A' })]),\n ok([\n detailRow('User', 'oldest — trimmed', '2026-06-10T10:01:00Z'),\n detailRow('User', 'kept 1', '2026-06-10T10:02:00Z'),\n detailRow('User', 'kept 2', '2026-06-10T10:03:00Z')\n ]),\n ok([])\n ],\n // Artifact junction query (NOT another leg — the walk must have stopped).\n [ok([])]\n ]);\n\n const review = await service.LoadSessionReview('SESSION-C', provider);\n\n expect(review?.Legs.map(l => l.SessionID)).toEqual(['SESSION-B', 'SESSION-C']);\n expect(review?.Legs[0].Turns.map(t => t.Text)).toEqual(['kept 1', 'kept 2']);\n expect(review?.Turns).toHaveLength(500);\n // No third LEG query was issued: call 3 is the artifact junction query.\n expect(capturedCalls[2][0].EntityName).toBe('MJ: Conversation Detail Artifacts');\n });\n });\n\n describe('LoadSessionReview — artifact collection', () => {\n function junctionRow(versionId: string | null, detailId = 'D-1'): object {\n return { ID: `J-${versionId ?? 'x'}`, ConversationDetailID: detailId, ArtifactVersionID: versionId };\n }\n function versionRow(id: string, artifactId: string, name: string | null, artifactName: string | null = 'Parent Artifact'): object {\n return { ID: id, ArtifactID: artifactId, Name: name, Artifact: artifactName };\n }\n\n it('collects {ArtifactID, ArtifactVersionID, Name} through the junction → version queries', async () => {\n mockRunViewsSequence([\n [ok([sessionRow()]), ok([detailRow('User', 'hi', '2026-06-10T10:01:00Z')]), ok([]), ok([])],\n [ok([junctionRow('AV-1'), junctionRow('AV-2')])],\n [ok([versionRow('AV-1', 'A-1', 'Quarterly Report'), versionRow('AV-2', 'A-2', null, 'Member Chart')])]\n ]);\n\n const review = await service.LoadSessionReview('SESSION-1', provider);\n\n expect(review?.Artifacts).toEqual([\n { ArtifactID: 'A-1', ArtifactVersionID: 'AV-1', Name: 'Quarterly Report' },\n { ArtifactID: 'A-2', ArtifactVersionID: 'AV-2', Name: 'Member Chart' } // version Name null → artifact name\n ]);\n // Junction query filters the chain's detail ids + Output direction.\n const junctionParams = capturedCalls[1][0];\n expect(junctionParams.EntityName).toBe('MJ: Conversation Detail Artifacts');\n expect(junctionParams.ExtraFilter).toContain(\"ConversationDetailID IN ('D-2026-06-10T10:01:00Z')\");\n expect(junctionParams.ExtraFilter).toContain(\"Direction='Output'\");\n // Version query loads the junctioned version ids.\n const versionParams = capturedCalls[2][0];\n expect(versionParams.EntityName).toBe('MJ: Artifact Versions');\n expect(versionParams.ExtraFilter).toBe(\"ID IN ('AV-1','AV-2')\");\n });\n\n it('dedupes duplicate versions, skips null version ids and unresolvable versions', async () => {\n mockRunViewsSequence([\n [ok([sessionRow()]), ok([detailRow('User', 'hi', '2026-06-10T10:01:00Z')]), ok([]), ok([])],\n [ok([junctionRow('AV-1'), junctionRow('AV-1'), junctionRow(null), junctionRow('AV-GONE')])],\n [ok([versionRow('AV-1', 'A-1', 'Report')])]\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.Artifacts).toEqual([{ ArtifactID: 'A-1', ArtifactVersionID: 'AV-1', Name: 'Report' }]);\n });\n\n it('issues NO artifact queries when the chain has no caption details', async () => {\n mockRunViews([ok([sessionRow()]), ok([]), ok([]), ok([])]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review?.Artifacts).toEqual([]);\n expect(capturedCalls).toHaveLength(1);\n });\n\n it('degrades a failed junction query to an empty Artifacts list (review still loads)', async () => {\n mockRunViewsSequence([\n [ok([sessionRow()]), ok([detailRow('User', 'hi', '2026-06-10T10:01:00Z')]), ok([]), ok([])],\n [failed()]\n ]);\n const review = await service.LoadSessionReview('SESSION-1', provider);\n expect(review).not.toBeNull();\n expect(review?.Artifacts).toEqual([]);\n });\n });\n});\n\n// ── Pure review → thread-item mapping ────────────────────────────────────────\n\nfunction reviewFixture(overrides: Partial<RealtimeSessionReview> = {}): RealtimeSessionReview {\n return {\n SessionID: 'SESSION-1',\n AgentID: 'AGENT-CO',\n AgentName: 'Skye',\n TargetAgentID: 'AGENT-TARGET',\n ConversationID: 'CONV-1',\n Status: 'Closed',\n CloseReason: 'Explicit',\n StartedAt: new Date('2026-06-10T10:00:00Z'),\n LastActiveAt: new Date('2026-06-10T10:30:00Z'),\n ClosedAt: new Date('2026-06-10T10:31:00Z'),\n Turns: [],\n DelegatedRuns: [],\n ChannelStates: [],\n Legs: [],\n Artifacts: [],\n ...overrides\n };\n}\n\nfunction legFixture(overrides: Partial<RealtimeSessionReviewLeg> = {}): RealtimeSessionReviewLeg {\n return {\n SessionID: 'SESSION-1',\n StartedAt: new Date('2026-06-10T10:00:00Z'),\n ClosedAt: new Date('2026-06-10T10:31:00Z'),\n CloseReason: 'Explicit',\n Turns: [],\n DelegatedRuns: [],\n ...overrides\n };\n}\n\nfunction reviewRun(id: string, startedAt: string | null, overrides: Partial<RealtimeSessionReviewRun> = {}): RealtimeSessionReviewRun {\n return {\n RunID: id,\n AgentID: 'AGENT-X',\n AgentName: 'Sage',\n Status: 'Completed',\n Success: true,\n Message: 'done',\n ErrorMessage: null,\n FinalStep: 'Success',\n StartedAt: startedAt ? new Date(startedAt) : null,\n CompletedAt: startedAt ? new Date(new Date(startedAt).getTime() + 60_000) : null,\n ...overrides\n };\n}\n\ndescribe('BuildReviewThreadItems', () => {\n it('interleaves turns and delegation cards chronologically (oldest first)', () => {\n const review = reviewFixture({\n Turns: [\n { Role: 'User', Text: 'first', At: new Date('2026-06-10T10:01:00Z') },\n { Role: 'Assistant', Text: 'third', At: new Date('2026-06-10T10:06:00Z') }\n ],\n DelegatedRuns: [reviewRun('RUN-1', '2026-06-10T10:03:00Z')]\n });\n const items = BuildReviewThreadItems(review);\n expect(items.map(i => i.Kind)).toEqual(['caption', 'delegation', 'caption']);\n expect(items[0]).toMatchObject({ Kind: 'caption', Role: 'User', Text: 'first' });\n expect(items[2]).toMatchObject({ Kind: 'caption', Role: 'Assistant', Text: 'third' });\n });\n\n it('keeps build order for entries without timestamps (stable sort to the front)', () => {\n const review = reviewFixture({\n Turns: [\n { Role: 'User', Text: 'a', At: null },\n { Role: 'Assistant', Text: 'b', At: null }\n ],\n DelegatedRuns: [reviewRun('RUN-1', '2026-06-10T10:03:00Z')]\n });\n const items = BuildReviewThreadItems(review);\n expect(items.map(i => (i.Kind === 'caption' ? i.Text : i.Kind === 'delegation' ? i.Card.CallID : i.Label))).toEqual(['a', 'b', 'RUN-1']);\n });\n\n it('names cards after the run agent, falling back to the review agent', () => {\n const review = reviewFixture({\n DelegatedRuns: [\n reviewRun('RUN-1', '2026-06-10T10:03:00Z'),\n reviewRun('RUN-2', '2026-06-10T10:04:00Z', { AgentName: null })\n ]\n });\n const items = BuildReviewThreadItems(review);\n const names = items.map(i => (i.Kind === 'delegation' ? i.Card.AgentName : ''));\n expect(names).toEqual(['Sage', 'Skye']);\n });\n\n it('renders a SINGLE leg with no divider (identical to the flat thread)', () => {\n const review = reviewFixture({\n Legs: [\n legFixture({\n Turns: [{ Role: 'User', Text: 'hello', At: new Date('2026-06-10T10:01:00Z') }],\n DelegatedRuns: [reviewRun('RUN-1', '2026-06-10T10:03:00Z')]\n })\n ]\n });\n const items = BuildReviewThreadItems(review);\n expect(items.map(i => i.Kind)).toEqual(['caption', 'delegation']);\n });\n\n it('renders a DIVIDER between legs, stamped with the new leg start + the PREVIOUS leg\\'s CloseReason', () => {\n const review = reviewFixture({\n Legs: [\n legFixture({\n SessionID: 'SESSION-A',\n CloseReason: 'Janitor',\n Turns: [{ Role: 'User', Text: 'leg one', At: new Date('2026-06-10T10:01:00Z') }]\n }),\n legFixture({\n SessionID: 'SESSION-B',\n StartedAt: new Date('2026-06-10T11:00:00Z'),\n CloseReason: 'Explicit',\n Turns: [{ Role: 'Assistant', Text: 'leg two', At: new Date('2026-06-10T11:01:00Z') }]\n })\n ]\n });\n const items = BuildReviewThreadItems(review);\n expect(items.map(i => i.Kind)).toEqual(['caption', 'divider', 'caption']);\n const divider = items[1];\n if (divider.Kind !== 'divider') {\n throw new Error('expected a divider');\n }\n expect(divider.Label).toBe('Session leg started');\n expect(divider.At?.toISOString()).toBe('2026-06-10T11:00:00.000Z');\n expect(divider.CloseReason).toBe('Janitor'); // why the PREVIOUS leg ended\n expect(divider.Icon).toContain('fa-');\n });\n\n it('keeps leg boundaries even when item timestamps interleave across legs', () => {\n // Leg B starts BEFORE leg A's last item timestamp — the divider must still sit between legs.\n const review = reviewFixture({\n Legs: [\n legFixture({ Turns: [{ Role: 'User', Text: 'a-late', At: new Date('2026-06-10T12:00:00Z') }] }),\n legFixture({\n StartedAt: new Date('2026-06-10T11:00:00Z'),\n Turns: [{ Role: 'User', Text: 'b-early', At: new Date('2026-06-10T11:30:00Z') }]\n })\n ]\n });\n const texts = BuildReviewThreadItems(review).map(i => (i.Kind === 'caption' ? i.Text : i.Kind));\n expect(texts).toEqual(['a-late', 'divider', 'b-early']);\n });\n});\n\n// ── Review→live continuation (StartLiveContinuation) ────────────────────────\n\ndescribe('RealtimeSessionState.StartLiveContinuation', () => {\n function loadedState(): RealtimeSessionState {\n const state = new RealtimeSessionState();\n state.LoadHistoricalItems(\n BuildReviewThreadItems(\n reviewFixture({\n Turns: [{ Role: 'User', Text: 'historical', At: new Date('2026-06-10T10:01:00Z') }],\n DelegatedRuns: [reviewRun('RUN-1', '2026-06-10T10:03:00Z')]\n })\n )\n );\n return state;\n }\n\n it('KEEPS the historical thread and appends the \"Resumed live session\" divider', () => {\n const state = loadedState();\n let changes = 0;\n state.Changed$.subscribe(() => changes++);\n\n state.StartLiveContinuation(new Date('2026-06-10T12:00:00Z'));\n\n expect(changes).toBe(1);\n expect(state.Items.map(i => i.Kind)).toEqual(['caption', 'delegation', 'divider']);\n const divider = state.Items[2];\n if (divider.Kind !== 'divider') {\n throw new Error('expected a divider');\n }\n expect(divider.Label).toBe('Resumed live session');\n expect(divider.At?.toISOString()).toBe('2026-06-10T12:00:00.000Z');\n expect(divider.CloseReason).toBeUndefined();\n });\n\n it('keeps the historical delegation cards in the rail (carryover, not a reset)', () => {\n const state = loadedState();\n state.StartLiveContinuation();\n expect(state.Cards.map(c => c.CallID)).toEqual(['RUN-1']);\n expect(state.ActiveCallId).toBeNull();\n });\n\n it('resets the caption bookkeeping so the NEW session\\'s captions append AFTER the divider', () => {\n const state = loadedState();\n const captions$ = new Subject<VoiceCaption[]>();\n state.Attach({\n Captions$: captions$.asObservable(),\n DelegationProgress$: new Subject<VoiceDelegationProgress>().asObservable(),\n DelegationResult$: new Subject<VoiceDelegationResult>().asObservable(),\n DelegationNarration$: new Subject<VoiceDelegationNarration>().asObservable()\n });\n\n state.StartLiveContinuation();\n // The fresh session's caption stream starts EMPTY — must be a no-op, not a reset.\n captions$.next([]);\n expect(state.Items).toHaveLength(3);\n\n captions$.next([{ Role: 'User', Text: 'live turn' }]);\n expect(state.Items.map(i => i.Kind)).toEqual(['caption', 'delegation', 'divider', 'caption']);\n const live = state.Items[3];\n expect(live.Kind === 'caption' && live.Text).toBe('live turn');\n });\n\n it('drops any lingering narration (nothing is running yet in the new leg)', () => {\n const state = loadedState();\n (state as unknown as { Narration: string | null }).Narration = 'old note';\n state.StartLiveContinuation();\n expect(state.Narration).toBeNull();\n });\n});\n\ndescribe('BuildReviewDelegationCard', () => {\n it('builds a DONE card carrying the run id, ref, result, and timing', () => {\n const card = BuildReviewDelegationCard(reviewRun('RUN-abc1', '2026-06-10T10:03:00Z'), 'Skye');\n expect(card.Done).toBe(true);\n expect(card.Success).toBe(true);\n expect(card.CallID).toBe('RUN-abc1');\n expect(card.RunID).toBe('RUN-abc1');\n expect(card.RunRef).toBe('#abc1');\n expect(card.Result).toBe('done');\n expect(card.StartedAt).toBe(new Date('2026-06-10T10:03:00Z').getTime());\n expect(card.FinishedAt).toBe(new Date('2026-06-10T10:04:00Z').getTime());\n });\n\n it('prefers the run Message, then ErrorMessage, then Status for the card text', () => {\n const failedCard = BuildReviewDelegationCard(\n reviewRun('RUN-1', '2026-06-10T10:03:00Z', { Success: false, Message: null, ErrorMessage: 'exploded' }),\n 'Skye'\n );\n expect(failedCard.Success).toBe(false);\n expect(failedCard.LatestMessage).toBe('exploded');\n expect(failedCard.Result).toBe('exploded');\n\n const bareCard = BuildReviewDelegationCard(\n reviewRun('RUN-2', null, { Message: null, ErrorMessage: null, FinalStep: null, Status: 'Cancelled' }),\n 'Skye'\n );\n expect(bareCard.LatestMessage).toBe('Cancelled');\n expect(bareCard.Result).toBeNull();\n expect(bareCard.StartedAt).toBe(0);\n });\n});\n\n// ── RealtimeSessionState historical population ───────────────────────────────\n\ndescribe('RealtimeSessionState.LoadHistoricalItems', () => {\n let state: RealtimeSessionState;\n\n beforeEach(() => {\n state = new RealtimeSessionState();\n });\n\n function historicalItems(): RealtimeThreadItem[] {\n return BuildReviewThreadItems(\n reviewFixture({\n Turns: [{ Role: 'User', Text: 'hello', At: new Date('2026-06-10T10:01:00Z') }],\n DelegatedRuns: [\n reviewRun('RUN-1', '2026-06-10T10:03:00Z'),\n reviewRun('RUN-2', '2026-06-10T10:05:00Z')\n ]\n })\n );\n }\n\n it('replaces the thread with the historical items and emits Changed$', () => {\n let changes = 0;\n state.Changed$.subscribe(() => changes++);\n state.LoadHistoricalItems(historicalItems());\n expect(changes).toBe(1);\n expect(state.Items.map(i => i.Kind)).toEqual(['caption', 'delegation', 'delegation']);\n });\n\n it('derives the rail Cards NEWEST first and no active call (all cards done)', () => {\n state.LoadHistoricalItems(historicalItems());\n expect(state.Cards.map(c => c.CallID)).toEqual(['RUN-2', 'RUN-1']);\n expect(state.ActiveCallId).toBeNull();\n expect(state.HasRunningDelegation).toBe(false);\n });\n\n it('re-populating replaces (does not append to) previous historical state', () => {\n state.LoadHistoricalItems(historicalItems());\n state.LoadHistoricalItems([{ Kind: 'caption', Role: 'User', Text: 'only this' }]);\n expect(state.Items).toHaveLength(1);\n expect(state.Cards).toHaveLength(0);\n });\n\n it('Clear() empties the thread, cards, and narration, and emits Changed$', () => {\n state.LoadHistoricalItems(historicalItems());\n let changes = 0;\n state.Changed$.subscribe(() => changes++);\n state.Clear();\n expect(changes).toBe(1);\n expect(state.Items).toEqual([]);\n expect(state.Cards).toEqual([]);\n expect(state.Narration).toBeNull();\n expect(state.ActiveCallId).toBeNull();\n });\n});\n\ndescribe('MergeChainChannelStates (multi-leg board restore)', () => {\n const wb = (json: string | null) => ({ ChannelName: 'Whiteboard', StateJson: json });\n\n it('an earlier leg\\'s SAVED board survives a final leg that never saved one', () => {\n const merged = MergeChainChannelStates([\n [wb('{\"version\":2,\"pages\":[]}')], // leg 1 drew\n [wb(null)] // leg 2 (newest) never touched the board\n ]);\n expect(merged).toEqual([wb('{\"version\":2,\"pages\":[]}')]);\n });\n\n it('the NEWEST leg with a saved state wins per channel', () => {\n const merged = MergeChainChannelStates([\n [wb('{\"old\":true}')],\n [wb('{\"new\":true}')],\n [wb('')] // newest, empty — registers nothing\n ]);\n expect(merged).toEqual([wb('{\"new\":true}')]);\n });\n\n it('channel names dedupe case-insensitively and other channels merge independently', () => {\n const merged = MergeChainChannelStates([\n [{ ChannelName: 'whiteboard', StateJson: '{\"a\":1}' }, { ChannelName: 'Notes', StateJson: null }],\n [{ ChannelName: 'Whiteboard', StateJson: null }, { ChannelName: 'Notes', StateJson: '{\"n\":1}' }]\n ]);\n expect(merged).toHaveLength(2);\n expect(merged.find(s => s.ChannelName.toLowerCase() === 'whiteboard')?.StateJson).toBe('{\"a\":1}');\n expect(merged.find(s => s.ChannelName === 'Notes')?.StateJson).toBe('{\"n\":1}');\n });\n\n it('channels no leg ever saved keep a null-state entry (existence still reviewable)', () => {\n expect(MergeChainChannelStates([[wb(null)], [wb(null)]])).toEqual([wb(null)]);\n });\n\n it('tolerates empty chains and blank channel names', () => {\n expect(MergeChainChannelStates([])).toEqual([]);\n expect(MergeChainChannelStates([[{ ChannelName: ' ', StateJson: '{\"x\":1}' }]])).toEqual([]);\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-session-state.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-state.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { RealtimeSessionState } from '../lib/components/realtime/realtime-session-state';
|
|
4
|
+
/** Test harness: drives the four session streams the state merges. */
|
|
5
|
+
function buildStreams() {
|
|
6
|
+
const captions$ = new Subject();
|
|
7
|
+
const progress$ = new Subject();
|
|
8
|
+
const result$ = new Subject();
|
|
9
|
+
const narration$ = new Subject();
|
|
10
|
+
const streams = {
|
|
11
|
+
Captions$: captions$.asObservable(),
|
|
12
|
+
DelegationProgress$: progress$.asObservable(),
|
|
13
|
+
DelegationResult$: result$.asObservable(),
|
|
14
|
+
DelegationNarration$: narration$.asObservable()
|
|
15
|
+
};
|
|
16
|
+
return { streams, captions$, progress$, result$, narration$ };
|
|
17
|
+
}
|
|
18
|
+
describe('RealtimeSessionState — RunID threading', () => {
|
|
19
|
+
let harness;
|
|
20
|
+
let state;
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
harness = buildStreams();
|
|
23
|
+
state = new RealtimeSessionState();
|
|
24
|
+
state.Attach(harness.streams);
|
|
25
|
+
});
|
|
26
|
+
it('creates a working card from the first progress event (no RunID yet)', () => {
|
|
27
|
+
harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });
|
|
28
|
+
expect(state.Cards).toHaveLength(1);
|
|
29
|
+
expect(state.Cards[0].Done).toBe(false);
|
|
30
|
+
expect(state.Cards[0].RunID).toBeUndefined();
|
|
31
|
+
expect(state.Cards[0].RunRef).toBeTruthy();
|
|
32
|
+
});
|
|
33
|
+
it('threads the result RunID onto the card and keeps the short RunRef display', () => {
|
|
34
|
+
harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });
|
|
35
|
+
const runRefBefore = state.Cards[0].RunRef;
|
|
36
|
+
harness.result$.next({ CallID: 'call-1', Success: true, Output: 'done!', RunID: 'run-abc' });
|
|
37
|
+
expect(state.Cards).toHaveLength(1);
|
|
38
|
+
const card = state.Cards[0];
|
|
39
|
+
expect(card.Done).toBe(true);
|
|
40
|
+
expect(card.Success).toBe(true);
|
|
41
|
+
expect(card.Result).toBe('done!');
|
|
42
|
+
expect(card.RunID).toBe('run-abc');
|
|
43
|
+
expect(card.RunRef).toBe(runRefBefore);
|
|
44
|
+
});
|
|
45
|
+
it('leaves RunID undefined when the result carries none', () => {
|
|
46
|
+
harness.progress$.next({ CallID: 'call-1', Step: 'action_execution', Message: 'running' });
|
|
47
|
+
harness.result$.next({ CallID: 'call-1', Success: false, Output: 'failed' });
|
|
48
|
+
expect(state.Cards[0].Done).toBe(true);
|
|
49
|
+
expect(state.Cards[0].Success).toBe(false);
|
|
50
|
+
expect(state.Cards[0].RunID).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
it('ignores results for calls that never produced a card (non-delegation tools)', () => {
|
|
53
|
+
harness.result$.next({ CallID: 'unknown', Success: true, Output: 'x', RunID: 'run-1' });
|
|
54
|
+
expect(state.Cards).toHaveLength(0);
|
|
55
|
+
});
|
|
56
|
+
it('threads result Artifacts onto the card', () => {
|
|
57
|
+
harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });
|
|
58
|
+
harness.result$.next({
|
|
59
|
+
CallID: 'call-1',
|
|
60
|
+
Success: true,
|
|
61
|
+
Output: 'done!',
|
|
62
|
+
RunID: 'run-abc',
|
|
63
|
+
Artifacts: [{ ArtifactID: 'a-1', ArtifactVersionID: 'av-1', Name: 'Weather Report' }]
|
|
64
|
+
});
|
|
65
|
+
expect(state.Cards[0].Artifacts).toEqual([
|
|
66
|
+
{ ArtifactID: 'a-1', ArtifactVersionID: 'av-1', Name: 'Weather Report' }
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
it('leaves card Artifacts undefined when the result carries none', () => {
|
|
70
|
+
harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });
|
|
71
|
+
harness.result$.next({ CallID: 'call-1', Success: true, Output: 'done!' });
|
|
72
|
+
expect(state.Cards[0].Artifacts).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
it('replaces the card immutably when the result lands (fresh references for CD)', () => {
|
|
75
|
+
harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });
|
|
76
|
+
const before = state.Cards[0];
|
|
77
|
+
const itemsBefore = state.Items;
|
|
78
|
+
harness.result$.next({ CallID: 'call-1', Success: true, Output: 'done', RunID: 'run-1' });
|
|
79
|
+
expect(state.Cards[0]).not.toBe(before);
|
|
80
|
+
expect(state.Items).not.toBe(itemsBefore);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
//# sourceMappingURL=realtime-session-state.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-session-state.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-session-state.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect, beforeEach } from 'vitest';\nimport { Subject } from 'rxjs';\nimport { RealtimeSessionState, RealtimeSessionStreams } from '../lib/components/realtime/realtime-session-state';\nimport type {\n VoiceCaption,\n VoiceDelegationNarration,\n VoiceDelegationProgress,\n VoiceDelegationResult\n} from '../lib/services/realtime-session.service';\n\n/** Test harness: drives the four session streams the state merges. */\nfunction buildStreams(): {\n streams: RealtimeSessionStreams;\n captions$: Subject<VoiceCaption[]>;\n progress$: Subject<VoiceDelegationProgress>;\n result$: Subject<VoiceDelegationResult>;\n narration$: Subject<VoiceDelegationNarration>;\n} {\n const captions$ = new Subject<VoiceCaption[]>();\n const progress$ = new Subject<VoiceDelegationProgress>();\n const result$ = new Subject<VoiceDelegationResult>();\n const narration$ = new Subject<VoiceDelegationNarration>();\n const streams: RealtimeSessionStreams = {\n Captions$: captions$.asObservable(),\n DelegationProgress$: progress$.asObservable(),\n DelegationResult$: result$.asObservable(),\n DelegationNarration$: narration$.asObservable()\n };\n return { streams, captions$, progress$, result$, narration$ };\n}\n\ndescribe('RealtimeSessionState — RunID threading', () => {\n let harness: ReturnType<typeof buildStreams>;\n let state: RealtimeSessionState;\n\n beforeEach(() => {\n harness = buildStreams();\n state = new RealtimeSessionState();\n state.Attach(harness.streams);\n });\n\n it('creates a working card from the first progress event (no RunID yet)', () => {\n harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });\n expect(state.Cards).toHaveLength(1);\n expect(state.Cards[0].Done).toBe(false);\n expect(state.Cards[0].RunID).toBeUndefined();\n expect(state.Cards[0].RunRef).toBeTruthy();\n });\n\n it('threads the result RunID onto the card and keeps the short RunRef display', () => {\n harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });\n const runRefBefore = state.Cards[0].RunRef;\n\n harness.result$.next({ CallID: 'call-1', Success: true, Output: 'done!', RunID: 'run-abc' });\n\n expect(state.Cards).toHaveLength(1);\n const card = state.Cards[0];\n expect(card.Done).toBe(true);\n expect(card.Success).toBe(true);\n expect(card.Result).toBe('done!');\n expect(card.RunID).toBe('run-abc');\n expect(card.RunRef).toBe(runRefBefore);\n });\n\n it('leaves RunID undefined when the result carries none', () => {\n harness.progress$.next({ CallID: 'call-1', Step: 'action_execution', Message: 'running' });\n harness.result$.next({ CallID: 'call-1', Success: false, Output: 'failed' });\n expect(state.Cards[0].Done).toBe(true);\n expect(state.Cards[0].Success).toBe(false);\n expect(state.Cards[0].RunID).toBeUndefined();\n });\n\n it('ignores results for calls that never produced a card (non-delegation tools)', () => {\n harness.result$.next({ CallID: 'unknown', Success: true, Output: 'x', RunID: 'run-1' });\n expect(state.Cards).toHaveLength(0);\n });\n\n it('threads result Artifacts onto the card', () => {\n harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });\n harness.result$.next({\n CallID: 'call-1',\n Success: true,\n Output: 'done!',\n RunID: 'run-abc',\n Artifacts: [{ ArtifactID: 'a-1', ArtifactVersionID: 'av-1', Name: 'Weather Report' }]\n });\n\n expect(state.Cards[0].Artifacts).toEqual([\n { ArtifactID: 'a-1', ArtifactVersionID: 'av-1', Name: 'Weather Report' }\n ]);\n });\n\n it('leaves card Artifacts undefined when the result carries none', () => {\n harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });\n harness.result$.next({ CallID: 'call-1', Success: true, Output: 'done!' });\n expect(state.Cards[0].Artifacts).toBeUndefined();\n });\n\n it('replaces the card immutably when the result lands (fresh references for CD)', () => {\n harness.progress$.next({ CallID: 'call-1', Step: 'prompt_execution', Message: 'thinking' });\n const before = state.Cards[0];\n const itemsBefore = state.Items;\n\n harness.result$.next({ CallID: 'call-1', Success: true, Output: 'done', RunID: 'run-1' });\n\n expect(state.Cards[0]).not.toBe(before);\n expect(state.Items).not.toBe(itemsBefore);\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-session-timeline-card.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-timeline-card.test.ts"],"names":[],"mappings":"AAEA,OAAO,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Angular components in this package are partial-compiled — load the JIT compiler first
|
|
2
|
+
// (same convention as the whiteboard / delegation-card suites in this node test environment).
|
|
3
|
+
import '@angular/compiler';
|
|
4
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
5
|
+
import { RealtimeSessionTimelineCardComponent } from '../lib/components/realtime/realtime-session-timeline-card.component';
|
|
6
|
+
/**
|
|
7
|
+
* The session timeline card's contract: the title/chip derivations the template renders,
|
|
8
|
+
* and the Open emission the message list bubbles up to host the SESSION REVIEW overlay.
|
|
9
|
+
* Class-level tests (no TestBed), matching the delegation-card suite's style.
|
|
10
|
+
*/
|
|
11
|
+
function group(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
SessionID: 'SESSION-1',
|
|
14
|
+
StartedAt: new Date(2026, 5, 1, 10, 0, 0),
|
|
15
|
+
EndedAt: new Date(2026, 5, 1, 10, 12, 0),
|
|
16
|
+
TurnCount: 7,
|
|
17
|
+
DetailCount: 9,
|
|
18
|
+
LastTurnRole: 'Assistant',
|
|
19
|
+
LastTurnPreview: 'sure, done!',
|
|
20
|
+
...overrides
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function meta(overrides = {}) {
|
|
24
|
+
return {
|
|
25
|
+
SessionID: 'SESSION-1',
|
|
26
|
+
AgentName: 'Voice Co-Agent',
|
|
27
|
+
Status: 'Closed',
|
|
28
|
+
CloseReason: 'Explicit',
|
|
29
|
+
ClosedAt: new Date(2026, 5, 1, 10, 12, 5),
|
|
30
|
+
...overrides
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function card(g = group(), m = null) {
|
|
34
|
+
const component = new RealtimeSessionTimelineCardComponent();
|
|
35
|
+
component.Group = g;
|
|
36
|
+
component.Meta = m;
|
|
37
|
+
return component;
|
|
38
|
+
}
|
|
39
|
+
describe('RealtimeSessionTimelineCardComponent — title', () => {
|
|
40
|
+
it('shows the generic label when no meta is available', () => {
|
|
41
|
+
expect(card().Title).toBe('Realtime session');
|
|
42
|
+
});
|
|
43
|
+
it('appends the agent name when the session meta carries one', () => {
|
|
44
|
+
expect(card(group(), meta()).Title).toBe('Realtime session · Voice Co-Agent');
|
|
45
|
+
});
|
|
46
|
+
it('falls back to the generic label for a blank agent name', () => {
|
|
47
|
+
expect(card(group(), meta({ AgentName: ' ' })).Title).toBe('Realtime session');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('RealtimeSessionTimelineCardComponent — status chip', () => {
|
|
51
|
+
it('hides the chip entirely when no meta is available', () => {
|
|
52
|
+
expect(card().StatusChip).toBeNull();
|
|
53
|
+
});
|
|
54
|
+
it('humanizes the close reason for closed sessions', () => {
|
|
55
|
+
expect(card(group(), meta({ CloseReason: 'Explicit' })).StatusChip).toBe('Ended');
|
|
56
|
+
expect(card(group(), meta({ CloseReason: 'Janitor' })).StatusChip).toBe('Timed out');
|
|
57
|
+
expect(card(group(), meta({ CloseReason: 'Shutdown' })).StatusChip).toBe('Server shutdown');
|
|
58
|
+
expect(card(group(), meta({ CloseReason: 'Error' })).StatusChip).toBe('Error');
|
|
59
|
+
});
|
|
60
|
+
it('falls back to "Closed" for legacy closed rows without a close reason', () => {
|
|
61
|
+
expect(card(group(), meta({ CloseReason: null })).StatusChip).toBe('Closed');
|
|
62
|
+
});
|
|
63
|
+
it('shows Live / Idle for open sessions', () => {
|
|
64
|
+
expect(card(group(), meta({ Status: 'Active', CloseReason: null })).StatusChip).toBe('Live');
|
|
65
|
+
expect(card(group(), meta({ Status: 'Idle', CloseReason: null })).StatusChip).toBe('Idle');
|
|
66
|
+
});
|
|
67
|
+
it('flags the error chip styling only for Error closes', () => {
|
|
68
|
+
expect(card(group(), meta({ CloseReason: 'Error' })).IsErrorChip).toBe(true);
|
|
69
|
+
expect(card(group(), meta({ CloseReason: 'Explicit' })).IsErrorChip).toBe(false);
|
|
70
|
+
expect(card(group(), meta({ Status: 'Active', CloseReason: null })).IsLiveChip).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe('RealtimeSessionTimelineCardComponent — Open emission', () => {
|
|
74
|
+
it('emits OpenRequested with the session id and stops event propagation', () => {
|
|
75
|
+
const component = card(group({ SessionID: 'SESSION-42' }));
|
|
76
|
+
const emitted = [];
|
|
77
|
+
component.OpenRequested.subscribe((id) => emitted.push(id));
|
|
78
|
+
const event = { stopPropagation: vi.fn() };
|
|
79
|
+
component.Open(event);
|
|
80
|
+
expect(emitted).toEqual(['SESSION-42']);
|
|
81
|
+
expect(event.stopPropagation).toHaveBeenCalled();
|
|
82
|
+
});
|
|
83
|
+
it('does not emit when the group has no session id', () => {
|
|
84
|
+
const component = card(group({ SessionID: '' }));
|
|
85
|
+
const emitted = [];
|
|
86
|
+
component.OpenRequested.subscribe((id) => emitted.push(id));
|
|
87
|
+
component.Open();
|
|
88
|
+
expect(emitted).toEqual([]);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('RealtimeSessionTimelineCardComponent — time range formatting hint', () => {
|
|
92
|
+
it('reports a same-day range for start/end on the same calendar day', () => {
|
|
93
|
+
expect(card().SameDayRange).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
it('reports a cross-day range when the session spans midnight', () => {
|
|
96
|
+
const g = group({
|
|
97
|
+
StartedAt: new Date(2026, 5, 1, 23, 50, 0),
|
|
98
|
+
EndedAt: new Date(2026, 5, 2, 0, 10, 0)
|
|
99
|
+
});
|
|
100
|
+
expect(card(g).SameDayRange).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
it('defaults to same-day when either end of the range is unknown', () => {
|
|
103
|
+
expect(card(group({ EndedAt: null })).SameDayRange).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=realtime-session-timeline-card.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-session-timeline-card.test.js","sourceRoot":"","sources":["../../src/__tests__/realtime-session-timeline-card.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Angular components in this package are partial-compiled — load the JIT compiler first\n// (same convention as the whiteboard / delegation-card suites in this node test environment).\nimport '@angular/compiler';\nimport { describe, it, expect, vi } from 'vitest';\nimport { RealtimeSessionTimelineCardComponent } from '../lib/components/realtime/realtime-session-timeline-card.component';\nimport { RealtimeSessionTimelineGroup, RealtimeSessionTimelineMeta } from '../lib/utils/realtime-session-timeline';\n\n/**\n * The session timeline card's contract: the title/chip derivations the template renders,\n * and the Open emission the message list bubbles up to host the SESSION REVIEW overlay.\n * Class-level tests (no TestBed), matching the delegation-card suite's style.\n */\n\nfunction group(overrides: Partial<RealtimeSessionTimelineGroup> = {}): RealtimeSessionTimelineGroup {\n return {\n SessionID: 'SESSION-1',\n StartedAt: new Date(2026, 5, 1, 10, 0, 0),\n EndedAt: new Date(2026, 5, 1, 10, 12, 0),\n TurnCount: 7,\n DetailCount: 9,\n LastTurnRole: 'Assistant',\n LastTurnPreview: 'sure, done!',\n ...overrides\n };\n}\n\nfunction meta(overrides: Partial<RealtimeSessionTimelineMeta> = {}): RealtimeSessionTimelineMeta {\n return {\n SessionID: 'SESSION-1',\n AgentName: 'Voice Co-Agent',\n Status: 'Closed',\n CloseReason: 'Explicit',\n ClosedAt: new Date(2026, 5, 1, 10, 12, 5),\n ...overrides\n };\n}\n\nfunction card(g = group(), m: RealtimeSessionTimelineMeta | null = null): RealtimeSessionTimelineCardComponent {\n const component = new RealtimeSessionTimelineCardComponent();\n component.Group = g;\n component.Meta = m;\n return component;\n}\n\ndescribe('RealtimeSessionTimelineCardComponent — title', () => {\n it('shows the generic label when no meta is available', () => {\n expect(card().Title).toBe('Realtime session');\n });\n\n it('appends the agent name when the session meta carries one', () => {\n expect(card(group(), meta()).Title).toBe('Realtime session · Voice Co-Agent');\n });\n\n it('falls back to the generic label for a blank agent name', () => {\n expect(card(group(), meta({ AgentName: ' ' })).Title).toBe('Realtime session');\n });\n});\n\ndescribe('RealtimeSessionTimelineCardComponent — status chip', () => {\n it('hides the chip entirely when no meta is available', () => {\n expect(card().StatusChip).toBeNull();\n });\n\n it('humanizes the close reason for closed sessions', () => {\n expect(card(group(), meta({ CloseReason: 'Explicit' })).StatusChip).toBe('Ended');\n expect(card(group(), meta({ CloseReason: 'Janitor' })).StatusChip).toBe('Timed out');\n expect(card(group(), meta({ CloseReason: 'Shutdown' })).StatusChip).toBe('Server shutdown');\n expect(card(group(), meta({ CloseReason: 'Error' })).StatusChip).toBe('Error');\n });\n\n it('falls back to \"Closed\" for legacy closed rows without a close reason', () => {\n expect(card(group(), meta({ CloseReason: null })).StatusChip).toBe('Closed');\n });\n\n it('shows Live / Idle for open sessions', () => {\n expect(card(group(), meta({ Status: 'Active', CloseReason: null })).StatusChip).toBe('Live');\n expect(card(group(), meta({ Status: 'Idle', CloseReason: null })).StatusChip).toBe('Idle');\n });\n\n it('flags the error chip styling only for Error closes', () => {\n expect(card(group(), meta({ CloseReason: 'Error' })).IsErrorChip).toBe(true);\n expect(card(group(), meta({ CloseReason: 'Explicit' })).IsErrorChip).toBe(false);\n expect(card(group(), meta({ Status: 'Active', CloseReason: null })).IsLiveChip).toBe(true);\n });\n});\n\ndescribe('RealtimeSessionTimelineCardComponent — Open emission', () => {\n it('emits OpenRequested with the session id and stops event propagation', () => {\n const component = card(group({ SessionID: 'SESSION-42' }));\n const emitted: string[] = [];\n component.OpenRequested.subscribe((id: string) => emitted.push(id));\n\n const event = { stopPropagation: vi.fn() } as unknown as MouseEvent & { stopPropagation: ReturnType<typeof vi.fn> };\n component.Open(event);\n\n expect(emitted).toEqual(['SESSION-42']);\n expect(event.stopPropagation).toHaveBeenCalled();\n });\n\n it('does not emit when the group has no session id', () => {\n const component = card(group({ SessionID: '' }));\n const emitted: string[] = [];\n component.OpenRequested.subscribe((id: string) => emitted.push(id));\n\n component.Open();\n\n expect(emitted).toEqual([]);\n });\n});\n\ndescribe('RealtimeSessionTimelineCardComponent — time range formatting hint', () => {\n it('reports a same-day range for start/end on the same calendar day', () => {\n expect(card().SameDayRange).toBe(true);\n });\n\n it('reports a cross-day range when the session spans midnight', () => {\n const g = group({\n StartedAt: new Date(2026, 5, 1, 23, 50, 0),\n EndedAt: new Date(2026, 5, 2, 0, 10, 0)\n });\n expect(card(g).SameDayRange).toBe(false);\n });\n\n it('defaults to same-day when either end of the range is unknown', () => {\n expect(card(group({ EndedAt: null })).SameDayRange).toBe(true);\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-session-timeline.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/realtime-session-timeline.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { BuildConversationTimeline } from '../lib/utils/realtime-session-timeline';
|
|
3
|
+
/**
|
|
4
|
+
* The PURE grouping pass behind the conversation timeline's realtime SESSION BLOCKS:
|
|
5
|
+
* details stamped with an `AgentSessionID` must NOT render as normal chat bubbles —
|
|
6
|
+
* they collapse into ONE block per session at the session's chronological position,
|
|
7
|
+
* while every unstamped message passes through untouched and in order.
|
|
8
|
+
*/
|
|
9
|
+
let nextId = 0;
|
|
10
|
+
function detail(overrides = {}) {
|
|
11
|
+
nextId++;
|
|
12
|
+
return {
|
|
13
|
+
ID: `D-${nextId}`,
|
|
14
|
+
AgentSessionID: null,
|
|
15
|
+
Role: 'User',
|
|
16
|
+
Message: `message ${nextId}`,
|
|
17
|
+
HiddenToUser: false,
|
|
18
|
+
__mj_CreatedAt: new Date(2026, 5, 1, 10, 0, nextId),
|
|
19
|
+
...overrides
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function kinds(items) {
|
|
23
|
+
return items.map(i => i.Kind);
|
|
24
|
+
}
|
|
25
|
+
describe('BuildConversationTimeline — passthrough of normal messages', () => {
|
|
26
|
+
it('returns an empty timeline for no details', () => {
|
|
27
|
+
expect(BuildConversationTimeline([])).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
it('passes unstamped messages through unchanged, in order, by identity', () => {
|
|
30
|
+
const a = detail();
|
|
31
|
+
const b = detail({ Role: 'AI' });
|
|
32
|
+
const items = BuildConversationTimeline([a, b]);
|
|
33
|
+
expect(kinds(items)).toEqual(['message', 'message']);
|
|
34
|
+
expect(items[0].Kind === 'message' && items[0].Detail).toBe(a);
|
|
35
|
+
expect(items[1].Kind === 'message' && items[1].Detail).toBe(b);
|
|
36
|
+
});
|
|
37
|
+
it('treats empty/whitespace AgentSessionID stamps as unstamped', () => {
|
|
38
|
+
const items = BuildConversationTimeline([
|
|
39
|
+
detail({ AgentSessionID: '' }),
|
|
40
|
+
detail({ AgentSessionID: ' ' })
|
|
41
|
+
]);
|
|
42
|
+
expect(kinds(items)).toEqual(['message', 'message']);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe('BuildConversationTimeline — session collapse', () => {
|
|
46
|
+
it('collapses consecutive same-session details into ONE block at their chronological position', () => {
|
|
47
|
+
const before = detail();
|
|
48
|
+
const turn1 = detail({ AgentSessionID: 'S-1', Role: 'User', Message: 'hello there' });
|
|
49
|
+
const turn2 = detail({ AgentSessionID: 'S-1', Role: 'AI', Message: 'hi! how can I help?' });
|
|
50
|
+
const after = detail();
|
|
51
|
+
const items = BuildConversationTimeline([before, turn1, turn2, after]);
|
|
52
|
+
expect(kinds(items)).toEqual(['message', 'session', 'message']);
|
|
53
|
+
const block = items[1];
|
|
54
|
+
if (block.Kind !== 'session')
|
|
55
|
+
throw new Error('expected a session block');
|
|
56
|
+
expect(block.Group.SessionID).toBe('S-1');
|
|
57
|
+
expect(block.Group.TurnCount).toBe(2);
|
|
58
|
+
expect(block.Group.DetailCount).toBe(2);
|
|
59
|
+
expect(block.Group.StartedAt).toEqual(turn1.__mj_CreatedAt);
|
|
60
|
+
expect(block.Group.EndedAt).toEqual(turn2.__mj_CreatedAt);
|
|
61
|
+
expect(block.Group.LastTurnRole).toBe('Assistant'); // AI maps to Assistant
|
|
62
|
+
expect(block.Group.LastTurnPreview).toBe('hi! how can I help?');
|
|
63
|
+
});
|
|
64
|
+
it('renders ONE element per session even when its rows are interleaved with normal messages', () => {
|
|
65
|
+
const items = BuildConversationTimeline([
|
|
66
|
+
detail({ AgentSessionID: 'S-1', Message: 'first leg turn' }),
|
|
67
|
+
detail({ Message: 'normal note in between' }),
|
|
68
|
+
detail({ AgentSessionID: 'S-1', Role: 'AI', Message: 'late session turn' })
|
|
69
|
+
]);
|
|
70
|
+
expect(kinds(items)).toEqual(['session', 'message']);
|
|
71
|
+
const block = items[0];
|
|
72
|
+
if (block.Kind !== 'session')
|
|
73
|
+
throw new Error('expected a session block');
|
|
74
|
+
expect(block.Group.TurnCount).toBe(2);
|
|
75
|
+
expect(block.Group.LastTurnPreview).toBe('late session turn');
|
|
76
|
+
});
|
|
77
|
+
it('produces separate blocks for DIFFERENT sessions, each at its own position', () => {
|
|
78
|
+
const items = BuildConversationTimeline([
|
|
79
|
+
detail({ AgentSessionID: 'S-1' }),
|
|
80
|
+
detail(),
|
|
81
|
+
detail({ AgentSessionID: 'S-2' })
|
|
82
|
+
]);
|
|
83
|
+
expect(kinds(items)).toEqual(['session', 'message', 'session']);
|
|
84
|
+
const first = items[0];
|
|
85
|
+
const second = items[2];
|
|
86
|
+
if (first.Kind !== 'session' || second.Kind !== 'session')
|
|
87
|
+
throw new Error('expected session blocks');
|
|
88
|
+
expect(first.Group.SessionID).toBe('S-1');
|
|
89
|
+
expect(second.Group.SessionID).toBe('S-2');
|
|
90
|
+
});
|
|
91
|
+
it('groups session ids case-insensitively (SQL Server uppercase vs PostgreSQL lowercase)', () => {
|
|
92
|
+
const items = BuildConversationTimeline([
|
|
93
|
+
detail({ AgentSessionID: 'ABC-DEF' }),
|
|
94
|
+
detail({ AgentSessionID: 'abc-def' })
|
|
95
|
+
]);
|
|
96
|
+
expect(kinds(items)).toEqual(['session']);
|
|
97
|
+
const block = items[0];
|
|
98
|
+
if (block.Kind !== 'session')
|
|
99
|
+
throw new Error('expected a session block');
|
|
100
|
+
expect(block.Group.DetailCount).toBe(2);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe('BuildConversationTimeline — turn counting mirrors review-mode visibility', () => {
|
|
104
|
+
it('folds hidden rows (junction anchors) into the block WITHOUT counting them as turns', () => {
|
|
105
|
+
const items = BuildConversationTimeline([
|
|
106
|
+
detail({ AgentSessionID: 'S-1', Role: 'User', Message: 'spoken turn' }),
|
|
107
|
+
detail({ AgentSessionID: 'S-1', Role: 'AI', Message: 'artifact anchor', HiddenToUser: true })
|
|
108
|
+
]);
|
|
109
|
+
const block = items[0];
|
|
110
|
+
if (block.Kind !== 'session')
|
|
111
|
+
throw new Error('expected a session block');
|
|
112
|
+
expect(block.Group.DetailCount).toBe(2);
|
|
113
|
+
expect(block.Group.TurnCount).toBe(1);
|
|
114
|
+
expect(block.Group.LastTurnPreview).toBe('spoken turn'); // hidden row never becomes the preview
|
|
115
|
+
});
|
|
116
|
+
it('excludes empty-text and Error-role rows from the turn count', () => {
|
|
117
|
+
const items = BuildConversationTimeline([
|
|
118
|
+
detail({ AgentSessionID: 'S-1', Message: ' ' }),
|
|
119
|
+
detail({ AgentSessionID: 'S-1', Role: 'Error', Message: 'boom' }),
|
|
120
|
+
detail({ AgentSessionID: 'S-1', Role: 'AI', Message: 'real turn' })
|
|
121
|
+
]);
|
|
122
|
+
const block = items[0];
|
|
123
|
+
if (block.Kind !== 'session')
|
|
124
|
+
throw new Error('expected a session block');
|
|
125
|
+
expect(block.Group.DetailCount).toBe(3);
|
|
126
|
+
expect(block.Group.TurnCount).toBe(1);
|
|
127
|
+
expect(block.Group.LastTurnRole).toBe('Assistant');
|
|
128
|
+
});
|
|
129
|
+
it('tolerates string timestamps and missing timestamps when computing the range', () => {
|
|
130
|
+
const items = BuildConversationTimeline([
|
|
131
|
+
detail({ AgentSessionID: 'S-1', __mj_CreatedAt: '2026-06-01T10:00:00Z' }),
|
|
132
|
+
detail({ AgentSessionID: 'S-1', __mj_CreatedAt: null }),
|
|
133
|
+
detail({ AgentSessionID: 'S-1', __mj_CreatedAt: '2026-06-01T10:05:00Z' })
|
|
134
|
+
]);
|
|
135
|
+
const block = items[0];
|
|
136
|
+
if (block.Kind !== 'session')
|
|
137
|
+
throw new Error('expected a session block');
|
|
138
|
+
expect(block.Group.StartedAt?.toISOString()).toBe('2026-06-01T10:00:00.000Z');
|
|
139
|
+
expect(block.Group.EndedAt?.toISOString()).toBe('2026-06-01T10:05:00.000Z');
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
//# sourceMappingURL=realtime-session-timeline.test.js.map
|