@memberjunction/ng-conversations 6.1.3 → 6.2.0-edge.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.
Files changed (113) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  3. package/dist/lib/components/conversation/conversation-chat-area.component.js +9 -26
  4. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  5. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts +1 -1
  6. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts.map +1 -1
  7. package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js.map +1 -1
  8. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +1 -1
  9. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
  10. package/dist/lib/components/realtime/channels/client-context-channel.js +1 -1
  11. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
  12. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +1 -1
  13. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
  14. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +3 -0
  15. package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
  16. package/dist/lib/components/realtime/media/media-channel.d.ts +2 -1
  17. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
  18. package/dist/lib/components/realtime/media/media-channel.js +1 -1
  19. package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
  20. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +1 -1
  21. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
  22. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
  23. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +1 -1
  24. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  25. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  26. package/dist/lib/components/realtime/realtime-composer.component.d.ts +3 -1
  27. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  28. package/dist/lib/components/realtime/realtime-composer.component.js +26 -8
  29. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  30. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +1 -1
  31. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
  32. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
  33. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +2 -2
  34. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  35. package/dist/lib/components/realtime/realtime-session-overlay.component.js +1 -1
  36. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  37. package/dist/lib/components/realtime/realtime-session-state.d.ts +2 -3
  38. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
  39. package/dist/lib/components/realtime/realtime-session-state.js +3 -2
  40. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
  41. package/dist/lib/components/realtime/realtime-session-thread.component.d.ts +17 -1
  42. package/dist/lib/components/realtime/realtime-session-thread.component.d.ts.map +1 -1
  43. package/dist/lib/components/realtime/realtime-session-thread.component.js +122 -45
  44. package/dist/lib/components/realtime/realtime-session-thread.component.js.map +1 -1
  45. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +1 -9
  46. package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -1
  47. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +13 -43
  48. package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -1
  49. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +2 -2
  50. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  51. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  52. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +1 -1
  53. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  54. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  55. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +1 -1
  56. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  57. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +1 -1
  58. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  59. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +1 -1
  60. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
  61. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +1 -1
  62. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
  63. package/dist/lib/conversations.module.d.ts.map +1 -1
  64. package/dist/lib/conversations.module.js.map +1 -1
  65. package/dist/lib/services/browser-realtime-media-host.d.ts +24 -0
  66. package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -0
  67. package/dist/lib/services/browser-realtime-media-host.js +95 -0
  68. package/dist/lib/services/browser-realtime-media-host.js.map +1 -0
  69. package/dist/lib/services/conversation-attachment.service.d.ts +24 -2
  70. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  71. package/dist/lib/services/conversation-attachment.service.js +43 -4
  72. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  73. package/dist/lib/services/graphql-attachment-blob-store.d.ts +44 -0
  74. package/dist/lib/services/graphql-attachment-blob-store.d.ts.map +1 -0
  75. package/dist/lib/services/graphql-attachment-blob-store.js +113 -0
  76. package/dist/lib/services/graphql-attachment-blob-store.js.map +1 -0
  77. package/dist/lib/services/mention-autocomplete.service.d.ts +17 -141
  78. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  79. package/dist/lib/services/mention-autocomplete.service.js +15 -460
  80. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  81. package/dist/lib/services/realtime-session-review.service.d.ts +1 -1
  82. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
  83. package/dist/lib/services/realtime-session-review.service.js +1 -1
  84. package/dist/lib/services/realtime-session-review.service.js.map +1 -1
  85. package/dist/lib/services/realtime-session.service.d.ts +16 -1150
  86. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  87. package/dist/lib/services/realtime-session.service.js +28 -2430
  88. package/dist/lib/services/realtime-session.service.js.map +1 -1
  89. package/dist/lib/utils/realtime-session-timeline.d.ts +8 -79
  90. package/dist/lib/utils/realtime-session-timeline.d.ts.map +1 -1
  91. package/dist/lib/utils/realtime-session-timeline.js +8 -89
  92. package/dist/lib/utils/realtime-session-timeline.js.map +1 -1
  93. package/dist/public-api.d.ts +2 -2
  94. package/dist/public-api.d.ts.map +1 -1
  95. package/dist/public-api.js +6 -2
  96. package/dist/public-api.js.map +1 -1
  97. package/package.json +33 -32
  98. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +0 -384
  99. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +0 -1
  100. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +0 -231
  101. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +0 -1
  102. package/dist/lib/services/delegation-result-parser.d.ts +0 -50
  103. package/dist/lib/services/delegation-result-parser.d.ts.map +0 -1
  104. package/dist/lib/services/delegation-result-parser.js +0 -60
  105. package/dist/lib/services/delegation-result-parser.js.map +0 -1
  106. package/dist/lib/services/narration-template.d.ts +0 -42
  107. package/dist/lib/services/narration-template.d.ts.map +0 -1
  108. package/dist/lib/services/narration-template.js +0 -73
  109. package/dist/lib/services/narration-template.js.map +0 -1
  110. package/dist/lib/services/skill-picker-narrowing.d.ts +0 -13
  111. package/dist/lib/services/skill-picker-narrowing.d.ts.map +0 -1
  112. package/dist/lib/services/skill-picker-narrowing.js +0 -13
  113. package/dist/lib/services/skill-picker-narrowing.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from '@angular/core';
2
- import { ChannelOnboardingDetails } from './base-realtime-channel-client';
2
+ import { ChannelOnboardingDetails } from '@memberjunction/realtime-runtime';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
5
5
  * The FIRST-RUN INTRO overlay for an interactive channel — a generic, channel-agnostic card
@@ -1 +1 @@
1
- {"version":3,"file":"channel-onboarding-panel.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/channel-onboarding-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;AAEvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;;AAE1E;;;;;;;;;;;;GAYG;AACH,qBAgJa,+BAA+B;IAC1C,iEAAiE;IACxD,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IAEzD,gFAAgF;IACtE,SAAS,qBAA4B;yCALpC,+BAA+B;2CAA/B,+BAA+B;CAM3C"}
1
+ {"version":3,"file":"channel-onboarding-panel.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/channel-onboarding-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;AAEvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;;AAE5E;;;;;;;;;;;;GAYG;AACH,qBAgJa,+BAA+B;IAC1C,iEAAiE;IACxD,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IAEzD,gFAAgF;IACtE,SAAS,qBAA4B;yCALpC,+BAA+B;2CAA/B,+BAA+B;CAM3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"channel-onboarding-panel.component.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/channel-onboarding-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;;;IAiCzD,8BAAiD;IAC/C,oBAAmC;IACrC,iBAAM;;;IADD,cAA2B;IAA3B,mCAA2B;;;IAU5B,8BAA4B;IAC1B,wBAAoD;IACpD,4BAAM;IAAA,YAAS;IACjB,AADiB,iBAAO,EACnB;;;IADG,eAAS;IAAT,4BAAS;;;IAJrB,6BAA6B;IAC3B,gJAKC;IACH,iBAAK;;;IANH,cAKC;IALD,8BAKC;;;;IAxBL,AADF,AADF,8BAA6F,aAC7D,gBAKC;IAFrB,mMAAS,uBAAgB,KAAC;IAGhC,uBAAoD;IACtD,iBAAS;IAET,+GAAyB;IAMzB,6BAAgC;IAAA,YAAqB;IAAA,iBAAK;IAC1D,4BAAmC;IAAA,YAAyB;IAAA,iBAAI;IAEhE,8GAA4B;IAY1B,AADF,+BAAiC,iBACiD;IAA3B,oMAAS,uBAAgB,KAAC;IAC7E,yBACF;IAGN,AADE,AADE,AADE,iBAAS,EACL,EACF,EACF;;;;IA1BF,eAIC;IAJD,+CAIC;IAE+B,eAAqB;IAArB,wCAAqB;IAClB,eAAyB;IAAzB,4CAAyB;IAE5D,cASC;IATD,oFASC;IAGkB,eAAqB;IAArB,mCAAqB;;AAlDlD;;;;;;;;;;;;GAYG;AAiJH,MAAM,OAAO,+BAA+B;IAC1C,iEAAiE;IACxD,OAAO,GAAoC,IAAI,CAAC;IAEzD,gFAAgF;IACtE,SAAS,GAAG,IAAI,YAAY,EAAQ,CAAC;yHALpC,+BAA+B;6DAA/B,+BAA+B;YA3IxC,kGAA2B;;;YAA3B,2DAsCC;4BAxCO,iBAAiB;;iFA6IhB,+BAA+B;cAhJ3C,SAAS;6BACI,IAAI,YACN,6BAA6B,WAC9B,CAAC,iBAAiB,CAAC,YAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCT;;kBAsGA,KAAK;;kBAGL,MAAM;;kFALI,+BAA+B","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { ChannelOnboardingDetails } from './base-realtime-channel-client';\n\n/**\n * The FIRST-RUN INTRO overlay for an interactive channel — a generic, channel-agnostic card\n * the surface panel floats over a channel's pane the very first time a user opens that channel\n * (whiteboard, remote browser, …). It renders whatever {@link ChannelOnboardingDetails} the\n * channel plugin supplied (icon · heading · description · optional tips) and a single \"Got it\"\n * action plus a small ✕ — both emit {@link Dismissed}, which the host uses to mark the channel\n * seen (per user, via the user's settings) and hide the panel.\n *\n * This component owns NO persistence or channel knowledge: it's a pure presenter wired by\n * `RealtimeSurfaceTabsComponent`, so it stays reusable for any current or future channel. When\n * {@link Content} is `null` it renders nothing (the host already gates on that, but the guard\n * keeps the component safe to drop in unconditionally).\n */\n@Component({\n standalone: true,\n selector: 'mj-channel-onboarding-panel',\n imports: [MJButtonDirective],\n template: `\n @if (Content; as content) {\n <div class=\"onboarding\" role=\"dialog\" aria-modal=\"false\" [attr.aria-label]=\"content.Heading\">\n <div class=\"onboarding__card\">\n <button type=\"button\"\n class=\"onboarding__close\"\n (click)=\"Dismissed.emit()\"\n title=\"Dismiss\"\n aria-label=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n\n @if (content.IconClass) {\n <div class=\"onboarding__icon\" aria-hidden=\"true\">\n <i [class]=\"content.IconClass\"></i>\n </div>\n }\n\n <h3 class=\"onboarding__heading\">{{ content.Heading }}</h3>\n <p class=\"onboarding__description\">{{ content.Description }}</p>\n\n @if (content.Tips?.length) {\n <ul class=\"onboarding__tips\">\n @for (tip of content.Tips; track tip) {\n <li class=\"onboarding__tip\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span>{{ tip }}</span>\n </li>\n }\n </ul>\n }\n\n <div class=\"onboarding__actions\">\n <button mjButton [variant]=\"'primary'\" type=\"button\" (click)=\"Dismissed.emit()\">\n Got it\n </button>\n </div>\n </div>\n </div>\n }\n `,\n styles: [`\n :host {\n position: absolute;\n inset: 0;\n display: block;\n z-index: 5;\n }\n .onboarding {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n /* Translucent backdrop over the channel pane — token-derived, no hardcoded colors. */\n background: color-mix(in srgb, var(--mj-bg-overlay) 55%, transparent);\n }\n .onboarding__card {\n position: relative;\n width: 100%;\n max-width: 24rem;\n padding: 1.75rem 1.5rem 1.5rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 12px);\n background: var(--mj-bg-surface);\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-bg-overlay) 35%, transparent);\n text-align: center;\n }\n .onboarding__close {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.75rem;\n height: 1.75rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--mj-radius-full, 999px);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease;\n }\n .onboarding__close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n .onboarding__icon {\n width: 3rem;\n height: 3rem;\n margin: 0 auto 0.75rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 1.35rem;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface-card));\n }\n .onboarding__heading {\n margin: 0 0 0.4rem;\n font-size: 1.15rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .onboarding__description {\n margin: 0;\n font-size: 0.9rem;\n line-height: 1.45;\n color: var(--mj-text-secondary);\n }\n .onboarding__tips {\n margin: 1rem 0 0;\n padding: 0;\n list-style: none;\n text-align: left;\n }\n .onboarding__tip {\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n padding: 0.3rem 0;\n font-size: 0.85rem;\n line-height: 1.4;\n color: var(--mj-text-secondary);\n }\n .onboarding__tip i {\n margin-top: 0.18rem;\n font-size: 0.75rem;\n color: var(--mj-brand-primary);\n }\n .onboarding__actions {\n margin-top: 1.25rem;\n display: flex;\n justify-content: center;\n }\n `]\n})\nexport class ChannelOnboardingPanelComponent {\n /** The intro content to present, or `null` to render nothing. */\n @Input() Content: ChannelOnboardingDetails | null = null;\n\n /** Emitted when the user dismisses the intro (the \"Got it\" button or the ✕). */\n @Output() Dismissed = new EventEmitter<void>();\n}\n"]}
1
+ {"version":3,"file":"channel-onboarding-panel.component.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/channel-onboarding-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;;;IAiCzD,8BAAiD;IAC/C,oBAAmC;IACrC,iBAAM;;;IADD,cAA2B;IAA3B,mCAA2B;;;IAU5B,8BAA4B;IAC1B,wBAAoD;IACpD,4BAAM;IAAA,YAAS;IACjB,AADiB,iBAAO,EACnB;;;IADG,eAAS;IAAT,4BAAS;;;IAJrB,6BAA6B;IAC3B,gJAKC;IACH,iBAAK;;;IANH,cAKC;IALD,8BAKC;;;;IAxBL,AADF,AADF,8BAA6F,aAC7D,gBAKC;IAFrB,mMAAS,uBAAgB,KAAC;IAGhC,uBAAoD;IACtD,iBAAS;IAET,+GAAyB;IAMzB,6BAAgC;IAAA,YAAqB;IAAA,iBAAK;IAC1D,4BAAmC;IAAA,YAAyB;IAAA,iBAAI;IAEhE,8GAA4B;IAY1B,AADF,+BAAiC,iBACiD;IAA3B,oMAAS,uBAAgB,KAAC;IAC7E,yBACF;IAGN,AADE,AADE,AADE,iBAAS,EACL,EACF,EACF;;;;IA1BF,eAIC;IAJD,+CAIC;IAE+B,eAAqB;IAArB,wCAAqB;IAClB,eAAyB;IAAzB,4CAAyB;IAE5D,cASC;IATD,oFASC;IAGkB,eAAqB;IAArB,mCAAqB;;AAlDlD;;;;;;;;;;;;GAYG;AAiJH,MAAM,OAAO,+BAA+B;IAC1C,iEAAiE;IACxD,OAAO,GAAoC,IAAI,CAAC;IAEzD,gFAAgF;IACtE,SAAS,GAAG,IAAI,YAAY,EAAQ,CAAC;yHALpC,+BAA+B;6DAA/B,+BAA+B;YA3IxC,kGAA2B;;;YAA3B,2DAsCC;4BAxCO,iBAAiB;;iFA6IhB,+BAA+B;cAhJ3C,SAAS;6BACI,IAAI,YACN,6BAA6B,WAC9B,CAAC,iBAAiB,CAAC,YAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCT;;kBAsGA,KAAK;;kBAGL,MAAM;;kFALI,+BAA+B","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { ChannelOnboardingDetails } from '@memberjunction/realtime-runtime';\n\n/**\n * The FIRST-RUN INTRO overlay for an interactive channel — a generic, channel-agnostic card\n * the surface panel floats over a channel's pane the very first time a user opens that channel\n * (whiteboard, remote browser, …). It renders whatever {@link ChannelOnboardingDetails} the\n * channel plugin supplied (icon · heading · description · optional tips) and a single \"Got it\"\n * action plus a small ✕ — both emit {@link Dismissed}, which the host uses to mark the channel\n * seen (per user, via the user's settings) and hide the panel.\n *\n * This component owns NO persistence or channel knowledge: it's a pure presenter wired by\n * `RealtimeSurfaceTabsComponent`, so it stays reusable for any current or future channel. When\n * {@link Content} is `null` it renders nothing (the host already gates on that, but the guard\n * keeps the component safe to drop in unconditionally).\n */\n@Component({\n standalone: true,\n selector: 'mj-channel-onboarding-panel',\n imports: [MJButtonDirective],\n template: `\n @if (Content; as content) {\n <div class=\"onboarding\" role=\"dialog\" aria-modal=\"false\" [attr.aria-label]=\"content.Heading\">\n <div class=\"onboarding__card\">\n <button type=\"button\"\n class=\"onboarding__close\"\n (click)=\"Dismissed.emit()\"\n title=\"Dismiss\"\n aria-label=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n\n @if (content.IconClass) {\n <div class=\"onboarding__icon\" aria-hidden=\"true\">\n <i [class]=\"content.IconClass\"></i>\n </div>\n }\n\n <h3 class=\"onboarding__heading\">{{ content.Heading }}</h3>\n <p class=\"onboarding__description\">{{ content.Description }}</p>\n\n @if (content.Tips?.length) {\n <ul class=\"onboarding__tips\">\n @for (tip of content.Tips; track tip) {\n <li class=\"onboarding__tip\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span>{{ tip }}</span>\n </li>\n }\n </ul>\n }\n\n <div class=\"onboarding__actions\">\n <button mjButton [variant]=\"'primary'\" type=\"button\" (click)=\"Dismissed.emit()\">\n Got it\n </button>\n </div>\n </div>\n </div>\n }\n `,\n styles: [`\n :host {\n position: absolute;\n inset: 0;\n display: block;\n z-index: 5;\n }\n .onboarding {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n /* Translucent backdrop over the channel pane — token-derived, no hardcoded colors. */\n background: color-mix(in srgb, var(--mj-bg-overlay) 55%, transparent);\n }\n .onboarding__card {\n position: relative;\n width: 100%;\n max-width: 24rem;\n padding: 1.75rem 1.5rem 1.5rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 12px);\n background: var(--mj-bg-surface);\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-bg-overlay) 35%, transparent);\n text-align: center;\n }\n .onboarding__close {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.75rem;\n height: 1.75rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--mj-radius-full, 999px);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease;\n }\n .onboarding__close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n .onboarding__icon {\n width: 3rem;\n height: 3rem;\n margin: 0 auto 0.75rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 1.35rem;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface-card));\n }\n .onboarding__heading {\n margin: 0 0 0.4rem;\n font-size: 1.15rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .onboarding__description {\n margin: 0;\n font-size: 0.9rem;\n line-height: 1.45;\n color: var(--mj-text-secondary);\n }\n .onboarding__tips {\n margin: 1rem 0 0;\n padding: 0;\n list-style: none;\n text-align: left;\n }\n .onboarding__tip {\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n padding: 0.3rem 0;\n font-size: 0.85rem;\n line-height: 1.4;\n color: var(--mj-text-secondary);\n }\n .onboarding__tip i {\n margin-top: 0.18rem;\n font-size: 0.75rem;\n color: var(--mj-brand-primary);\n }\n .onboarding__actions {\n margin-top: 1.25rem;\n display: flex;\n justify-content: center;\n }\n `]\n})\nexport class ChannelOnboardingPanelComponent {\n /** The intro content to present, or `null` to render nothing. */\n @Input() Content: ChannelOnboardingDetails | null = null;\n\n /** Emitted when the user dismisses the intro (the \"Got it\" button or the ✕). */\n @Output() Dismissed = new EventEmitter<void>();\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { RealtimeToolDefinition } from '@memberjunction/ai';
2
- import { BaseRealtimeChannelClient } from './base-realtime-channel-client';
2
+ import { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';
3
3
  /** The stable name of the single proxy tool this channel registers with the realtime provider. */
4
4
  export declare const CONTEXT_TOOL_NAME = "ContextTool";
5
5
  /**
@@ -1 +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"}
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,kCAAkC,CAAC;AAE7E,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"}
@@ -36,7 +36,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
36
36
  import { RegisterClass } from '@memberjunction/global';
37
37
  import { FormatAppContextNote } from '@memberjunction/ai-core-plus';
38
38
  import { distinctUntilChanged } from 'rxjs/operators';
39
- import { BaseRealtimeChannelClient } from './base-realtime-channel-client';
39
+ import { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';
40
40
  /** The stable name of the single proxy tool this channel registers with the realtime provider. */
41
41
  export const CONTEXT_TOOL_NAME = 'ContextTool';
42
42
  /** The single stable proxy tool — declared once; the live catalog of valid `action`s rides context. */
@@ -1 +1 @@
1
- {"version":3,"file":"client-context-channel.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/client-context-channel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview The headless **Client Context** channel — the browser half of the live wire that\n * keeps the realtime co-agent continuously aware of the user's app context and lets it act in the\n * app through a single stable proxy tool.\n *\n * Paired with `ClientContextChannelServer` (`@memberjunction/ai-agents`) via the seeded\n * `MJ: AI Agent Channels` row (`Name: 'ClientContextChannel'`, `IsHeadless: 1`,\n * `ClientPluginClass: 'ClientContextChannel'`).\n *\n * Two responsibilities, both client-side (no server round-trip in the client-direct topology):\n *\n * 1. **Perception (streaming).** It subscribes to the host's live app-context stream\n * ({@link RealtimeChannelContext.AppContext$}, fed by Explorer from `NavigationService`) and, on\n * every change, pushes a compact `SendContextNote` so the model always knows where the user is,\n * what they see, and which tools/agents are available — the *continuous* half of client-context\n * delivery (the session-start half is injected into the companion prompt server-side at mint).\n *\n * 2. **Action (the `ContextTool` proxy).** It declares ONE stable tool, `ContextTool`, so the\n * provider tool surface never changes mid-session (which connect-bound providers reject). The\n * model invokes any currently-available surface client tool via `ContextTool({ action, params })`;\n * the channel routes that to the host's {@link RealtimeChannelContext.ExecuteClientTool} (which runs\n * the surface handler the host registered from `SetAgentClientTools`) and returns a structured\n * result the model narrates.\n *\n * **Headless:** no surface component — it never mounts a tab (`GetSurfaceComponent` stays `null`;\n * `BindSurface` is a no-op). It is a wire, not a panel.\n *\n * @module @memberjunction/ng-conversations\n */\nimport { RegisterClass } from '@memberjunction/global';\nimport { RealtimeToolDefinition } from '@memberjunction/ai';\nimport { FormatAppContextNote } from '@memberjunction/ai-core-plus';\nimport { Subscription } from 'rxjs';\nimport { distinctUntilChanged } from 'rxjs/operators';\nimport { BaseRealtimeChannelClient } from './base-realtime-channel-client';\n\n/** The stable name of the single proxy tool this channel registers with the realtime provider. */\nexport const CONTEXT_TOOL_NAME = 'ContextTool';\n\n/** The single stable proxy tool — declared once; the live catalog of valid `action`s rides context. */\nconst CONTEXT_TOOL_DEFINITION: RealtimeToolDefinition = {\n Name: CONTEXT_TOOL_NAME,\n Description:\n \"Perform an action in the application the user is currently in. The set of valid actions (the \" +\n \"client tools and the things you can do on the current surface) is provided to you continuously \" +\n \"as context — only call actions listed as currently available. Pass the action name and its \" +\n \"parameters.\",\n ParametersSchema: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n description: 'The name of a currently-available action/tool to run (from the context you were given).'\n },\n params: {\n type: 'object',\n description: \"The action's parameters, matching its advertised input schema.\"\n }\n },\n required: ['action']\n }\n};\n\n/**\n * The headless Client Context channel client. One instance per realtime session (created by the\n * session service from the `MJ: AI Agent Channels` registry — never construct directly).\n */\n@RegisterClass(BaseRealtimeChannelClient, 'ClientContextChannel')\nexport class ClientContextChannel extends BaseRealtimeChannelClient<object> {\n /** Subscription to the host app-context stream (perception); cleared on {@link Dispose}. */\n private appContextSub: Subscription | null = null;\n\n /** Matches the seeded `MJ: AI Agent Channels` row's `Name`. */\n public get ChannelName(): string {\n return 'ClientContextChannel';\n }\n\n /** Routing prefix — the single `ContextTool` matches `ContextTool`.startsWith(prefix). */\n public get ToolNamePrefix(): string {\n return CONTEXT_TOOL_NAME;\n }\n\n /** Headless — never rendered, but the abstract contract requires a label/icon. */\n public get TabTitle(): string {\n return 'App Context';\n }\n public get TabIcon(): string {\n return 'fa-solid fa-satellite-dish';\n }\n\n /** Declares the single stable proxy tool. */\n public GetToolDefinitions(): RealtimeToolDefinition[] {\n return [CONTEXT_TOOL_DEFINITION];\n }\n\n /**\n * Routes a `ContextTool({ action, params })` call to the host's registered surface client tool.\n * Tolerant: malformed args, a missing host executor, or an unknown/throwing tool all serialize to\n * a structured `{ success: false, output }` the model narrates (never throws).\n */\n public async ApplyAgentTool(toolName: string, argsJson: string): Promise<string> {\n if (toolName !== CONTEXT_TOOL_NAME) {\n return JSON.stringify({ success: false, output: `Unknown context tool \"${toolName}\".` });\n }\n const parsed = this.parseArgs(argsJson);\n if (!parsed.action) {\n return JSON.stringify({ success: false, output: 'ContextTool requires an \"action\" naming the tool to run.' });\n }\n const executor = this.Context?.ExecuteClientTool;\n if (!executor) {\n return JSON.stringify({\n success: false,\n output: 'No app surface is available to perform that action right now.'\n });\n }\n const result = await executor(parsed.action, parsed.params);\n return result.Success\n ? JSON.stringify({ success: true, output: result.Result ?? 'Done.' })\n : JSON.stringify({ success: false, output: result.ErrorMessage ?? 'The action could not be performed.' });\n }\n\n /** Headless — no surface to bind. */\n public BindSurface(): void {\n /* no-op: this channel renders no surface */\n }\n\n /**\n * Subscribes to the host's live app-context stream and streams each change to the model as a\n * compact context note (the perception half). Null-safe — hosts that supply no `AppContext$`\n * (custom apps) simply get no streaming, and the session-start prompt injection still applies.\n */\n protected override OnInitialize(): void {\n const stream = this.Context?.AppContext$;\n if (!stream) {\n return;\n }\n this.appContextSub = stream\n .pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))\n .subscribe((snapshot) => {\n if (!snapshot) {\n return;\n }\n const note = FormatAppContextNote(snapshot);\n if (note) {\n this.Context?.SendContextNote(note);\n }\n });\n }\n\n /** Tolerantly parses the `{ action, params }` arguments. */\n private parseArgs(argsJson: string): { action: string | null; params: Record<string, unknown> } {\n try {\n const parsed = JSON.parse(argsJson) as { action?: unknown; params?: unknown };\n const action = typeof parsed.action === 'string' && parsed.action.trim().length > 0 ? parsed.action.trim() : null;\n const params =\n parsed.params && typeof parsed.params === 'object' && !Array.isArray(parsed.params)\n ? (parsed.params as Record<string, unknown>)\n : {};\n return { action, params };\n } catch {\n return { action: null, params: {} };\n }\n }\n\n /** Unsubscribes the app-context stream and tears down. */\n public override Dispose(): void {\n this.appContextSub?.unsubscribe();\n this.appContextSub = null;\n super.Dispose();\n }\n}\n\n/**\n * Tree-shaking prevention for {@link ClientContextChannel}'s `@RegisterClass` registration. Called\n * from a static code path in `conversations.module.ts` so the registration always executes —\n * mirroring every other realtime channel client.\n */\nexport function LoadClientContextChannel(): void {\n // no-op — the import + call create a static reference bundlers cannot eliminate\n}\n"]}
1
+ {"version":3,"file":"client-context-channel.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/client-context-channel.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAE7E,kGAAkG;AAClG,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C,uGAAuG;AACvG,MAAM,uBAAuB,GAA2B;IACtD,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,+FAA+F;QAC/F,iGAAiG;QACjG,6FAA6F;QAC7F,aAAa;IACf,gBAAgB,EAAE;QAChB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,yFAAyF;aACvG;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gEAAgE;aAC9E;SACF;QACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB;CACF,CAAC;AAEF;;;GAGG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,yBAAiC;IACzE,4FAA4F;IACpF,aAAa,GAAwB,IAAI,CAAC;IAElD,+DAA+D;IAC/D,IAAW,WAAW;QACpB,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,0FAA0F;IAC1F,IAAW,cAAc;QACvB,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,kFAAkF;IAClF,IAAW,QAAQ;QACjB,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,IAAW,OAAO;QAChB,OAAO,4BAA4B,CAAC;IACtC,CAAC;IAED,6CAA6C;IACtC,kBAAkB;QACvB,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,QAAgB;QAC5D,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,yBAAyB,QAAQ,IAAI,EAAE,CAAC,CAAC;QAC3F,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,0DAA0D,EAAE,CAAC,CAAC;QAChH,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC;QACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,+DAA+D;aACxE,CAAC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5D,OAAO,MAAM,CAAC,OAAO;YACnB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC;YACrE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,YAAY,IAAI,oCAAoC,EAAE,CAAC,CAAC;IAC9G,CAAC;IAED,qCAAqC;IAC9B,WAAW;QAChB,4CAA4C;IAC9C,CAAC;IAED;;;;OAIG;IACgB,YAAY;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,MAAM;aACxB,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;aAC7E,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE;YACtB,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,CAAC;QACH,CAAC,CAAC,CAAC;IACP,CAAC;IAED,4DAA4D;IACpD,SAAS,CAAC,QAAgB;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAA2C,CAAC;YAC9E,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAClH,MAAM,MAAM,GACV,MAAM,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;gBACjF,CAAC,CAAE,MAAM,CAAC,MAAkC;gBAC5C,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1C,OAAO;QACrB,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,KAAK,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC;CACF,CAAA;AAtGY,oBAAoB;IADhC,aAAa,CAAC,yBAAyB,EAAE,sBAAsB,CAAC;GACpD,oBAAoB,CAsGhC;;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB;IACtC,gFAAgF;AAClF,CAAC","sourcesContent":["/**\n * @fileoverview The headless **Client Context** channel — the browser half of the live wire that\n * keeps the realtime co-agent continuously aware of the user's app context and lets it act in the\n * app through a single stable proxy tool.\n *\n * Paired with `ClientContextChannelServer` (`@memberjunction/ai-agents`) via the seeded\n * `MJ: AI Agent Channels` row (`Name: 'ClientContextChannel'`, `IsHeadless: 1`,\n * `ClientPluginClass: 'ClientContextChannel'`).\n *\n * Two responsibilities, both client-side (no server round-trip in the client-direct topology):\n *\n * 1. **Perception (streaming).** It subscribes to the host's live app-context stream\n * ({@link RealtimeChannelContext.AppContext$}, fed by Explorer from `NavigationService`) and, on\n * every change, pushes a compact `SendContextNote` so the model always knows where the user is,\n * what they see, and which tools/agents are available — the *continuous* half of client-context\n * delivery (the session-start half is injected into the companion prompt server-side at mint).\n *\n * 2. **Action (the `ContextTool` proxy).** It declares ONE stable tool, `ContextTool`, so the\n * provider tool surface never changes mid-session (which connect-bound providers reject). The\n * model invokes any currently-available surface client tool via `ContextTool({ action, params })`;\n * the channel routes that to the host's {@link RealtimeChannelContext.ExecuteClientTool} (which runs\n * the surface handler the host registered from `SetAgentClientTools`) and returns a structured\n * result the model narrates.\n *\n * **Headless:** no surface component — it never mounts a tab (`GetSurfaceComponent` stays `null`;\n * `BindSurface` is a no-op). It is a wire, not a panel.\n *\n * @module @memberjunction/ng-conversations\n */\nimport { RegisterClass } from '@memberjunction/global';\nimport { RealtimeToolDefinition } from '@memberjunction/ai';\nimport { FormatAppContextNote } from '@memberjunction/ai-core-plus';\nimport { Subscription } from 'rxjs';\nimport { distinctUntilChanged } from 'rxjs/operators';\nimport { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';\n\n/** The stable name of the single proxy tool this channel registers with the realtime provider. */\nexport const CONTEXT_TOOL_NAME = 'ContextTool';\n\n/** The single stable proxy tool — declared once; the live catalog of valid `action`s rides context. */\nconst CONTEXT_TOOL_DEFINITION: RealtimeToolDefinition = {\n Name: CONTEXT_TOOL_NAME,\n Description:\n \"Perform an action in the application the user is currently in. The set of valid actions (the \" +\n \"client tools and the things you can do on the current surface) is provided to you continuously \" +\n \"as context — only call actions listed as currently available. Pass the action name and its \" +\n \"parameters.\",\n ParametersSchema: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n description: 'The name of a currently-available action/tool to run (from the context you were given).'\n },\n params: {\n type: 'object',\n description: \"The action's parameters, matching its advertised input schema.\"\n }\n },\n required: ['action']\n }\n};\n\n/**\n * The headless Client Context channel client. One instance per realtime session (created by the\n * session service from the `MJ: AI Agent Channels` registry — never construct directly).\n */\n@RegisterClass(BaseRealtimeChannelClient, 'ClientContextChannel')\nexport class ClientContextChannel extends BaseRealtimeChannelClient<object> {\n /** Subscription to the host app-context stream (perception); cleared on {@link Dispose}. */\n private appContextSub: Subscription | null = null;\n\n /** Matches the seeded `MJ: AI Agent Channels` row's `Name`. */\n public get ChannelName(): string {\n return 'ClientContextChannel';\n }\n\n /** Routing prefix — the single `ContextTool` matches `ContextTool`.startsWith(prefix). */\n public get ToolNamePrefix(): string {\n return CONTEXT_TOOL_NAME;\n }\n\n /** Headless — never rendered, but the abstract contract requires a label/icon. */\n public get TabTitle(): string {\n return 'App Context';\n }\n public get TabIcon(): string {\n return 'fa-solid fa-satellite-dish';\n }\n\n /** Declares the single stable proxy tool. */\n public GetToolDefinitions(): RealtimeToolDefinition[] {\n return [CONTEXT_TOOL_DEFINITION];\n }\n\n /**\n * Routes a `ContextTool({ action, params })` call to the host's registered surface client tool.\n * Tolerant: malformed args, a missing host executor, or an unknown/throwing tool all serialize to\n * a structured `{ success: false, output }` the model narrates (never throws).\n */\n public async ApplyAgentTool(toolName: string, argsJson: string): Promise<string> {\n if (toolName !== CONTEXT_TOOL_NAME) {\n return JSON.stringify({ success: false, output: `Unknown context tool \"${toolName}\".` });\n }\n const parsed = this.parseArgs(argsJson);\n if (!parsed.action) {\n return JSON.stringify({ success: false, output: 'ContextTool requires an \"action\" naming the tool to run.' });\n }\n const executor = this.Context?.ExecuteClientTool;\n if (!executor) {\n return JSON.stringify({\n success: false,\n output: 'No app surface is available to perform that action right now.'\n });\n }\n const result = await executor(parsed.action, parsed.params);\n return result.Success\n ? JSON.stringify({ success: true, output: result.Result ?? 'Done.' })\n : JSON.stringify({ success: false, output: result.ErrorMessage ?? 'The action could not be performed.' });\n }\n\n /** Headless — no surface to bind. */\n public BindSurface(): void {\n /* no-op: this channel renders no surface */\n }\n\n /**\n * Subscribes to the host's live app-context stream and streams each change to the model as a\n * compact context note (the perception half). Null-safe — hosts that supply no `AppContext$`\n * (custom apps) simply get no streaming, and the session-start prompt injection still applies.\n */\n protected override OnInitialize(): void {\n const stream = this.Context?.AppContext$;\n if (!stream) {\n return;\n }\n this.appContextSub = stream\n .pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))\n .subscribe((snapshot) => {\n if (!snapshot) {\n return;\n }\n const note = FormatAppContextNote(snapshot);\n if (note) {\n this.Context?.SendContextNote(note);\n }\n });\n }\n\n /** Tolerantly parses the `{ action, params }` arguments. */\n private parseArgs(argsJson: string): { action: string | null; params: Record<string, unknown> } {\n try {\n const parsed = JSON.parse(argsJson) as { action?: unknown; params?: unknown };\n const action = typeof parsed.action === 'string' && parsed.action.trim().length > 0 ? parsed.action.trim() : null;\n const params =\n parsed.params && typeof parsed.params === 'object' && !Array.isArray(parsed.params)\n ? (parsed.params as Record<string, unknown>)\n : {};\n return { action, params };\n } catch {\n return { action: null, params: {} };\n }\n }\n\n /** Unsubscribes the app-context stream and tears down. */\n public override Dispose(): void {\n this.appContextSub?.unsubscribe();\n this.appContextSub = null;\n super.Dispose();\n }\n}\n\n/**\n * Tree-shaking prevention for {@link ClientContextChannel}'s `@RegisterClass` registration. Called\n * from a static code path in `conversations.module.ts` so the registration always executes —\n * mirroring every other realtime channel client.\n */\nexport function LoadClientContextChannel(): void {\n // no-op — the import + call create a static reference bundlers cannot eliminate\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { OnDestroy, OnInit } from '@angular/core';
2
- import { BaseRealtimeChannelClient } from './base-realtime-channel-client';
2
+ import { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
5
5
  * Generic pane host for an interactive channel's surface inside the overlay's tabbed
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-channel-pane.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/realtime-channel-pane.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,SAAS,EAAE,MAAM,EAA4B,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;;AAE3E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAMa,4BAA6B,YAAW,MAAM,EAAE,SAAS;IACpE,oEAAoE;IACzC,MAAM,EAAG,yBAAyB,CAAC;IAE9D,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,UAAU,CAAqC;IAEvD,QAAQ,IAAI,IAAI;IAchB,WAAW,IAAI,IAAI;yCArBR,4BAA4B;2CAA5B,4BAA4B;CA0BxC"}
1
+ {"version":3,"file":"realtime-channel-pane.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/realtime-channel-pane.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,SAAS,EAAE,MAAM,EAAkC,MAAM,eAAe,CAAC;AAClH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;;AAE7E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAMa,4BAA6B,YAAW,MAAM,EAAE,SAAS;IACpE,oEAAoE;IACzC,MAAM,EAAG,yBAAyB,CAAC;IAE9D,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,UAAU,CAAqC;IAEvD,QAAQ,IAAI,IAAI;IAiBhB,WAAW,IAAI,IAAI;yCAxBR,4BAA4B;2CAA5B,4BAA4B;CA6BxC"}
@@ -33,6 +33,9 @@ export class RealtimeChannelPaneComponent {
33
33
  if (!surface) {
34
34
  return;
35
35
  }
36
+ // The runtime carries the surface as an opaque component class — it has no business knowing
37
+ // what a component is in any given framework. This is the single point that does, so the
38
+ // Angular narrowing belongs here rather than as a structural claim in the shared contract.
36
39
  this.surfaceRef = this.viewContainer.createComponent(surface);
37
40
  // Bind BEFORE the created component's first change detection — inputs the plugin sets
38
41
  // here are in place when the surface's ngOnInit runs.
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-channel-pane.component.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/realtime-channel-pane.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,KAAK,EAAqB,gBAAgB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AAG5G;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,MAAM,OAAO,4BAA4B;IACvC,oEAAoE;IACzC,MAAM,CAA6B;IAEtD,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACzC,UAAU,GAAgC,IAAI,CAAC;IAEvD,QAAQ;QACN,8FAA8F;QAC9F,gGAAgG;QAChG,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC9D,sFAAsF;QACtF,sDAAsD;QACtD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,YAAY,EAAE,CAAC;IACnD,CAAC;IAED,WAAW;QACT,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC5B,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;sHAzBU,4BAA4B;6DAA5B,4BAA4B;;iFAA5B,4BAA4B;cANxC,SAAS;6BACI,IAAI,YACN,0BAA0B,YAC1B,EAAE;;kBAKX,KAAK;mBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;kFAFd,4BAA4B","sourcesContent":["import { Component, ComponentRef, Input, OnDestroy, OnInit, ViewContainerRef, inject } from '@angular/core';\nimport { BaseRealtimeChannelClient } from './base-realtime-channel-client';\n\n/**\n * Generic pane host for an interactive channel's surface inside the overlay's tabbed\n * surface panel. Given the per-session channel {@link Plugin}, it:\n *\n * 1. dynamically creates the plugin's surface component\n * ({@link BaseRealtimeChannelClient.GetSurfaceComponent}) into its own view container;\n * 2. immediately hands the created instance to\n * {@link BaseRealtimeChannelClient.BindSurface} — synchronously, BEFORE the surface's\n * first change detection, so inputs the plugin sets are visible in its `ngOnInit`;\n * 3. notifies {@link BaseRealtimeChannelClient.UnbindSurface} when the pane is destroyed\n * (panel collapsed / overlay torn down), flipping the plugin back into its\n * no-surface tool-execution mode.\n *\n * This is how channel surfaces render with ZERO channel-specific wiring in the overlay:\n * the host never knows the surface component's type or API — the plugin wires its own\n * inputs/outputs in `BindSurface`.\n *\n * The created component is inserted as a SIBLING of this host element (standard\n * `ViewContainerRef` semantics), so it participates directly in the pane's flex layout;\n * the host element itself renders nothing (`display: none`).\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-channel-pane',\n template: '',\n styles: [':host { display: none; }']\n})\nexport class RealtimeChannelPaneComponent implements OnInit, OnDestroy {\n /** The per-session channel plugin whose surface this pane hosts. */\n @Input({ required: true }) Plugin!: BaseRealtimeChannelClient;\n\n private viewContainer = inject(ViewContainerRef);\n private surfaceRef: ComponentRef<object> | null = null;\n\n ngOnInit(): void {\n // Server-only channels have no surface (GetSurfaceComponent === null). The overlay should not\n // register a pane for them, but guard here too so a stray registration never crashes the panel.\n const surface = this.Plugin.GetSurfaceComponent();\n if (!surface) {\n return;\n }\n this.surfaceRef = this.viewContainer.createComponent(surface);\n // Bind BEFORE the created component's first change detection — inputs the plugin sets\n // here are in place when the surface's ngOnInit runs.\n this.Plugin.BindSurface(this.surfaceRef.instance);\n this.surfaceRef.changeDetectorRef.markForCheck();\n }\n\n ngOnDestroy(): void {\n this.Plugin.UnbindSurface();\n this.surfaceRef?.destroy();\n this.surfaceRef = null;\n }\n}\n"]}
1
+ {"version":3,"file":"realtime-channel-pane.component.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/channels/realtime-channel-pane.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,KAAK,EAA2B,gBAAgB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AAGlH;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,MAAM,OAAO,4BAA4B;IACvC,oEAAoE;IACzC,MAAM,CAA6B;IAEtD,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACzC,UAAU,GAAgC,IAAI,CAAC;IAEvD,QAAQ;QACN,8FAA8F;QAC9F,gGAAgG;QAChG,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,4FAA4F;QAC5F,yFAAyF;QACzF,2FAA2F;QAC3F,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,OAAuB,CAAC,CAAC;QAC9E,sFAAsF;QACtF,sDAAsD;QACtD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,YAAY,EAAE,CAAC;IACnD,CAAC;IAED,WAAW;QACT,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC5B,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;sHA5BU,4BAA4B;6DAA5B,4BAA4B;;iFAA5B,4BAA4B;cANxC,SAAS;6BACI,IAAI,YACN,0BAA0B,YAC1B,EAAE;;kBAKX,KAAK;mBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;kFAFd,4BAA4B","sourcesContent":["import { Component, ComponentRef, Input, OnDestroy, OnInit, Type, ViewContainerRef, inject } from '@angular/core';\nimport { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';\n\n/**\n * Generic pane host for an interactive channel's surface inside the overlay's tabbed\n * surface panel. Given the per-session channel {@link Plugin}, it:\n *\n * 1. dynamically creates the plugin's surface component\n * ({@link BaseRealtimeChannelClient.GetSurfaceComponent}) into its own view container;\n * 2. immediately hands the created instance to\n * {@link BaseRealtimeChannelClient.BindSurface} — synchronously, BEFORE the surface's\n * first change detection, so inputs the plugin sets are visible in its `ngOnInit`;\n * 3. notifies {@link BaseRealtimeChannelClient.UnbindSurface} when the pane is destroyed\n * (panel collapsed / overlay torn down), flipping the plugin back into its\n * no-surface tool-execution mode.\n *\n * This is how channel surfaces render with ZERO channel-specific wiring in the overlay:\n * the host never knows the surface component's type or API — the plugin wires its own\n * inputs/outputs in `BindSurface`.\n *\n * The created component is inserted as a SIBLING of this host element (standard\n * `ViewContainerRef` semantics), so it participates directly in the pane's flex layout;\n * the host element itself renders nothing (`display: none`).\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-channel-pane',\n template: '',\n styles: [':host { display: none; }']\n})\nexport class RealtimeChannelPaneComponent implements OnInit, OnDestroy {\n /** The per-session channel plugin whose surface this pane hosts. */\n @Input({ required: true }) Plugin!: BaseRealtimeChannelClient;\n\n private viewContainer = inject(ViewContainerRef);\n private surfaceRef: ComponentRef<object> | null = null;\n\n ngOnInit(): void {\n // Server-only channels have no surface (GetSurfaceComponent === null). The overlay should not\n // register a pane for them, but guard here too so a stray registration never crashes the panel.\n const surface = this.Plugin.GetSurfaceComponent();\n if (!surface) {\n return;\n }\n // The runtime carries the surface as an opaque component class — it has no business knowing\n // what a component is in any given framework. This is the single point that does, so the\n // Angular narrowing belongs here rather than as a structural claim in the shared contract.\n this.surfaceRef = this.viewContainer.createComponent(surface as Type<object>);\n // Bind BEFORE the created component's first change detection — inputs the plugin sets\n // here are in place when the surface's ngOnInit runs.\n this.Plugin.BindSurface(this.surfaceRef.instance);\n this.surfaceRef.changeDetectorRef.markForCheck();\n }\n\n ngOnDestroy(): void {\n this.Plugin.UnbindSurface();\n this.surfaceRef?.destroy();\n this.surfaceRef = null;\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { Type } from '@angular/core';
2
2
  import { RealtimeToolDefinition } from '@memberjunction/ai';
3
- import { BaseRealtimeChannelClient, ChannelOnboardingDetails } from '../channels/base-realtime-channel-client';
3
+ import { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';
4
+ import { ChannelOnboardingDetails } from '@memberjunction/realtime-runtime';
4
5
  import { MediaChannelState } from './media-channel-state';
5
6
  import { RealtimeMediaSurfaceComponent } from './realtime-media-surface.component';
6
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"media-channel.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/media/media-channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AAE/G,OAAO,EAAE,iBAAiB,EAAiC,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AAkBnF;;;;;;;;;;;;;;;;;GAiBG;AACH,qBACa,oBAAqB,SAAQ,yBAAyB,CAAC,6BAA6B,CAAC;IAChG,mFAAmF;IACnF,SAAgB,KAAK,oBAA2B;IAEhD,2EAA2E;IAC3E,OAAO,CAAC,OAAO,CAA8C;IAC7D,8EAA8E;IAC9E,OAAO,CAAC,eAAe,CAA6B;IAEpD,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED,IAAW,cAAc,IAAI,MAAM,CAElC;IAED,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,OAAO,IAAI,MAAM,CAE3B;IAEM,kBAAkB,IAAI,sBAAsB,EAAE;IAIrC,mBAAmB,IAAI,IAAI,CAAC,6BAA6B,CAAC;IAI1E,yFAAyF;IACzE,oBAAoB,IAAI,wBAAwB;IAgBhE,kGAAkG;cAC/E,YAAY,IAAI,IAAI;IAMvC;;;;OAIG;IACI,WAAW,CAAC,QAAQ,EAAE,6BAA6B,GAAG,IAAI;IAOjD,aAAa,IAAI,IAAI;IAIrC;;;;;;OAMG;IACI,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IA2BjE,+GAA+G;IAC/G,OAAO,CAAC,cAAc;IAyBtB,2BAA2B;IAC3B,OAAO,CAAC,eAAe;IAavB,qDAAqD;IACrD,OAAO,CAAC,cAAc;IAatB,mFAAmF;IACnF,OAAO,CAAC,cAAc;IAqBtB,wBAAwB;IACxB,OAAO,CAAC,aAAa;IAMrB,4FAA4F;IAC5E,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/C;;;;OAIG;IACa,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIxC,OAAO,IAAI,IAAI;IAO/B,sFAAsF;IACtF,OAAO,CAAC,IAAI;IAIZ;;;OAGG;IACH,OAAO,CAAC,IAAI;CAKb;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
1
+ {"version":3,"file":"media-channel.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/media/media-channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,iBAAiB,EAAiC,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AAkBnF;;;;;;;;;;;;;;;;;GAiBG;AACH,qBACa,oBAAqB,SAAQ,yBAAyB,CAAC,6BAA6B,CAAC;IAChG,mFAAmF;IACnF,SAAgB,KAAK,oBAA2B;IAEhD,2EAA2E;IAC3E,OAAO,CAAC,OAAO,CAA8C;IAC7D,8EAA8E;IAC9E,OAAO,CAAC,eAAe,CAA6B;IAEpD,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED,IAAW,cAAc,IAAI,MAAM,CAElC;IAED,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,OAAO,IAAI,MAAM,CAE3B;IAEM,kBAAkB,IAAI,sBAAsB,EAAE;IAIrC,mBAAmB,IAAI,IAAI,CAAC,6BAA6B,CAAC;IAI1E,yFAAyF;IACzE,oBAAoB,IAAI,wBAAwB;IAgBhE,kGAAkG;cAC/E,YAAY,IAAI,IAAI;IAMvC;;;;OAIG;IACI,WAAW,CAAC,QAAQ,EAAE,6BAA6B,GAAG,IAAI;IAOjD,aAAa,IAAI,IAAI;IAIrC;;;;;;OAMG;IACI,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IA2BjE,+GAA+G;IAC/G,OAAO,CAAC,cAAc;IAyBtB,2BAA2B;IAC3B,OAAO,CAAC,eAAe;IAavB,qDAAqD;IACrD,OAAO,CAAC,cAAc;IAatB,mFAAmF;IACnF,OAAO,CAAC,cAAc;IAqBtB,wBAAwB;IACxB,OAAO,CAAC,aAAa;IAMrB,4FAA4F;IAC5E,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/C;;;;OAIG;IACa,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIxC,OAAO,IAAI,IAAI;IAO/B,sFAAsF;IACtF,OAAO,CAAC,IAAI;IAIZ;;;OAGG;IACH,OAAO,CAAC,IAAI;CAKb;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { RegisterClass } from '@memberjunction/global';
8
- import { BaseRealtimeChannelClient } from '../channels/base-realtime-channel-client';
8
+ import { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';
9
9
  import { MEDIA_TOOL_DEFINITIONS, MEDIA_TOOL_NAMES, MEDIA_TOOL_PREFIX } from './media-channel-tools';
10
10
  import { MediaChannelState } from './media-channel-state';
11
11
  import { RealtimeMediaSurfaceComponent } from './realtime-media-surface.component';
@@ -1 +1 @@
1
- {"version":3,"file":"media-channel.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/media/media-channel.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Type } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { RegisterClass } from '@memberjunction/global';\nimport { RealtimeToolDefinition } from '@memberjunction/ai';\nimport { BaseRealtimeChannelClient, ChannelOnboardingDetails } from '../channels/base-realtime-channel-client';\nimport { MEDIA_TOOL_DEFINITIONS, MEDIA_TOOL_NAMES, MEDIA_TOOL_PREFIX } from './media-channel-tools';\nimport { MediaChannelState, MediaHighlight, MediaItemType } from './media-channel-state';\nimport { RealtimeMediaSurfaceComponent } from './realtime-media-surface.component';\n\n/** A JSON-serializable value (the building block of a parsed tool-args object). */\ntype ToolArgValue = string | number | boolean | null | ToolArgValue[] | { [key: string]: ToolArgValue };\n\n/** Coerces a parsed arg to a non-empty string, or `undefined` when absent / wrong-typed. */\nfunction asString(value: ToolArgValue | undefined): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\n/** Coerces a parsed arg to a finite number, or `undefined` when absent / wrong-typed. */\nfunction asNumber(value: ToolArgValue | undefined): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\n/** The media types `Media_ShowMedia` accepts (validated before mutating state). */\nconst VALID_MEDIA_TYPES: MediaItemType[] = ['image', 'video', 'audio', 'pdf', 'web'];\n\n/**\n * The shared MEDIA SURFACE as a pluggable interactive channel — a {@link BaseRealtimeChannelClient}\n * resolved from the `MJ: AI Agent Channels` registry row whose `ClientPluginClass` is\n * `'RealtimeMediaChannel'`. One instance per session (created via ClassFactory at session start).\n *\n * It owns a {@link MediaChannelState} engine and contributes the channel's full contract:\n *\n * - **Action**: the `Media_*` client-executed tool set ({@link MEDIA_TOOL_DEFINITIONS});\n * {@link ApplyAgentTool} parses the args, mutates the state engine, returns a short JSON result\n * string, and sends the model a `[media]` background context note (so it stays aware of what's\n * on screen). Works with NO surface bound — the tools mutate the state engine directly.\n * - **Surface**: {@link RealtimeMediaSurfaceComponent}, created dynamically by the overlay's\n * channel tab; {@link BindSurface} hands it the shared state engine + agent name.\n * - **State of record**: every mutation requests a debounced save of {@link MediaChannelState.ToJSON}\n * under channel name `'Media'`; a prior session's media is rehydrated via {@link RestoreState}.\n *\n * Modeled directly on `RealtimeWhiteboardChannel`.\n */\n@RegisterClass(BaseRealtimeChannelClient, 'RealtimeMediaChannel')\nexport class RealtimeMediaChannel extends BaseRealtimeChannelClient<RealtimeMediaSurfaceComponent> {\n /** The media state of record — created fresh with the plugin (one per session). */\n public readonly State = new MediaChannelState();\n\n /** The live bound surface, when the channel tab's pane is instantiated. */\n private surface: RealtimeMediaSurfaceComponent | null = null;\n /** Media-mutation subscription driving the debounced state-of-record save. */\n private stateChangedSub: Subscription | null = null;\n\n public get ChannelName(): string {\n return 'Media';\n }\n\n public get ToolNamePrefix(): string {\n return MEDIA_TOOL_PREFIX;\n }\n\n public get TabTitle(): string {\n return 'Media';\n }\n\n public get TabIcon(): string {\n return 'fa-solid fa-images';\n }\n\n public GetToolDefinitions(): RealtimeToolDefinition[] {\n return MEDIA_TOOL_DEFINITIONS;\n }\n\n public override GetSurfaceComponent(): Type<RealtimeMediaSurfaceComponent> {\n return RealtimeMediaSurfaceComponent;\n }\n\n /** First-run intro shown the first time the user opens the Media tab (once per user). */\n public override GetOnboardingDetails(): ChannelOnboardingDetails {\n return {\n Heading: 'Media',\n Description:\n 'A shared surface where the agent can show you visuals during the call — images, videos, ' +\n 'audio clips, PDFs and web pages. Each item opens in its own tab; the agent can switch ' +\n 'between them and highlight regions to point at exactly what it means.',\n Tips: [\n 'Switch between shared items using the tabs along the top.',\n 'The agent can highlight part of an image or page to draw your eye to it.',\n 'Open any item in a new browser tab or download it from the toolbar.',\n ],\n IconClass: 'fa-solid fa-images',\n };\n }\n\n /** Persist the media surface (host-debounced) on EVERY mutation — agent tools and tab changes. */\n protected override OnInitialize(): void {\n this.stateChangedSub = this.State.Changed$.subscribe(() => {\n this.Context?.RequestSave(this.State.ToJSON());\n });\n }\n\n /**\n * Wires the dynamically-created media surface (before first CD): shared state engine + agent name,\n * plus the live session's MJ provider so FileID-backed items stream securely (mj-storage-media-player\n * + CreateMediaAccessToken) under the SAME authenticated, multi-provider-safe provider.\n */\n public BindSurface(instance: RealtimeMediaSurfaceComponent): void {\n this.surface = instance;\n instance.State = this.State;\n instance.AgentName = this.Context?.AgentName ?? 'The agent';\n instance.Provider = this.Context?.Provider ?? null;\n }\n\n public override UnbindSurface(): void {\n this.surface = null;\n }\n\n /**\n * Executes one `Media_*` tool call LOCALLY: parse args, mutate the state engine, push a `[media]`\n * background context note so the agent stays aware of the surface, and return a short JSON result\n * string for the model. Never throws — malformed args resolve to a `{ success: false, error }`\n * payload the model can narrate. Works with or without a bound surface (it mutates the state engine,\n * which the surface observes).\n */\n public ApplyAgentTool(toolName: string, argsJson: string): string {\n let args: Record<string, ToolArgValue> = {};\n try {\n const parsed = argsJson ? (JSON.parse(argsJson) as unknown) : {};\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n args = parsed as Record<string, ToolArgValue>;\n }\n } catch {\n return this.fail(`Could not parse arguments for ${toolName}.`);\n }\n\n switch (toolName) {\n case MEDIA_TOOL_NAMES.ShowMedia:\n return this.applyShowMedia(args);\n case MEDIA_TOOL_NAMES.CloseMedia:\n return this.applyCloseMedia(args);\n case MEDIA_TOOL_NAMES.PlayMedia:\n return this.applyPlayMedia(args);\n case MEDIA_TOOL_NAMES.Highlight:\n return this.applyHighlight(args);\n case MEDIA_TOOL_NAMES.ClearAll:\n return this.applyClearAll();\n default:\n return this.fail(`Unknown Media tool \"${toolName}\".`);\n }\n }\n\n /** Adds a media item and makes it active. Source is a public `url` OR an MJStorage `fileId` (>=1 required). */\n private applyShowMedia(args: Record<string, ToolArgValue>): string {\n const mediaType = asString(args['mediaType']);\n const url = asString(args['url']);\n const fileId = asString(args['fileId']);\n const displayName = asString(args['displayName']);\n if (!mediaType || !VALID_MEDIA_TYPES.includes(mediaType as MediaItemType)) {\n return this.fail('Media_ShowMedia requires a \"mediaType\" of image | video | audio | pdf | web.');\n }\n if (!url && !fileId) {\n return this.fail('Media_ShowMedia requires a source — provide a \"url\" (external/public) OR a \"fileId\" (an MJ: Files id).');\n }\n if (!displayName) {\n return this.fail('Media_ShowMedia requires a \"displayName\".');\n }\n const item = this.State.AddItem({\n Type: mediaType as MediaItemType,\n Url: url,\n FileID: fileId,\n DisplayName: displayName,\n Caption: asString(args['caption']),\n });\n this.note(`now showing ${mediaType} \"${displayName}\"`);\n return JSON.stringify({ success: true, id: item.Id, active: true });\n }\n\n /** Closes a media item. */\n private applyCloseMedia(args: Record<string, ToolArgValue>): string {\n const id = asString(args['id']);\n if (!id) {\n return this.fail('Media_CloseMedia requires an \"id\".');\n }\n const removed = this.State.RemoveItem(id);\n if (!removed) {\n return this.fail(`No media item with id \"${id}\".`);\n }\n this.note(`closed media item \"${id}\"`);\n return JSON.stringify({ success: true, id });\n }\n\n /** Activates + requests playback of a media item. */\n private applyPlayMedia(args: Record<string, ToolArgValue>): string {\n const id = asString(args['id']);\n if (!id) {\n return this.fail('Media_PlayMedia requires an \"id\".');\n }\n const ok = this.State.RequestPlay(id);\n if (!ok) {\n return this.fail(`No media item with id \"${id}\".`);\n }\n this.note(`playing media item \"${id}\"`);\n return JSON.stringify({ success: true, id });\n }\n\n /** Draws (or, with absent dims, clears) a fractional highlight on a media item. */\n private applyHighlight(args: Record<string, ToolArgValue>): string {\n const id = asString(args['id']);\n if (!id) {\n return this.fail('Media_Highlight requires an \"id\".');\n }\n const x = asNumber(args['x']);\n const y = asNumber(args['y']);\n const w = asNumber(args['w']);\n const h = asNumber(args['h']);\n if (x === undefined || y === undefined || w === undefined || h === undefined) {\n return this.fail('Media_Highlight requires numeric fractional x, y, w, h (0..1).');\n }\n const highlight: MediaHighlight = { X: x, Y: y, W: w, H: h, Label: asString(args['label']) };\n const ok = this.State.Highlight(id, highlight);\n if (!ok) {\n return this.fail(`No media item with id \"${id}\".`);\n }\n this.note(`highlighted a region of media item \"${id}\"`);\n return JSON.stringify({ success: true, id });\n }\n\n /** Clears all media. */\n private applyClearAll(): string {\n this.State.Clear();\n this.note('cleared all media');\n return JSON.stringify({ success: true });\n }\n\n /** The Media channel's serialized state of record (persisted under {@link ChannelName}). */\n public override SerializeState(): string | null {\n return this.State.ToJSON();\n }\n\n /**\n * Rehydrates a prior session's saved media into THIS session's state engine (in place — the\n * {@link State} instance and its subscriptions are preserved). Tolerant: malformed JSON returns\n * `false` and the surface stays empty.\n */\n public override RestoreState(stateJson: string): boolean {\n return this.State.LoadFromJSON(stateJson);\n }\n\n public override Dispose(): void {\n this.stateChangedSub?.unsubscribe();\n this.stateChangedSub = null;\n this.surface = null;\n super.Dispose();\n }\n\n /** Builds a model-readable failure payload (never thrown — returned to the model). */\n private fail(error: string): string {\n return JSON.stringify({ success: false, error });\n }\n\n /**\n * Pushes a background context note so the agent stays aware of the surface state. Framed as\n * background (like the whiteboard's scene-delta notes) so the model doesn't narrate every change.\n */\n private note(summary: string): void {\n this.Context?.SendContextNote(\n `[media] ${summary} (background context — do NOT narrate routine changes; mention only if relevant).`,\n );\n }\n}\n\n/**\n * Tree-shaking prevention: the Media channel is resolved dynamically through the ClassFactory (by the\n * registry row's `ClientPluginClass` key), so this static call keeps its `@RegisterClass` side effect\n * from being eliminated by the bundler. Called alongside `LoadRealtimeWhiteboardChannel()`.\n */\nexport function LoadRealtimeMediaChannel(): void {\n // intentional no-op — the import side effect performs the registration\n}\n"]}
1
+ {"version":3,"file":"media-channel.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/media/media-channel.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Type } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { RegisterClass } from '@memberjunction/global';\nimport { RealtimeToolDefinition } from '@memberjunction/ai';\nimport { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';\nimport { ChannelOnboardingDetails } from '@memberjunction/realtime-runtime';\nimport { MEDIA_TOOL_DEFINITIONS, MEDIA_TOOL_NAMES, MEDIA_TOOL_PREFIX } from './media-channel-tools';\nimport { MediaChannelState, MediaHighlight, MediaItemType } from './media-channel-state';\nimport { RealtimeMediaSurfaceComponent } from './realtime-media-surface.component';\n\n/** A JSON-serializable value (the building block of a parsed tool-args object). */\ntype ToolArgValue = string | number | boolean | null | ToolArgValue[] | { [key: string]: ToolArgValue };\n\n/** Coerces a parsed arg to a non-empty string, or `undefined` when absent / wrong-typed. */\nfunction asString(value: ToolArgValue | undefined): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\n/** Coerces a parsed arg to a finite number, or `undefined` when absent / wrong-typed. */\nfunction asNumber(value: ToolArgValue | undefined): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\n/** The media types `Media_ShowMedia` accepts (validated before mutating state). */\nconst VALID_MEDIA_TYPES: MediaItemType[] = ['image', 'video', 'audio', 'pdf', 'web'];\n\n/**\n * The shared MEDIA SURFACE as a pluggable interactive channel — a {@link BaseRealtimeChannelClient}\n * resolved from the `MJ: AI Agent Channels` registry row whose `ClientPluginClass` is\n * `'RealtimeMediaChannel'`. One instance per session (created via ClassFactory at session start).\n *\n * It owns a {@link MediaChannelState} engine and contributes the channel's full contract:\n *\n * - **Action**: the `Media_*` client-executed tool set ({@link MEDIA_TOOL_DEFINITIONS});\n * {@link ApplyAgentTool} parses the args, mutates the state engine, returns a short JSON result\n * string, and sends the model a `[media]` background context note (so it stays aware of what's\n * on screen). Works with NO surface bound — the tools mutate the state engine directly.\n * - **Surface**: {@link RealtimeMediaSurfaceComponent}, created dynamically by the overlay's\n * channel tab; {@link BindSurface} hands it the shared state engine + agent name.\n * - **State of record**: every mutation requests a debounced save of {@link MediaChannelState.ToJSON}\n * under channel name `'Media'`; a prior session's media is rehydrated via {@link RestoreState}.\n *\n * Modeled directly on `RealtimeWhiteboardChannel`.\n */\n@RegisterClass(BaseRealtimeChannelClient, 'RealtimeMediaChannel')\nexport class RealtimeMediaChannel extends BaseRealtimeChannelClient<RealtimeMediaSurfaceComponent> {\n /** The media state of record — created fresh with the plugin (one per session). */\n public readonly State = new MediaChannelState();\n\n /** The live bound surface, when the channel tab's pane is instantiated. */\n private surface: RealtimeMediaSurfaceComponent | null = null;\n /** Media-mutation subscription driving the debounced state-of-record save. */\n private stateChangedSub: Subscription | null = null;\n\n public get ChannelName(): string {\n return 'Media';\n }\n\n public get ToolNamePrefix(): string {\n return MEDIA_TOOL_PREFIX;\n }\n\n public get TabTitle(): string {\n return 'Media';\n }\n\n public get TabIcon(): string {\n return 'fa-solid fa-images';\n }\n\n public GetToolDefinitions(): RealtimeToolDefinition[] {\n return MEDIA_TOOL_DEFINITIONS;\n }\n\n public override GetSurfaceComponent(): Type<RealtimeMediaSurfaceComponent> {\n return RealtimeMediaSurfaceComponent;\n }\n\n /** First-run intro shown the first time the user opens the Media tab (once per user). */\n public override GetOnboardingDetails(): ChannelOnboardingDetails {\n return {\n Heading: 'Media',\n Description:\n 'A shared surface where the agent can show you visuals during the call — images, videos, ' +\n 'audio clips, PDFs and web pages. Each item opens in its own tab; the agent can switch ' +\n 'between them and highlight regions to point at exactly what it means.',\n Tips: [\n 'Switch between shared items using the tabs along the top.',\n 'The agent can highlight part of an image or page to draw your eye to it.',\n 'Open any item in a new browser tab or download it from the toolbar.',\n ],\n IconClass: 'fa-solid fa-images',\n };\n }\n\n /** Persist the media surface (host-debounced) on EVERY mutation — agent tools and tab changes. */\n protected override OnInitialize(): void {\n this.stateChangedSub = this.State.Changed$.subscribe(() => {\n this.Context?.RequestSave(this.State.ToJSON());\n });\n }\n\n /**\n * Wires the dynamically-created media surface (before first CD): shared state engine + agent name,\n * plus the live session's MJ provider so FileID-backed items stream securely (mj-storage-media-player\n * + CreateMediaAccessToken) under the SAME authenticated, multi-provider-safe provider.\n */\n public BindSurface(instance: RealtimeMediaSurfaceComponent): void {\n this.surface = instance;\n instance.State = this.State;\n instance.AgentName = this.Context?.AgentName ?? 'The agent';\n instance.Provider = this.Context?.Provider ?? null;\n }\n\n public override UnbindSurface(): void {\n this.surface = null;\n }\n\n /**\n * Executes one `Media_*` tool call LOCALLY: parse args, mutate the state engine, push a `[media]`\n * background context note so the agent stays aware of the surface, and return a short JSON result\n * string for the model. Never throws — malformed args resolve to a `{ success: false, error }`\n * payload the model can narrate. Works with or without a bound surface (it mutates the state engine,\n * which the surface observes).\n */\n public ApplyAgentTool(toolName: string, argsJson: string): string {\n let args: Record<string, ToolArgValue> = {};\n try {\n const parsed = argsJson ? (JSON.parse(argsJson) as unknown) : {};\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n args = parsed as Record<string, ToolArgValue>;\n }\n } catch {\n return this.fail(`Could not parse arguments for ${toolName}.`);\n }\n\n switch (toolName) {\n case MEDIA_TOOL_NAMES.ShowMedia:\n return this.applyShowMedia(args);\n case MEDIA_TOOL_NAMES.CloseMedia:\n return this.applyCloseMedia(args);\n case MEDIA_TOOL_NAMES.PlayMedia:\n return this.applyPlayMedia(args);\n case MEDIA_TOOL_NAMES.Highlight:\n return this.applyHighlight(args);\n case MEDIA_TOOL_NAMES.ClearAll:\n return this.applyClearAll();\n default:\n return this.fail(`Unknown Media tool \"${toolName}\".`);\n }\n }\n\n /** Adds a media item and makes it active. Source is a public `url` OR an MJStorage `fileId` (>=1 required). */\n private applyShowMedia(args: Record<string, ToolArgValue>): string {\n const mediaType = asString(args['mediaType']);\n const url = asString(args['url']);\n const fileId = asString(args['fileId']);\n const displayName = asString(args['displayName']);\n if (!mediaType || !VALID_MEDIA_TYPES.includes(mediaType as MediaItemType)) {\n return this.fail('Media_ShowMedia requires a \"mediaType\" of image | video | audio | pdf | web.');\n }\n if (!url && !fileId) {\n return this.fail('Media_ShowMedia requires a source — provide a \"url\" (external/public) OR a \"fileId\" (an MJ: Files id).');\n }\n if (!displayName) {\n return this.fail('Media_ShowMedia requires a \"displayName\".');\n }\n const item = this.State.AddItem({\n Type: mediaType as MediaItemType,\n Url: url,\n FileID: fileId,\n DisplayName: displayName,\n Caption: asString(args['caption']),\n });\n this.note(`now showing ${mediaType} \"${displayName}\"`);\n return JSON.stringify({ success: true, id: item.Id, active: true });\n }\n\n /** Closes a media item. */\n private applyCloseMedia(args: Record<string, ToolArgValue>): string {\n const id = asString(args['id']);\n if (!id) {\n return this.fail('Media_CloseMedia requires an \"id\".');\n }\n const removed = this.State.RemoveItem(id);\n if (!removed) {\n return this.fail(`No media item with id \"${id}\".`);\n }\n this.note(`closed media item \"${id}\"`);\n return JSON.stringify({ success: true, id });\n }\n\n /** Activates + requests playback of a media item. */\n private applyPlayMedia(args: Record<string, ToolArgValue>): string {\n const id = asString(args['id']);\n if (!id) {\n return this.fail('Media_PlayMedia requires an \"id\".');\n }\n const ok = this.State.RequestPlay(id);\n if (!ok) {\n return this.fail(`No media item with id \"${id}\".`);\n }\n this.note(`playing media item \"${id}\"`);\n return JSON.stringify({ success: true, id });\n }\n\n /** Draws (or, with absent dims, clears) a fractional highlight on a media item. */\n private applyHighlight(args: Record<string, ToolArgValue>): string {\n const id = asString(args['id']);\n if (!id) {\n return this.fail('Media_Highlight requires an \"id\".');\n }\n const x = asNumber(args['x']);\n const y = asNumber(args['y']);\n const w = asNumber(args['w']);\n const h = asNumber(args['h']);\n if (x === undefined || y === undefined || w === undefined || h === undefined) {\n return this.fail('Media_Highlight requires numeric fractional x, y, w, h (0..1).');\n }\n const highlight: MediaHighlight = { X: x, Y: y, W: w, H: h, Label: asString(args['label']) };\n const ok = this.State.Highlight(id, highlight);\n if (!ok) {\n return this.fail(`No media item with id \"${id}\".`);\n }\n this.note(`highlighted a region of media item \"${id}\"`);\n return JSON.stringify({ success: true, id });\n }\n\n /** Clears all media. */\n private applyClearAll(): string {\n this.State.Clear();\n this.note('cleared all media');\n return JSON.stringify({ success: true });\n }\n\n /** The Media channel's serialized state of record (persisted under {@link ChannelName}). */\n public override SerializeState(): string | null {\n return this.State.ToJSON();\n }\n\n /**\n * Rehydrates a prior session's saved media into THIS session's state engine (in place — the\n * {@link State} instance and its subscriptions are preserved). Tolerant: malformed JSON returns\n * `false` and the surface stays empty.\n */\n public override RestoreState(stateJson: string): boolean {\n return this.State.LoadFromJSON(stateJson);\n }\n\n public override Dispose(): void {\n this.stateChangedSub?.unsubscribe();\n this.stateChangedSub = null;\n this.surface = null;\n super.Dispose();\n }\n\n /** Builds a model-readable failure payload (never thrown — returned to the model). */\n private fail(error: string): string {\n return JSON.stringify({ success: false, error });\n }\n\n /**\n * Pushes a background context note so the agent stays aware of the surface state. Framed as\n * background (like the whiteboard's scene-delta notes) so the model doesn't narrate every change.\n */\n private note(summary: string): void {\n this.Context?.SendContextNote(\n `[media] ${summary} (background context — do NOT narrate routine changes; mention only if relevant).`,\n );\n }\n}\n\n/**\n * Tree-shaking prevention: the Media channel is resolved dynamically through the ClassFactory (by the\n * registry row's `ClientPluginClass` key), so this static call keeps its `@RegisterClass` side effect\n * from being eliminated by the bundler. Called alongside `LoadRealtimeWhiteboardChannel()`.\n */\nexport function LoadRealtimeMediaChannel(): void {\n // intentional no-op — the import side effect performs the registration\n}\n"]}
@@ -2,7 +2,7 @@ import { EventEmitter, OnInit, OnDestroy } from '@angular/core';
2
2
  import { SplitGutterInteractionEvent } from 'angular-split';
3
3
  import { UserInfo } from '@memberjunction/core';
4
4
  import { RealtimeSessionState, RealtimeDelegationCardVM } from './realtime-session-state';
5
- import { ParsedDelegationArtifact } from '../../services/delegation-result-parser';
5
+ import { ParsedDelegationArtifact } from '@memberjunction/realtime-runtime';
6
6
  import * as i0 from "@angular/core";
7
7
  /**
8
8
  * The "Session activity" surface (the Activity tab's content): a compact, newest-first list
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-activity-rail.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-activity-rail.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,EAAE,SAAS,EAA6B,MAAM,eAAe,CAAC;AAGrH,OAAO,EAAsB,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EACL,oBAAoB,EAAE,wBAAwB,EAC/C,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;;AAMnF;;;;;;;;;;;;;;;;GAgBG;AACH,qBAOa,6BAA8B,YAAW,MAAM,EAAE,SAAS;IACrE,+DAA+D;IAC/D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAM;IAE7C,6DAA6D;IAClC,KAAK,EAAG,oBAAoB,CAAC;IAExD,kFAAkF;IACzE,OAAO,UAAS;IAEzB;;;;;OAKG;IACM,QAAQ,UAAS;IAE1B,sEAAsE;IAC7D,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAE7C,6EAA6E;IACpE,aAAa,SAAM;IAE5B;;;;;OAKG;IACM,cAAc,EAAE,wBAAwB,EAAE,CAAM;IAEzD,0FAA0F;IAChF,gBAAgB,uBAA8B;IAExD,8FAA8F;IACpF,qBAAqB,yCAAgD;IAE/E,qFAAqF;IAC9E,SAAS,UAAS;IAEzB,+FAA+F;IACxF,gBAAgB,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IAEhE,0FAA0F;IACnF,oBAAoB,SAAkC;IAE7D,OAAO,CAAC,UAAU,CAAC,CAAe;IAClC,OAAO,CAAC,GAAG,CAA6B;IAExC,qFAAqF;IACrF,SAAgB,oBAAoB,UACyD;IAE7F,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IAInB,qFAAqF;IAC9E,MAAM,IAAI,IAAI;IAIrB,wCAAwC;IACjC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,GAAG,MAAM;IAIvE,gDAAgD;IACzC,SAAS,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM;IAIxD,4FAA4F;IACrF,OAAO,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM,GAAG,IAAI;IAO7D,2IAA2I;IACpI,WAAW,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO;IAI3D,+DAA+D;IACxD,OAAO,CAAC,IAAI,EAAE,wBAAwB,GAAG,IAAI;IAMpD,6FAA6F;IACtF,aAAa,CAAC,IAAI,EAAE,wBAAwB,GAAG,wBAAwB,EAAE;IAIhF,qDAAqD;IAC9C,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,wBAAwB,GAAG,MAAM;IAI/E,8EAA8E;IACvE,cAAc,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO;IAIlE;;;;;OAKG;IACI,YAAY,CAAC,QAAQ,EAAE,wBAAwB,GAAG,IAAI;IAS7D,iEAAiE;IAC1D,aAAa,IAAI,IAAI;IAO5B;;;;;OAKG;IACI,cAAc,CAAC,KAAK,EAAE,2BAA2B,GAAG,IAAI;IAS/D,8CAA8C;IACvC,OAAO,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM;IAMtD,wFAAwF;IACxF,OAAO,CAAC,aAAa;IAWrB,gFAAgF;IAChF,OAAO,CAAC,gBAAgB;yCA3Kb,6BAA6B;2CAA7B,6BAA6B;CAkLzC"}
1
+ {"version":3,"file":"realtime-activity-rail.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-activity-rail.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,EAAE,SAAS,EAA6B,MAAM,eAAe,CAAC;AAGrH,OAAO,EAAsB,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EACL,oBAAoB,EAAE,wBAAwB,EAC/C,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;;AAM5E;;;;;;;;;;;;;;;;GAgBG;AACH,qBAOa,6BAA8B,YAAW,MAAM,EAAE,SAAS;IACrE,+DAA+D;IAC/D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAM;IAE7C,6DAA6D;IAClC,KAAK,EAAG,oBAAoB,CAAC;IAExD,kFAAkF;IACzE,OAAO,UAAS;IAEzB;;;;;OAKG;IACM,QAAQ,UAAS;IAE1B,sEAAsE;IAC7D,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAE7C,6EAA6E;IACpE,aAAa,SAAM;IAE5B;;;;;OAKG;IACM,cAAc,EAAE,wBAAwB,EAAE,CAAM;IAEzD,0FAA0F;IAChF,gBAAgB,uBAA8B;IAExD,8FAA8F;IACpF,qBAAqB,yCAAgD;IAE/E,qFAAqF;IAC9E,SAAS,UAAS;IAEzB,+FAA+F;IACxF,gBAAgB,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IAEhE,0FAA0F;IACnF,oBAAoB,SAAkC;IAE7D,OAAO,CAAC,UAAU,CAAC,CAAe;IAClC,OAAO,CAAC,GAAG,CAA6B;IAExC,qFAAqF;IACrF,SAAgB,oBAAoB,UACyD;IAE7F,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IAInB,qFAAqF;IAC9E,MAAM,IAAI,IAAI;IAIrB,wCAAwC;IACjC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,GAAG,MAAM;IAIvE,gDAAgD;IACzC,SAAS,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM;IAIxD,4FAA4F;IACrF,OAAO,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM,GAAG,IAAI;IAO7D,2IAA2I;IACpI,WAAW,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO;IAI3D,+DAA+D;IACxD,OAAO,CAAC,IAAI,EAAE,wBAAwB,GAAG,IAAI;IAMpD,6FAA6F;IACtF,aAAa,CAAC,IAAI,EAAE,wBAAwB,GAAG,wBAAwB,EAAE;IAIhF,qDAAqD;IAC9C,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,wBAAwB,GAAG,MAAM;IAI/E,8EAA8E;IACvE,cAAc,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO;IAIlE;;;;;OAKG;IACI,YAAY,CAAC,QAAQ,EAAE,wBAAwB,GAAG,IAAI;IAS7D,iEAAiE;IAC1D,aAAa,IAAI,IAAI;IAO5B;;;;;OAKG;IACI,cAAc,CAAC,KAAK,EAAE,2BAA2B,GAAG,IAAI;IAS/D,8CAA8C;IACvC,OAAO,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM;IAMtD,wFAAwF;IACxF,OAAO,CAAC,aAAa;IAWrB,gFAAgF;IAChF,OAAO,CAAC,gBAAgB;yCA3Kb,6BAA6B;2CAA7B,6BAA6B;CAkLzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-activity-rail.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-activity-rail.component.ts","../../../../src/lib/components/realtime/realtime-activity-rail.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output, OnInit, OnDestroy, ChangeDetectorRef, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { AngularSplitModule, SplitGutterInteractionEvent } from 'angular-split';\nimport { UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { ArtifactsModule } from '@memberjunction/ng-artifacts';\nimport {\n RealtimeSessionState, RealtimeDelegationCardVM, FriendlyStepLabel, FormatElapsed\n} from './realtime-session-state';\nimport { ParsedDelegationArtifact } from '../../services/delegation-result-parser';\nimport {\n ACTIVITY_SPLIT_DEFAULT_PERCENT, ACTIVITY_SPLIT_PREF_KEY,\n ClampActivitySplitPercent, ParseActivitySplitPercent, SerializeActivitySplitPercent\n} from './realtime-surface-tab-style';\n\n/**\n * The \"Session activity\" surface (the Activity tab's content): a compact, newest-first list\n * of EVERY tool/agent call of the session — so parallel/multiple delegations live here and\n * the conversation thread stays clean.\n *\n * Each entry shows agent name, status, the latest friendly step label, elapsed time, and a\n * one-line result preview. When a run produced ARTIFACTS, each artifact renders as an inline\n * PREVIEW card (reusing `mj-artifact-message-card`, the same component the conversation\n * messages use). Clicking a preview SPLITS this pane horizontally — activity list on the\n * LEFT, the full artifact viewer on the RIGHT (`as-split`); clicking another swaps the right\n * pane; a close control collapses back to full-width activity. The split width is persisted\n * per-user via {@link UserInfoEngine} (NOT localStorage). This replaces the old \"one surface\n * tab per artifact\" model.\n *\n * Collapsible via the chevron in its header (standalone presentation only). Presentational\n * over the same {@link RealtimeSessionState} the thread renders.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-activity-rail',\n imports: [CommonModule, AngularSplitModule, ArtifactsModule],\n templateUrl: './realtime-activity-rail.component.html',\n styleUrl: './realtime-activity-rail.component.css'\n})\nexport class RealtimeActivityRailComponent implements OnInit, OnDestroy {\n /** Maximum characters of the result preview in a done card. */\n private static readonly PreviewMaxChars = 90;\n\n /** Shared live-session state, owned by the overlay shell. */\n @Input({ required: true }) State!: RealtimeSessionState;\n\n /** Whether developer affordances (\"Open run\" links) are revealed (gear-gated). */\n @Input() DevMode = false;\n\n /**\n * EMBEDDED mode: the rail renders as the content of the surface panel's Activity tab —\n * its own header/collapse chrome is hidden (the panel's tab strip owns collapse) and it\n * stretches to the pane's full width. Default `false` keeps the original standalone\n * right-rail presentation for any other consumer.\n */\n @Input() Embedded = false;\n\n /** The signed-in user, threaded to the split-pane artifact viewer. */\n @Input() CurrentUser: UserInfo | null = null;\n\n /** The active environment id, threaded to the split-pane artifact viewer. */\n @Input() EnvironmentID = '';\n\n /**\n * Extra artifacts NOT tied to a specific activity card — the SESSION-REVIEW chain's\n * carryover artifacts. Rendered as a \"Session artifacts\" group above the activity list so\n * a reviewed session's outputs are reachable inside the Activity tab (the live path gets\n * artifacts from each card's `Artifacts`). Empty for a live session.\n */\n @Input() ExtraArtifacts: ParsedDelegationArtifact[] = [];\n\n /** Emitted with the delegated run's ID when an entry's dev \"Open run\" link is clicked. */\n @Output() OpenRunRequested = new EventEmitter<string>();\n\n /** Emitted when an artifact is opened in the split viewer (lets a host react if it wants). */\n @Output() OpenArtifactRequested = new EventEmitter<ParsedDelegationArtifact>();\n\n /** Whether the rail is collapsed to its slim toggle strip (standalone mode only). */\n public Collapsed = false;\n\n /** The artifact currently shown in the split-pane viewer, or null when the split is closed. */\n public SelectedArtifact: ParsedDelegationArtifact | null = null;\n\n /** The artifact (right) pane's width percentage — persisted per-user, clamped on load. */\n public SplitArtifactPercent = ACTIVITY_SPLIT_DEFAULT_PERCENT;\n\n private changedSub?: Subscription;\n private cdr = inject(ChangeDetectorRef);\n\n /** True while reduced-motion is preferred — disables the split's drag transition. */\n public readonly PrefersReducedMotion =\n typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n ngOnInit(): void {\n this.loadSplitPref();\n this.changedSub = this.State.Changed$.subscribe(() => this.cdr.markForCheck());\n }\n\n ngOnDestroy(): void {\n this.changedSub?.unsubscribe();\n }\n\n /** Toggle the rail between expanded and slim-collapsed (standalone presentation). */\n public Toggle(): void {\n this.Collapsed = !this.Collapsed;\n }\n\n /** track fn for the @for over cards. */\n public TrackCard(index: number, card: RealtimeDelegationCardVM): string {\n return card.CallID;\n }\n\n /** Friendly label of the card's latest step. */\n public StepLabel(card: RealtimeDelegationCardVM): string {\n return FriendlyStepLabel(card.LatestStep, card.LatestMessage);\n }\n\n /** Elapsed duration for finished work (\"8s\", \"1m 04s\"); null while running (kept cheap). */\n public Elapsed(card: RealtimeDelegationCardVM): string | null {\n if (card.FinishedAt == null) {\n return null;\n }\n return FormatElapsed(card.FinishedAt - card.StartedAt);\n }\n\n /** True when the dev \"Open run\" link should render for this card (gear on + run id known). Suppressed for direct actions and narration. */\n public ShowOpenRun(card: RealtimeDelegationCardVM): boolean {\n return this.DevMode && card.Kind === 'agent' && !!card.RunID;\n }\n\n /** Emits the open-run request for the card's delegated run. */\n public OpenRun(card: RealtimeDelegationCardVM): void {\n if (card.RunID) {\n this.OpenRunRequested.emit(card.RunID);\n }\n }\n\n /** The artifacts a done card carries (empty array when none — keeps the template simple). */\n public CardArtifacts(card: RealtimeDelegationCardVM): ParsedDelegationArtifact[] {\n return card.Done && card.Artifacts ? card.Artifacts : [];\n }\n\n /** track fn for the @for over a card's artifacts. */\n public TrackArtifact(index: number, artifact: ParsedDelegationArtifact): string {\n return artifact.ArtifactVersionID;\n }\n\n /** Whether the artifact `a` is the one currently open in the split viewer. */\n public IsArtifactOpen(artifact: ParsedDelegationArtifact): boolean {\n return this.SelectedArtifact?.ArtifactVersionID === artifact.ArtifactVersionID;\n }\n\n /**\n * Opens (or swaps to) `artifact` in the split-pane viewer: the activity list keeps the\n * left pane, the full artifact viewer fills the right. Re-opening the same artifact is a\n * no-op; opening a different one swaps the right pane. Also reachable from the surface-tabs\n * \"View →\" affordance.\n */\n public OpenArtifact(artifact: ParsedDelegationArtifact): void {\n if (this.SelectedArtifact?.ArtifactVersionID === artifact.ArtifactVersionID) {\n return;\n }\n this.SelectedArtifact = artifact;\n this.OpenArtifactRequested.emit(artifact);\n this.cdr.markForCheck();\n }\n\n /** Closes the split, returning to a full-width activity list. */\n public CloseArtifact(): void {\n if (this.SelectedArtifact) {\n this.SelectedArtifact = null;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * `as-split` drag finished: adopt + persist the artifact (right) pane's width percentage\n * per-user (debounced, via {@link UserInfoEngine} — never localStorage). The split reports\n * the two area sizes (percent here); index 1 is the artifact pane. A wildcard `'*'` size\n * (non-numeric) is ignored — nothing to persist.\n */\n public OnSplitDragEnd(event: SplitGutterInteractionEvent): void {\n const right = event.sizes[1];\n if (typeof right !== 'number') {\n return;\n }\n this.SplitArtifactPercent = ClampActivitySplitPercent(right);\n this.persistSplitPref(this.SplitArtifactPercent);\n }\n\n /** One-line result preview for done items. */\n public Preview(card: RealtimeDelegationCardVM): string {\n const text = (card.Result || card.LatestMessage || '').replace(/\\s+/g, ' ').trim();\n const max = RealtimeActivityRailComponent.PreviewMaxChars;\n return text.length > max ? `${text.slice(0, max).trimEnd()}…` : text;\n }\n\n /** Reads the persisted split width once (tolerant; default tier applies when unset). */\n private loadSplitPref(): void {\n try {\n const percent = ParseActivitySplitPercent(UserInfoEngine.Instance.GetSetting(ACTIVITY_SPLIT_PREF_KEY));\n if (percent !== null) {\n this.SplitArtifactPercent = percent;\n }\n } catch {\n // UserInfoEngine not configured (plain-node tests / early bootstrap) — default applies.\n }\n }\n\n /** Persists the split width preference server-side (debounced, best-effort). */\n private persistSplitPref(percent: number): void {\n try {\n UserInfoEngine.Instance.SetSettingDebounced(ACTIVITY_SPLIT_PREF_KEY, SerializeActivitySplitPercent(percent));\n } catch {\n // engine unavailable — the width still applies for this session\n }\n }\n}\n","<aside class=\"rail\" [class.rail--collapsed]=\"Collapsed && !Embedded\" [class.rail--embedded]=\"Embedded\" aria-label=\"Session activity\">\n @if (!Embedded) {\n <div class=\"rail__head\">\n <button type=\"button\"\n class=\"rail__toggle\"\n (click)=\"Toggle()\"\n [title]=\"Collapsed ? 'Show session activity' : 'Hide session activity'\"\n [attr.aria-expanded]=\"!Collapsed\">\n <i class=\"fa-solid\" [ngClass]=\"Collapsed ? 'fa-chevron-left' : 'fa-chevron-right'\" aria-hidden=\"true\"></i>\n </button>\n @if (!Collapsed) {\n <span class=\"rail__title\">\n <i class=\"fa-solid fa-wave-square\" aria-hidden=\"true\"></i>\n Session activity\n </span>\n }\n </div>\n }\n\n @if (!Collapsed || Embedded) {\n <as-split class=\"rail__split\"\n direction=\"horizontal\"\n unit=\"percent\"\n [gutterSize]=\"SelectedArtifact ? 8 : 0\"\n [disabled]=\"!SelectedArtifact\"\n [useTransition]=\"!PrefersReducedMotion\"\n (dragEnd)=\"OnSplitDragEnd($event)\">\n\n <!-- LEFT: the activity list (full width until an artifact splits the pane) -->\n <as-split-area [size]=\"SelectedArtifact ? (100 - SplitArtifactPercent) : 100\">\n <div class=\"rail__list\">\n @if (ExtraArtifacts.length > 0) {\n <div class=\"rail__group\">\n <div class=\"rail__group-title\">\n <i class=\"fa-solid fa-folder-open\" aria-hidden=\"true\"></i> Session artifacts\n </div>\n @for (artifact of ExtraArtifacts; track TrackArtifact($index, artifact)) {\n <div class=\"act-card__artifact\"\n [class.act-card__artifact--open]=\"IsArtifactOpen(artifact)\">\n @if (CurrentUser) {\n <mj-artifact-message-card\n [artifactId]=\"artifact.ArtifactID\"\n [currentUser]=\"CurrentUser\"\n (actionPerformed)=\"OpenArtifact(artifact)\">\n </mj-artifact-message-card>\n } @else {\n <button type=\"button\" class=\"act-card__artifact-link\" (click)=\"OpenArtifact(artifact)\"\n [title]=\"'View ' + artifact.Name\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n <span>{{ artifact.Name }}</span>\n <i class=\"fa-solid fa-up-right-and-down-left-from-center\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n </div>\n }\n @for (card of State.Cards; track TrackCard($index, card)) {\n <div class=\"act-card\"\n [class.act-card--running]=\"!card.Done\"\n [class.act-card--done]=\"card.Done && card.Success\"\n [class.act-card--failed]=\"card.Done && !card.Success\">\n <div class=\"act-card__top\">\n <span class=\"act-card__name\">{{ card.AgentName }}</span>\n @if (!card.Done) {\n <span class=\"act-status act-status--running\">\n <i class=\"fa-solid fa-spinner spin\" aria-hidden=\"true\"></i> Running\n </span>\n } @else if (card.Success) {\n <span class=\"act-status act-status--done\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i> Done\n </span>\n } @else {\n <span class=\"act-status act-status--failed\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i> Failed\n </span>\n }\n </div>\n <div class=\"act-card__step\">{{ StepLabel(card) }}</div>\n @if (card.Done) {\n @if (Elapsed(card); as elapsed) {\n <div class=\"act-card__meta\">\n <i class=\"fa-regular fa-clock\" aria-hidden=\"true\"></i> {{ elapsed }}\n </div>\n }\n @if (Preview(card)) {\n <div class=\"act-card__preview\">{{ Preview(card) }}</div>\n }\n }\n @for (artifact of CardArtifacts(card); track TrackArtifact($index, artifact)) {\n <div class=\"act-card__artifact\"\n [class.act-card__artifact--open]=\"IsArtifactOpen(artifact)\">\n @if (CurrentUser) {\n <!-- Inline preview (same component the conversation message cards use);\n clicking expands it into the split-pane viewer on the right. -->\n <mj-artifact-message-card\n [artifactId]=\"artifact.ArtifactID\"\n [currentUser]=\"CurrentUser\"\n (actionPerformed)=\"OpenArtifact(artifact)\">\n </mj-artifact-message-card>\n } @else {\n <button type=\"button\" class=\"act-card__artifact-link\" (click)=\"OpenArtifact(artifact)\"\n [title]=\"'View ' + artifact.Name\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n <span>{{ artifact.Name }}</span>\n <i class=\"fa-solid fa-up-right-and-down-left-from-center\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n @if (ShowOpenRun(card)) {\n <button type=\"button\" class=\"act-card__dev-link\" (click)=\"OpenRun(card)\"\n title=\"Open the delegated agent run record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Open run</span>\n </button>\n }\n </div>\n } @empty {\n <div class=\"rail__empty\">Tool and agent calls will appear here as they run.</div>\n }\n </div>\n </as-split-area>\n\n <!-- RIGHT: the full artifact viewer (only present while an artifact is open) -->\n @if (SelectedArtifact; as artifact) {\n <as-split-area [size]=\"SplitArtifactPercent\" [minSize]=\"25\">\n <div class=\"rail__viewer\">\n <div class=\"rail__viewer-head\">\n <span class=\"rail__viewer-title\" [title]=\"artifact.Name\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n {{ artifact.Name }}\n </span>\n <button type=\"button\" class=\"rail__viewer-close\" (click)=\"CloseArtifact()\"\n title=\"Close artifact\" aria-label=\"Close artifact\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"rail__viewer-body\">\n <mj-artifact-viewer-panel\n [artifactId]=\"artifact.ArtifactID\"\n [currentUser]=\"CurrentUser!\"\n [environmentId]=\"EnvironmentID\"\n [showHeader]=\"false\"\n [showTabs]=\"false\"\n [showSaveToCollection]=\"false\"\n [showCloseButton]=\"false\"\n [showMaximizeButton]=\"false\">\n </mj-artifact-viewer-panel>\n </div>\n </div>\n </as-split-area>\n }\n </as-split>\n }\n</aside>\n"]}
1
+ {"version":3,"file":"realtime-activity-rail.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-activity-rail.component.ts","../../../../src/lib/components/realtime/realtime-activity-rail.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output, OnInit, OnDestroy, ChangeDetectorRef, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { AngularSplitModule, SplitGutterInteractionEvent } from 'angular-split';\nimport { UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { ArtifactsModule } from '@memberjunction/ng-artifacts';\nimport {\n RealtimeSessionState, RealtimeDelegationCardVM, FriendlyStepLabel, FormatElapsed\n} from './realtime-session-state';\nimport { ParsedDelegationArtifact } from '@memberjunction/realtime-runtime';\nimport {\n ACTIVITY_SPLIT_DEFAULT_PERCENT, ACTIVITY_SPLIT_PREF_KEY,\n ClampActivitySplitPercent, ParseActivitySplitPercent, SerializeActivitySplitPercent\n} from './realtime-surface-tab-style';\n\n/**\n * The \"Session activity\" surface (the Activity tab's content): a compact, newest-first list\n * of EVERY tool/agent call of the session — so parallel/multiple delegations live here and\n * the conversation thread stays clean.\n *\n * Each entry shows agent name, status, the latest friendly step label, elapsed time, and a\n * one-line result preview. When a run produced ARTIFACTS, each artifact renders as an inline\n * PREVIEW card (reusing `mj-artifact-message-card`, the same component the conversation\n * messages use). Clicking a preview SPLITS this pane horizontally — activity list on the\n * LEFT, the full artifact viewer on the RIGHT (`as-split`); clicking another swaps the right\n * pane; a close control collapses back to full-width activity. The split width is persisted\n * per-user via {@link UserInfoEngine} (NOT localStorage). This replaces the old \"one surface\n * tab per artifact\" model.\n *\n * Collapsible via the chevron in its header (standalone presentation only). Presentational\n * over the same {@link RealtimeSessionState} the thread renders.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-activity-rail',\n imports: [CommonModule, AngularSplitModule, ArtifactsModule],\n templateUrl: './realtime-activity-rail.component.html',\n styleUrl: './realtime-activity-rail.component.css'\n})\nexport class RealtimeActivityRailComponent implements OnInit, OnDestroy {\n /** Maximum characters of the result preview in a done card. */\n private static readonly PreviewMaxChars = 90;\n\n /** Shared live-session state, owned by the overlay shell. */\n @Input({ required: true }) State!: RealtimeSessionState;\n\n /** Whether developer affordances (\"Open run\" links) are revealed (gear-gated). */\n @Input() DevMode = false;\n\n /**\n * EMBEDDED mode: the rail renders as the content of the surface panel's Activity tab —\n * its own header/collapse chrome is hidden (the panel's tab strip owns collapse) and it\n * stretches to the pane's full width. Default `false` keeps the original standalone\n * right-rail presentation for any other consumer.\n */\n @Input() Embedded = false;\n\n /** The signed-in user, threaded to the split-pane artifact viewer. */\n @Input() CurrentUser: UserInfo | null = null;\n\n /** The active environment id, threaded to the split-pane artifact viewer. */\n @Input() EnvironmentID = '';\n\n /**\n * Extra artifacts NOT tied to a specific activity card — the SESSION-REVIEW chain's\n * carryover artifacts. Rendered as a \"Session artifacts\" group above the activity list so\n * a reviewed session's outputs are reachable inside the Activity tab (the live path gets\n * artifacts from each card's `Artifacts`). Empty for a live session.\n */\n @Input() ExtraArtifacts: ParsedDelegationArtifact[] = [];\n\n /** Emitted with the delegated run's ID when an entry's dev \"Open run\" link is clicked. */\n @Output() OpenRunRequested = new EventEmitter<string>();\n\n /** Emitted when an artifact is opened in the split viewer (lets a host react if it wants). */\n @Output() OpenArtifactRequested = new EventEmitter<ParsedDelegationArtifact>();\n\n /** Whether the rail is collapsed to its slim toggle strip (standalone mode only). */\n public Collapsed = false;\n\n /** The artifact currently shown in the split-pane viewer, or null when the split is closed. */\n public SelectedArtifact: ParsedDelegationArtifact | null = null;\n\n /** The artifact (right) pane's width percentage — persisted per-user, clamped on load. */\n public SplitArtifactPercent = ACTIVITY_SPLIT_DEFAULT_PERCENT;\n\n private changedSub?: Subscription;\n private cdr = inject(ChangeDetectorRef);\n\n /** True while reduced-motion is preferred — disables the split's drag transition. */\n public readonly PrefersReducedMotion =\n typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n ngOnInit(): void {\n this.loadSplitPref();\n this.changedSub = this.State.Changed$.subscribe(() => this.cdr.markForCheck());\n }\n\n ngOnDestroy(): void {\n this.changedSub?.unsubscribe();\n }\n\n /** Toggle the rail between expanded and slim-collapsed (standalone presentation). */\n public Toggle(): void {\n this.Collapsed = !this.Collapsed;\n }\n\n /** track fn for the @for over cards. */\n public TrackCard(index: number, card: RealtimeDelegationCardVM): string {\n return card.CallID;\n }\n\n /** Friendly label of the card's latest step. */\n public StepLabel(card: RealtimeDelegationCardVM): string {\n return FriendlyStepLabel(card.LatestStep, card.LatestMessage);\n }\n\n /** Elapsed duration for finished work (\"8s\", \"1m 04s\"); null while running (kept cheap). */\n public Elapsed(card: RealtimeDelegationCardVM): string | null {\n if (card.FinishedAt == null) {\n return null;\n }\n return FormatElapsed(card.FinishedAt - card.StartedAt);\n }\n\n /** True when the dev \"Open run\" link should render for this card (gear on + run id known). Suppressed for direct actions and narration. */\n public ShowOpenRun(card: RealtimeDelegationCardVM): boolean {\n return this.DevMode && card.Kind === 'agent' && !!card.RunID;\n }\n\n /** Emits the open-run request for the card's delegated run. */\n public OpenRun(card: RealtimeDelegationCardVM): void {\n if (card.RunID) {\n this.OpenRunRequested.emit(card.RunID);\n }\n }\n\n /** The artifacts a done card carries (empty array when none — keeps the template simple). */\n public CardArtifacts(card: RealtimeDelegationCardVM): ParsedDelegationArtifact[] {\n return card.Done && card.Artifacts ? card.Artifacts : [];\n }\n\n /** track fn for the @for over a card's artifacts. */\n public TrackArtifact(index: number, artifact: ParsedDelegationArtifact): string {\n return artifact.ArtifactVersionID;\n }\n\n /** Whether the artifact `a` is the one currently open in the split viewer. */\n public IsArtifactOpen(artifact: ParsedDelegationArtifact): boolean {\n return this.SelectedArtifact?.ArtifactVersionID === artifact.ArtifactVersionID;\n }\n\n /**\n * Opens (or swaps to) `artifact` in the split-pane viewer: the activity list keeps the\n * left pane, the full artifact viewer fills the right. Re-opening the same artifact is a\n * no-op; opening a different one swaps the right pane. Also reachable from the surface-tabs\n * \"View →\" affordance.\n */\n public OpenArtifact(artifact: ParsedDelegationArtifact): void {\n if (this.SelectedArtifact?.ArtifactVersionID === artifact.ArtifactVersionID) {\n return;\n }\n this.SelectedArtifact = artifact;\n this.OpenArtifactRequested.emit(artifact);\n this.cdr.markForCheck();\n }\n\n /** Closes the split, returning to a full-width activity list. */\n public CloseArtifact(): void {\n if (this.SelectedArtifact) {\n this.SelectedArtifact = null;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * `as-split` drag finished: adopt + persist the artifact (right) pane's width percentage\n * per-user (debounced, via {@link UserInfoEngine} — never localStorage). The split reports\n * the two area sizes (percent here); index 1 is the artifact pane. A wildcard `'*'` size\n * (non-numeric) is ignored — nothing to persist.\n */\n public OnSplitDragEnd(event: SplitGutterInteractionEvent): void {\n const right = event.sizes[1];\n if (typeof right !== 'number') {\n return;\n }\n this.SplitArtifactPercent = ClampActivitySplitPercent(right);\n this.persistSplitPref(this.SplitArtifactPercent);\n }\n\n /** One-line result preview for done items. */\n public Preview(card: RealtimeDelegationCardVM): string {\n const text = (card.Result || card.LatestMessage || '').replace(/\\s+/g, ' ').trim();\n const max = RealtimeActivityRailComponent.PreviewMaxChars;\n return text.length > max ? `${text.slice(0, max).trimEnd()}…` : text;\n }\n\n /** Reads the persisted split width once (tolerant; default tier applies when unset). */\n private loadSplitPref(): void {\n try {\n const percent = ParseActivitySplitPercent(UserInfoEngine.Instance.GetSetting(ACTIVITY_SPLIT_PREF_KEY));\n if (percent !== null) {\n this.SplitArtifactPercent = percent;\n }\n } catch {\n // UserInfoEngine not configured (plain-node tests / early bootstrap) — default applies.\n }\n }\n\n /** Persists the split width preference server-side (debounced, best-effort). */\n private persistSplitPref(percent: number): void {\n try {\n UserInfoEngine.Instance.SetSettingDebounced(ACTIVITY_SPLIT_PREF_KEY, SerializeActivitySplitPercent(percent));\n } catch {\n // engine unavailable — the width still applies for this session\n }\n }\n}\n","<aside class=\"rail\" [class.rail--collapsed]=\"Collapsed && !Embedded\" [class.rail--embedded]=\"Embedded\" aria-label=\"Session activity\">\n @if (!Embedded) {\n <div class=\"rail__head\">\n <button type=\"button\"\n class=\"rail__toggle\"\n (click)=\"Toggle()\"\n [title]=\"Collapsed ? 'Show session activity' : 'Hide session activity'\"\n [attr.aria-expanded]=\"!Collapsed\">\n <i class=\"fa-solid\" [ngClass]=\"Collapsed ? 'fa-chevron-left' : 'fa-chevron-right'\" aria-hidden=\"true\"></i>\n </button>\n @if (!Collapsed) {\n <span class=\"rail__title\">\n <i class=\"fa-solid fa-wave-square\" aria-hidden=\"true\"></i>\n Session activity\n </span>\n }\n </div>\n }\n\n @if (!Collapsed || Embedded) {\n <as-split class=\"rail__split\"\n direction=\"horizontal\"\n unit=\"percent\"\n [gutterSize]=\"SelectedArtifact ? 8 : 0\"\n [disabled]=\"!SelectedArtifact\"\n [useTransition]=\"!PrefersReducedMotion\"\n (dragEnd)=\"OnSplitDragEnd($event)\">\n\n <!-- LEFT: the activity list (full width until an artifact splits the pane) -->\n <as-split-area [size]=\"SelectedArtifact ? (100 - SplitArtifactPercent) : 100\">\n <div class=\"rail__list\">\n @if (ExtraArtifacts.length > 0) {\n <div class=\"rail__group\">\n <div class=\"rail__group-title\">\n <i class=\"fa-solid fa-folder-open\" aria-hidden=\"true\"></i> Session artifacts\n </div>\n @for (artifact of ExtraArtifacts; track TrackArtifact($index, artifact)) {\n <div class=\"act-card__artifact\"\n [class.act-card__artifact--open]=\"IsArtifactOpen(artifact)\">\n @if (CurrentUser) {\n <mj-artifact-message-card\n [artifactId]=\"artifact.ArtifactID\"\n [currentUser]=\"CurrentUser\"\n (actionPerformed)=\"OpenArtifact(artifact)\">\n </mj-artifact-message-card>\n } @else {\n <button type=\"button\" class=\"act-card__artifact-link\" (click)=\"OpenArtifact(artifact)\"\n [title]=\"'View ' + artifact.Name\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n <span>{{ artifact.Name }}</span>\n <i class=\"fa-solid fa-up-right-and-down-left-from-center\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n </div>\n }\n @for (card of State.Cards; track TrackCard($index, card)) {\n <div class=\"act-card\"\n [class.act-card--running]=\"!card.Done\"\n [class.act-card--done]=\"card.Done && card.Success\"\n [class.act-card--failed]=\"card.Done && !card.Success\">\n <div class=\"act-card__top\">\n <span class=\"act-card__name\">{{ card.AgentName }}</span>\n @if (!card.Done) {\n <span class=\"act-status act-status--running\">\n <i class=\"fa-solid fa-spinner spin\" aria-hidden=\"true\"></i> Running\n </span>\n } @else if (card.Success) {\n <span class=\"act-status act-status--done\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i> Done\n </span>\n } @else {\n <span class=\"act-status act-status--failed\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i> Failed\n </span>\n }\n </div>\n <div class=\"act-card__step\">{{ StepLabel(card) }}</div>\n @if (card.Done) {\n @if (Elapsed(card); as elapsed) {\n <div class=\"act-card__meta\">\n <i class=\"fa-regular fa-clock\" aria-hidden=\"true\"></i> {{ elapsed }}\n </div>\n }\n @if (Preview(card)) {\n <div class=\"act-card__preview\">{{ Preview(card) }}</div>\n }\n }\n @for (artifact of CardArtifacts(card); track TrackArtifact($index, artifact)) {\n <div class=\"act-card__artifact\"\n [class.act-card__artifact--open]=\"IsArtifactOpen(artifact)\">\n @if (CurrentUser) {\n <!-- Inline preview (same component the conversation message cards use);\n clicking expands it into the split-pane viewer on the right. -->\n <mj-artifact-message-card\n [artifactId]=\"artifact.ArtifactID\"\n [currentUser]=\"CurrentUser\"\n (actionPerformed)=\"OpenArtifact(artifact)\">\n </mj-artifact-message-card>\n } @else {\n <button type=\"button\" class=\"act-card__artifact-link\" (click)=\"OpenArtifact(artifact)\"\n [title]=\"'View ' + artifact.Name\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n <span>{{ artifact.Name }}</span>\n <i class=\"fa-solid fa-up-right-and-down-left-from-center\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n @if (ShowOpenRun(card)) {\n <button type=\"button\" class=\"act-card__dev-link\" (click)=\"OpenRun(card)\"\n title=\"Open the delegated agent run record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Open run</span>\n </button>\n }\n </div>\n } @empty {\n <div class=\"rail__empty\">Tool and agent calls will appear here as they run.</div>\n }\n </div>\n </as-split-area>\n\n <!-- RIGHT: the full artifact viewer (only present while an artifact is open) -->\n @if (SelectedArtifact; as artifact) {\n <as-split-area [size]=\"SplitArtifactPercent\" [minSize]=\"25\">\n <div class=\"rail__viewer\">\n <div class=\"rail__viewer-head\">\n <span class=\"rail__viewer-title\" [title]=\"artifact.Name\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n {{ artifact.Name }}\n </span>\n <button type=\"button\" class=\"rail__viewer-close\" (click)=\"CloseArtifact()\"\n title=\"Close artifact\" aria-label=\"Close artifact\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"rail__viewer-body\">\n <mj-artifact-viewer-panel\n [artifactId]=\"artifact.ArtifactID\"\n [currentUser]=\"CurrentUser!\"\n [environmentId]=\"EnvironmentID\"\n [showHeader]=\"false\"\n [showTabs]=\"false\"\n [showSaveToCollection]=\"false\"\n [showCloseButton]=\"false\"\n [showMaximizeButton]=\"false\">\n </mj-artifact-viewer-panel>\n </div>\n </div>\n </as-split-area>\n }\n </as-split>\n }\n</aside>\n"]}
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from '@angular/core';
2
- import { RealtimeConnectionState } from '../../services/realtime-session.service';
2
+ import { RealtimeConnectionState } from '@memberjunction/realtime-runtime';
3
3
  import { RealtimeUxDensity } from './realtime-disclosure';
4
4
  import * as i0 from "@angular/core";
5
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-agent-banner.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-agent-banner.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAA+B,MAAM,eAAe,CAAC;AAErF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;;AAE1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAOa,4BAA4B;IACvC,gFAAgF;IACrD,KAAK,EAAG,uBAAuB,CAAC;IAE3D;;;;;;;OAOG;IACM,OAAO,UAAS;IAEzB,wEAAwE;IAC/D,SAAS,SAAe;IAEjC;;;OAGG;IACM,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC,yFAAyF;IAChF,OAAO,UAAS;IAEzB,wFAAwF;IAC/E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC;;;;OAIG;IACM,UAAU,UAAS;IAE5B,wEAAwE;IAC/D,eAAe,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE7C,kFAAkF;IACzE,cAAc,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE5C,+GAA+G;IACtG,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAMjD,0FAA0F;IACjF,QAAQ,UAAS;IAE1B;;;;;OAKG;IACM,iBAAiB,UAAQ;IAElC,iEAAiE;IACxD,YAAY,UAAS;IAE9B,0FAA0F;IACjF,OAAO,EAAE,iBAAiB,CAAU;IAE7C,wFAAwF;IAC9E,oBAAoB,uBAA8B;IAE5D,2EAA2E;IACjE,cAAc,wBAA+B;IAEvD,4EAA4E;IAClE,cAAc,kCAAyC;IAEjE,2EAA2E;IACjE,iBAAiB,qBAA4B;IAEvD,qFAAqF;IAC3E,kBAAkB,qBAA4B;IAExD,sFAAsF;IAC5E,cAAc,qBAA4B;IAEpD,sEAAsE;IAC/D,QAAQ,UAAS;IAExB,qEAAqE;IACrE,SAAgB,SAAS,EAAE,aAAa,CAAC;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAKjF;IAEF,wFAAwF;IACxF,IAAW,eAAe,IAAI,OAAO,CAEpC;IAED,wEAAwE;IACjE,WAAW,IAAI,IAAI;IAM1B,6FAA6F;IACtF,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAK1C,iDAAiD;IAE1C,eAAe,IAAI,IAAI;IAM9B,mFAAmF;IAC5E,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAItD,4CAA4C;IACrC,SAAS,IAAI,IAAI;IAKxB,iGAAiG;IACjG,IAAW,gBAAgB,IAAI,MAAM,CASpC;IAED,oEAAoE;IACpE,IAAW,sBAAsB,IAAI,MAAM,CAQ1C;IAED,iFAAiF;IACjF,OAAO,CAAC,WAAW;IAQnB,kGAAkG;IAC3F,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU;IAQtF,qEAAqE;IAC9D,UAAU,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM;IAYzD,+EAA+E;IACxE,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO;yCA3L3C,4BAA4B;2CAA5B,4BAA4B;CA8LxC"}
1
+ {"version":3,"file":"realtime-agent-banner.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-agent-banner.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAA+B,MAAM,eAAe,CAAC;AAErF,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;;AAE1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAOa,4BAA4B;IACvC,gFAAgF;IACrD,KAAK,EAAG,uBAAuB,CAAC;IAE3D;;;;;;;OAOG;IACM,OAAO,UAAS;IAEzB,wEAAwE;IAC/D,SAAS,SAAe;IAEjC;;;OAGG;IACM,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC,yFAAyF;IAChF,OAAO,UAAS;IAEzB,wFAAwF;IAC/E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC;;;;OAIG;IACM,UAAU,UAAS;IAE5B,wEAAwE;IAC/D,eAAe,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE7C,kFAAkF;IACzE,cAAc,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE5C,+GAA+G;IACtG,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAMjD,0FAA0F;IACjF,QAAQ,UAAS;IAE1B;;;;;OAKG;IACM,iBAAiB,UAAQ;IAElC,iEAAiE;IACxD,YAAY,UAAS;IAE9B,0FAA0F;IACjF,OAAO,EAAE,iBAAiB,CAAU;IAE7C,wFAAwF;IAC9E,oBAAoB,uBAA8B;IAE5D,2EAA2E;IACjE,cAAc,wBAA+B;IAEvD,4EAA4E;IAClE,cAAc,kCAAyC;IAEjE,2EAA2E;IACjE,iBAAiB,qBAA4B;IAEvD,qFAAqF;IAC3E,kBAAkB,qBAA4B;IAExD,sFAAsF;IAC5E,cAAc,qBAA4B;IAEpD,sEAAsE;IAC/D,QAAQ,UAAS;IAExB,qEAAqE;IACrE,SAAgB,SAAS,EAAE,aAAa,CAAC;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAKjF;IAEF,wFAAwF;IACxF,IAAW,eAAe,IAAI,OAAO,CAEpC;IAED,wEAAwE;IACjE,WAAW,IAAI,IAAI;IAM1B,6FAA6F;IACtF,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAK1C,iDAAiD;IAE1C,eAAe,IAAI,IAAI;IAM9B,mFAAmF;IAC5E,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAItD,4CAA4C;IACrC,SAAS,IAAI,IAAI;IAKxB,iGAAiG;IACjG,IAAW,gBAAgB,IAAI,MAAM,CASpC;IAED,oEAAoE;IACpE,IAAW,sBAAsB,IAAI,MAAM,CAQ1C;IAED,iFAAiF;IACjF,OAAO,CAAC,WAAW;IAQnB,kGAAkG;IAC3F,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU;IAQtF,qEAAqE;IAC9D,UAAU,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM;IAYzD,+EAA+E;IACxE,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO;yCA3L3C,4BAA4B;2CAA5B,4BAA4B;CA8LxC"}