@gooddata/sdk-ui-gen-ai 11.52.0 → 11.53.0-alpha.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 (133) hide show
  1. package/esm/components/GenAIChat.d.ts.map +1 -1
  2. package/esm/components/GenAIChat.js +2 -2
  3. package/esm/components/GenAiStore.d.ts +9 -0
  4. package/esm/components/GenAiStore.d.ts.map +1 -1
  5. package/esm/components/GenAiStore.js +2 -1
  6. package/esm/components/intelligence/GenAiInteractionIntelligence.d.ts +21 -0
  7. package/esm/components/intelligence/GenAiInteractionIntelligence.d.ts.map +1 -0
  8. package/esm/components/intelligence/GenAiInteractionIntelligence.js +57 -0
  9. package/esm/components/intelligence/InteractionIntelligenceTrigger.d.ts +15 -0
  10. package/esm/components/intelligence/InteractionIntelligenceTrigger.d.ts.map +1 -0
  11. package/esm/components/intelligence/InteractionIntelligenceTrigger.js +19 -0
  12. package/esm/components/intelligence/data/categoryDetailRows.d.ts +12 -0
  13. package/esm/components/intelligence/data/categoryDetailRows.d.ts.map +1 -0
  14. package/esm/components/intelligence/data/categoryDetailRows.js +206 -0
  15. package/esm/components/intelligence/data/constants.d.ts +22 -0
  16. package/esm/components/intelligence/data/constants.d.ts.map +1 -0
  17. package/esm/components/intelligence/data/constants.js +27 -0
  18. package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.d.ts +23 -0
  19. package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.d.ts.map +1 -0
  20. package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.js +109 -0
  21. package/esm/components/intelligence/data/mergeDetailRows.d.ts +15 -0
  22. package/esm/components/intelligence/data/mergeDetailRows.d.ts.map +1 -0
  23. package/esm/components/intelligence/data/mergeDetailRows.js +91 -0
  24. package/esm/components/intelligence/data/timeline.d.ts +18 -0
  25. package/esm/components/intelligence/data/timeline.d.ts.map +1 -0
  26. package/esm/components/intelligence/data/timeline.js +40 -0
  27. package/esm/components/intelligence/data/types.d.ts +159 -0
  28. package/esm/components/intelligence/data/types.d.ts.map +1 -0
  29. package/esm/components/intelligence/data/types.js +2 -0
  30. package/esm/components/intelligence/data/useInteractionIntelligenceData.d.ts +9 -0
  31. package/esm/components/intelligence/data/useInteractionIntelligenceData.d.ts.map +1 -0
  32. package/esm/components/intelligence/data/useInteractionIntelligenceData.js +20 -0
  33. package/esm/components/intelligence/data/useInteractionIntelligenceTotals.d.ts +9 -0
  34. package/esm/components/intelligence/data/useInteractionIntelligenceTotals.d.ts.map +1 -0
  35. package/esm/components/intelligence/data/useInteractionIntelligenceTotals.js +20 -0
  36. package/esm/components/intelligence/detail/DetailRowValue.d.ts +10 -0
  37. package/esm/components/intelligence/detail/DetailRowValue.d.ts.map +1 -0
  38. package/esm/components/intelligence/detail/DetailRowValue.js +23 -0
  39. package/esm/components/intelligence/detail/IntelligenceCategoryDetail.d.ts +17 -0
  40. package/esm/components/intelligence/detail/IntelligenceCategoryDetail.d.ts.map +1 -0
  41. package/esm/components/intelligence/detail/IntelligenceCategoryDetail.js +21 -0
  42. package/esm/components/intelligence/detail/IntelligenceDetailHeader.d.ts +12 -0
  43. package/esm/components/intelligence/detail/IntelligenceDetailHeader.d.ts.map +1 -0
  44. package/esm/components/intelligence/detail/IntelligenceDetailHeader.js +19 -0
  45. package/esm/components/intelligence/detail/IntelligenceDetailRows.d.ts +11 -0
  46. package/esm/components/intelligence/detail/IntelligenceDetailRows.d.ts.map +1 -0
  47. package/esm/components/intelligence/detail/IntelligenceDetailRows.js +16 -0
  48. package/esm/components/intelligence/detail/IntelligenceStepCarousel.d.ts +12 -0
  49. package/esm/components/intelligence/detail/IntelligenceStepCarousel.d.ts.map +1 -0
  50. package/esm/components/intelligence/detail/IntelligenceStepCarousel.js +21 -0
  51. package/esm/components/intelligence/format/formatDuration.d.ts +23 -0
  52. package/esm/components/intelligence/format/formatDuration.d.ts.map +1 -0
  53. package/esm/components/intelligence/format/formatDuration.js +38 -0
  54. package/esm/components/intelligence/format/formatTokens.d.ts +8 -0
  55. package/esm/components/intelligence/format/formatTokens.d.ts.map +1 -0
  56. package/esm/components/intelligence/format/formatTokens.js +10 -0
  57. package/esm/components/intelligence/format/resolveMessage.d.ts +9 -0
  58. package/esm/components/intelligence/format/resolveMessage.d.ts.map +1 -0
  59. package/esm/components/intelligence/format/resolveMessage.js +10 -0
  60. package/esm/components/intelligence/intelligenceBem.d.ts +7 -0
  61. package/esm/components/intelligence/intelligenceBem.d.ts.map +1 -0
  62. package/esm/components/intelligence/intelligenceBem.js +8 -0
  63. package/esm/components/intelligence/panel/IconCircle.d.ts +10 -0
  64. package/esm/components/intelligence/panel/IconCircle.d.ts.map +1 -0
  65. package/esm/components/intelligence/panel/IconCircle.js +12 -0
  66. package/esm/components/intelligence/panel/IntelligenceCategoryList.d.ts +13 -0
  67. package/esm/components/intelligence/panel/IntelligenceCategoryList.d.ts.map +1 -0
  68. package/esm/components/intelligence/panel/IntelligenceCategoryList.js +10 -0
  69. package/esm/components/intelligence/panel/IntelligenceCategoryRow.d.ts +14 -0
  70. package/esm/components/intelligence/panel/IntelligenceCategoryRow.d.ts.map +1 -0
  71. package/esm/components/intelligence/panel/IntelligenceCategoryRow.js +19 -0
  72. package/esm/components/intelligence/panel/IntelligenceDurationTokens.d.ts +12 -0
  73. package/esm/components/intelligence/panel/IntelligenceDurationTokens.d.ts.map +1 -0
  74. package/esm/components/intelligence/panel/IntelligenceDurationTokens.js +19 -0
  75. package/esm/components/intelligence/panel/IntelligenceFooter.d.ts +10 -0
  76. package/esm/components/intelligence/panel/IntelligenceFooter.d.ts.map +1 -0
  77. package/esm/components/intelligence/panel/IntelligenceFooter.js +20 -0
  78. package/esm/components/intelligence/panel/IntelligenceHeader.d.ts +8 -0
  79. package/esm/components/intelligence/panel/IntelligenceHeader.d.ts.map +1 -0
  80. package/esm/components/intelligence/panel/IntelligenceHeader.js +15 -0
  81. package/esm/components/intelligence/panel/IntelligenceStepTooltip.d.ts +12 -0
  82. package/esm/components/intelligence/panel/IntelligenceStepTooltip.d.ts.map +1 -0
  83. package/esm/components/intelligence/panel/IntelligenceStepTooltip.js +18 -0
  84. package/esm/components/intelligence/panel/IntelligenceTimeline.d.ts +15 -0
  85. package/esm/components/intelligence/panel/IntelligenceTimeline.d.ts.map +1 -0
  86. package/esm/components/intelligence/panel/IntelligenceTimeline.js +16 -0
  87. package/esm/components/intelligence/panel/TimelineBar.d.ts +19 -0
  88. package/esm/components/intelligence/panel/TimelineBar.d.ts.map +1 -0
  89. package/esm/components/intelligence/panel/TimelineBar.js +34 -0
  90. package/esm/components/messages/AssistantItem.d.ts.map +1 -1
  91. package/esm/components/messages/AssistantItem.js +15 -1
  92. package/esm/components/messages/AssistantItemFeedback.d.ts +6 -1
  93. package/esm/components/messages/AssistantItemFeedback.d.ts.map +1 -1
  94. package/esm/components/messages/AssistantItemFeedback.js +11 -4
  95. package/esm/hooks/useGenAIStore.d.ts +1 -0
  96. package/esm/hooks/useGenAIStore.d.ts.map +1 -1
  97. package/esm/hooks/useGenAIStore.js +3 -3
  98. package/esm/index.d.ts +2 -0
  99. package/esm/index.d.ts.map +1 -1
  100. package/esm/index.js +2 -0
  101. package/esm/localization/bundles/en-US.localization-bundle.d.ts +184 -0
  102. package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  103. package/esm/localization/bundles/en-US.localization-bundle.js +184 -0
  104. package/esm/sdk-ui-gen-ai.d.ts +36 -0
  105. package/esm/store/chatWindow/chatWindowSelectors.d.ts +2 -0
  106. package/esm/store/chatWindow/chatWindowSelectors.d.ts.map +1 -1
  107. package/esm/store/chatWindow/chatWindowSelectors.js +5 -0
  108. package/esm/store/chatWindow/chatWindowSlice.d.ts +7 -1
  109. package/esm/store/chatWindow/chatWindowSlice.d.ts.map +1 -1
  110. package/esm/store/chatWindow/chatWindowSlice.js +3 -1
  111. package/esm/store/messages/messagesSelectors.d.ts +6 -0
  112. package/esm/store/messages/messagesSelectors.d.ts.map +1 -1
  113. package/esm/store/messages/messagesSelectors.js +9 -0
  114. package/esm/store/messages/messagesSlice.d.ts +11 -3
  115. package/esm/store/messages/messagesSlice.d.ts.map +1 -1
  116. package/esm/store/messages/messagesSlice.js +34 -1
  117. package/esm/store/sideEffects/onUserMessage.d.ts.map +1 -1
  118. package/esm/store/sideEffects/onUserMessage.js +40 -6
  119. package/esm/store/store.d.ts +1 -1
  120. package/esm/store/store.d.ts.map +1 -1
  121. package/esm/store/store.js +2 -2
  122. package/esm/types.d.ts +33 -1
  123. package/esm/types.d.ts.map +1 -1
  124. package/package.json +20 -20
  125. package/styles/css/intelligence.css +300 -0
  126. package/styles/css/intelligence.css.map +1 -0
  127. package/styles/css/main.css +304 -1
  128. package/styles/css/main.css.map +1 -1
  129. package/styles/css/messages.css +5 -1
  130. package/styles/css/messages.css.map +1 -1
  131. package/styles/scss/intelligence.scss +328 -0
  132. package/styles/scss/main.scss +1 -0
  133. package/styles/scss/messages.scss +10 -1
@@ -1 +1 @@
1
- {"version":3,"file":"GenAIChat.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChat.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAQ3C,OAAO,EAEH,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAExB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,GAAG;IAClE;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,CAAC;IAEvE;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;OAEG;IACH,8BAA8B,CAAC,EAAE,MAAM,aAAa,CAAC;IAErD;;OAEG;IACH,2BAA2B,CAAC,EAAE,MAAM,aAAa,GAAG,IAAI,CAAC;IAEzD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1B;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAmDxD;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,uBAAiB,CAAC"}
1
+ {"version":3,"file":"GenAIChat.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChat.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAQ3C,OAAO,EAEH,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAExB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,GAAG;IAClE;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,CAAC;IAEvE;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;OAEG;IACH,8BAA8B,CAAC,EAAE,MAAM,aAAa,CAAC;IAErD;;OAEG;IACH,2BAA2B,CAAC,EAAE,MAAM,aAAa,GAAG,IAAI,CAAC;IAEzD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1B;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAqDxD;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,uBAAiB,CAAC"}
@@ -12,10 +12,10 @@ import { GenAiStore } from "./GenAiStore.js";
12
12
  * @public
13
13
  */
14
14
  export function GenAIAssistant(props) {
15
- const { backend, workspace, locale, colorPalette, eventHandlers, settings, objectTypes, catalogItems, includeTags, excludeTags, isPreview, providedStore, onDispatcher, onLinkClick, mode, allowNativeLinks, } = props;
15
+ const { backend, workspace, locale, colorPalette, eventHandlers, settings, objectTypes, catalogItems, includeTags, excludeTags, isPreview, allowInteractionIntelligence, providedStore, onDispatcher, onLinkClick, mode, allowNativeLinks, } = props;
16
16
  const effectiveBackend = useBackendStrict(backend);
17
17
  const effectiveWorkspace = useWorkspaceStrict(workspace);
18
- return (_jsx(IntlWrapper, { locale: locale, children: _jsx(GenAiStore, { backend: effectiveBackend, workspace: effectiveWorkspace, onDispatcher: onDispatcher, colorPalette: colorPalette, mode: mode, eventHandlers: eventHandlers, allowNativeLinks: allowNativeLinks, onLinkClick: onLinkClick, settings: settings, objectTypes: objectTypes, includeTags: includeTags, excludeTags: excludeTags, catalogItems: catalogItems, isPreview: isPreview, providedStore: providedStore, children: _jsx(BackendProvider, { backend: effectiveBackend, children: _jsx(WorkspaceProvider, { workspace: effectiveWorkspace, children: _jsx(PermissionsProvider, { children: _jsx(GenAIContent, { ...props }) }) }) }) }) }));
18
+ return (_jsx(IntlWrapper, { locale: locale, children: _jsx(GenAiStore, { backend: effectiveBackend, workspace: effectiveWorkspace, onDispatcher: onDispatcher, colorPalette: colorPalette, mode: mode, eventHandlers: eventHandlers, allowNativeLinks: allowNativeLinks, onLinkClick: onLinkClick, settings: settings, objectTypes: objectTypes, includeTags: includeTags, excludeTags: excludeTags, catalogItems: catalogItems, isPreview: isPreview, allowInteractionIntelligence: allowInteractionIntelligence, providedStore: providedStore, children: _jsx(BackendProvider, { backend: effectiveBackend, children: _jsx(WorkspaceProvider, { workspace: effectiveWorkspace, children: _jsx(PermissionsProvider, { children: _jsx(GenAIContent, { ...props }) }) }) }) }) }));
19
19
  }
20
20
  /**
21
21
  * UI component that renders the Gen AI chat.
@@ -86,6 +86,15 @@ export type GenAiStoreProps = {
86
86
  * @internal
87
87
  */
88
88
  isPreview?: boolean;
89
+ /**
90
+ * Enables the Interaction Intelligence panel on assistant messages. Agent builder
91
+ * passes `true`; regular assistants leave this off. Also requires
92
+ * `settings.enableGenAiInteractionIntelligence` to be enabled — both must be true for the
93
+ * panel to be usable.
94
+ *
95
+ * @internal
96
+ */
97
+ allowInteractionIntelligence?: boolean;
89
98
  };
90
99
  /**
91
100
  * Provides the Gen AI store to the application.
@@ -1 +1 @@
1
- {"version":3,"file":"GenAiStore.d.ts","sourceRoot":"","sources":["../../src/components/GenAiStore.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAmC,MAAM,OAAO,CAAC;AAExE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGlE,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKjG,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAkB,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEpG;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAElC;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACnC;;OAEG;IACH,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;OAEG;IACH,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC7D;;OAEG;IACH,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,UAAU,EAAE,aAAa,KAAK,SAAS,CAAC,CAAC;IAEjE;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,kDAmDhD"}
1
+ {"version":3,"file":"GenAiStore.d.ts","sourceRoot":"","sources":["../../src/components/GenAiStore.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAmC,MAAM,OAAO,CAAC;AAExE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGlE,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKjG,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAkB,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEpG;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAElC;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACnC;;OAEG;IACH,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;OAEG;IACH,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC7D;;OAEG;IACH,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,UAAU,EAAE,aAAa,KAAK,SAAS,CAAC,CAAC;IAEjE;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;;OAOG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;CAC1C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,kDAmDhD"}
@@ -59,7 +59,7 @@ function InjectedStore({ onDispatcher, children, currentStore, }) {
59
59
  const content = typeof children === "function" ? children(currentStore) : children;
60
60
  return _jsx(StoreProvider, { store: currentStore, children: content });
61
61
  }
62
- function InternalStore({ backend, workspace, onDispatcher, children, eventHandlers, settings, catalogItems, includeTags, excludeTags, objectTypes, allowNativeLinks, onLinkClick, mode, isPreview, colorPalette, }) {
62
+ function InternalStore({ backend, workspace, onDispatcher, children, eventHandlers, settings, catalogItems, includeTags, excludeTags, objectTypes, allowNativeLinks, onLinkClick, mode, isPreview, allowInteractionIntelligence, colorPalette, }) {
63
63
  const effectiveBackend = useBackendStrict(backend);
64
64
  const effectiveWorkspace = useWorkspaceStrict(workspace);
65
65
  const genAIStore = useGenAIStore(effectiveBackend, effectiveWorkspace, {
@@ -71,6 +71,7 @@ function InternalStore({ backend, workspace, onDispatcher, children, eventHandle
71
71
  excludeTags,
72
72
  catalogItems,
73
73
  isPreview,
74
+ allowInteractionIntelligence,
74
75
  allowNativeLinks,
75
76
  onLinkClick,
76
77
  mode,
@@ -0,0 +1,21 @@
1
+ import type { InteractionIntelligenceMode } from "./data/types.js";
2
+ /**
3
+ * Props for the {@link GenAiInteractionIntelligence} component.
4
+ * @public
5
+ */
6
+ export interface IGenAiInteractionIntelligenceProps {
7
+ responseId: string;
8
+ onClose: () => void;
9
+ /** Lets a consumer render directly into a specific category's detail view. */
10
+ initialMode?: InteractionIntelligenceMode;
11
+ /** Category id to open when `initialMode === "detail"`. Falls back to list mode if unknown. */
12
+ initialCategory?: string;
13
+ }
14
+ /**
15
+ * The Interaction Intelligence panel: a single timeline of the processing steps behind one
16
+ * assistant response, with a list view and a per-category detail view. Loads its own data on
17
+ * mount and owns which view/category is currently shown.
18
+ * @public
19
+ */
20
+ export declare function GenAiInteractionIntelligence({ responseId, onClose, initialMode, initialCategory }: IGenAiInteractionIntelligenceProps): import("react/jsx-runtime").JSX.Element | null;
21
+ //# sourceMappingURL=GenAiInteractionIntelligence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenAiInteractionIntelligence.d.ts","sourceRoot":"","sources":["../../../src/components/intelligence/GenAiInteractionIntelligence.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAwB,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AASzF;;;GAGG;AACH,MAAM,WAAW,kCAAkC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,2BAA2B,CAAC;IAC1C,+FAA+F;IAC/F,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,EACzC,UAAU,EACV,OAAO,EACP,WAAoB,EACpB,eAAe,EAClB,EAAE,kCAAkC,kDAmEpC"}
@@ -0,0 +1,57 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { useSelector } from "react-redux";
5
+ import { interactionIntelligenceEnabledSelector } from "../../store/chatWindow/chatWindowSelectors.js";
6
+ import { useInteractionIntelligenceData } from "./data/useInteractionIntelligenceData.js";
7
+ import { IntelligenceCategoryDetail } from "./detail/IntelligenceCategoryDetail.js";
8
+ import { b } from "./intelligenceBem.js";
9
+ import { IntelligenceCategoryList } from "./panel/IntelligenceCategoryList.js";
10
+ import { IntelligenceFooter } from "./panel/IntelligenceFooter.js";
11
+ import { IntelligenceHeader } from "./panel/IntelligenceHeader.js";
12
+ import { IntelligenceTimeline } from "./panel/IntelligenceTimeline.js";
13
+ /**
14
+ * The Interaction Intelligence panel: a single timeline of the processing steps behind one
15
+ * assistant response, with a list view and a per-category detail view. Loads its own data on
16
+ * mount and owns which view/category is currently shown.
17
+ * @public
18
+ */
19
+ export function GenAiInteractionIntelligence({ responseId, onClose, initialMode = "list", initialCategory, }) {
20
+ // Self-gated on the feature flag/prop, not just by whoever mounts this component — it is a
21
+ // public export, so a caller other than AssistantItem must not be able to show it by omission.
22
+ const interactionIntelligenceEnabled = useSelector(interactionIntelligenceEnabledSelector);
23
+ const data = useInteractionIntelligenceData(responseId, interactionIntelligenceEnabled);
24
+ const [view, setView] = useState();
25
+ const [hoveredStepIndexes, setHoveredStepIndexes] = useState(undefined);
26
+ const panelRef = useRef(null);
27
+ // Mounted from AssistantItem the trace is already in the store, so this resolves on the first
28
+ // render. A consumer that mounts the panel while the response still streams gets it as soon as
29
+ // the trace lands instead, which is why the initial view is derived rather than seeded.
30
+ const resolvedView = view ??
31
+ (data
32
+ ? resolveInitialView(data.categories, initialMode, initialCategory)
33
+ : { mode: "list", categoryIndex: 0 });
34
+ const openCategory = useCallback((categoryIndex) => {
35
+ setView({ mode: "detail", categoryIndex });
36
+ }, []);
37
+ const backToList = useCallback(() => setView({ mode: "list", categoryIndex: 0 }), []);
38
+ const hasData = !!data;
39
+ // The panel opens below the message and the detail view is taller than the list, so both
40
+ // opening it and switching views can push its bottom out of the viewport. Scroll it back into
41
+ // view once it has something to show, and on every view change after that.
42
+ useEffect(() => {
43
+ panelRef.current?.scrollIntoView({ block: "nearest" });
44
+ }, [resolvedView.mode, hasData]);
45
+ if (!data) {
46
+ return null;
47
+ }
48
+ return (_jsx("div", { className: b(), ref: panelRef, children: resolvedView.mode === "detail" ? (_jsx(IntelligenceCategoryDetail, { data: data, categoryIndex: resolvedView.categoryIndex, onBack: backToList, onClose: onClose, onSelectCategory: openCategory })) : (_jsxs(_Fragment, { children: [
49
+ _jsx(IntelligenceHeader, { onClose: onClose }), _jsx(IntelligenceTimeline, { steps: data.steps, totalDurationMs: data.totals.durationMs, categories: data.categories, highlightedStepIndexes: hoveredStepIndexes }), _jsx(IntelligenceCategoryList, { categories: data.categories, onSelectCategory: openCategory, onHoveredStepIndexesChange: setHoveredStepIndexes }), data.traceId ? _jsx(IntelligenceFooter, { traceId: data.traceId }) : null] })) }));
50
+ }
51
+ /** Opens on `initialCategory`'s detail when asked for one that exists, else on the list. */
52
+ function resolveInitialView(categories, initialMode, initialCategory) {
53
+ const categoryIndex = categories.findIndex((category) => category.category === initialCategory);
54
+ return initialMode === "detail" && categoryIndex >= 0
55
+ ? { mode: "detail", categoryIndex }
56
+ : { mode: "list", categoryIndex: 0 };
57
+ }
@@ -0,0 +1,15 @@
1
+ import type { IInteractionIntelligenceTotals } from "./data/types.js";
2
+ export interface IInteractionIntelligenceTriggerProps {
3
+ /** The turn's duration/tokens, shown as the trigger's own content. Renders nothing until available. */
4
+ totals?: IInteractionIntelligenceTotals;
5
+ isOpen: boolean;
6
+ onToggle: () => void;
7
+ }
8
+ /**
9
+ * The Interaction Intelligence trigger shown next to an assistant message: the turn's
10
+ * duration/tokens, styled like the panel's own summary stats, acting as the clickable trigger.
11
+ * Renders nothing until `totals` is available. A plain toggle — it holds no state and renders no
12
+ * panel itself.
13
+ */
14
+ export declare function InteractionIntelligenceTrigger({ totals, isOpen, onToggle }: IInteractionIntelligenceTriggerProps): import("react/jsx-runtime").JSX.Element | null;
15
+ //# sourceMappingURL=InteractionIntelligenceTrigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InteractionIntelligenceTrigger.d.ts","sourceRoot":"","sources":["../../../src/components/intelligence/InteractionIntelligenceTrigger.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AAItE,MAAM,WAAW,oCAAoC;IACjD,uGAAuG;IACvG,MAAM,CAAC,EAAE,8BAA8B,CAAC;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,EAC3C,MAAM,EACN,MAAM,EACN,QAAQ,EACX,EAAE,oCAAoC,kDAoBtC"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { e } from "./intelligenceBem.js";
5
+ import { IntelligenceDurationTokens } from "./panel/IntelligenceDurationTokens.js";
6
+ /**
7
+ * The Interaction Intelligence trigger shown next to an assistant message: the turn's
8
+ * duration/tokens, styled like the panel's own summary stats, acting as the clickable trigger.
9
+ * Renders nothing until `totals` is available. A plain toggle — it holds no state and renders no
10
+ * panel itself.
11
+ */
12
+ export function InteractionIntelligenceTrigger({ totals, isOpen, onToggle, }) {
13
+ const intl = useIntl();
14
+ if (!totals) {
15
+ return null;
16
+ }
17
+ const label = intl.formatMessage({ id: "gd.gen-ai.interactionIntelligence.explain" });
18
+ return (_jsx("button", { type: "button", className: e("trigger"), onClick: onToggle, "aria-label": label, "aria-expanded": isOpen, children: _jsx(IntelligenceDurationTokens, { totals: totals }) }));
19
+ }
@@ -0,0 +1,12 @@
1
+ import type { IChatConversationItemDetail } from "@gooddata/sdk-backend-spi";
2
+ import type { IInteractionCategoryExcerptFragment, IInteractionStepDetailRow } from "./types.js";
3
+ /**
4
+ * The list row's right-hand excerpt for one occurrence of a category, built from the same
5
+ * `detail` its rows come from. At most two fragments (e.g. "2 found" + "1 used"). Counts are
6
+ * summed across a category's occurrences by the caller — this only reports one occurrence's own.
7
+ * @internal
8
+ */
9
+ export declare function excerptForDetail(detail: IChatConversationItemDetail): IInteractionCategoryExcerptFragment[];
10
+ /** The category's detail rows, built from one action's detail body. */
11
+ export declare function rowsForDetail(detail: IChatConversationItemDetail): IInteractionStepDetailRow[];
12
+ //# sourceMappingURL=categoryDetailRows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categoryDetailRows.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/categoryDetailRows.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAIR,2BAA2B,EAG9B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EACR,mCAAmC,EAEnC,yBAAyB,EAC5B,MAAM,YAAY,CAAC;AAsCpB;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,2BAA2B,GAAG,mCAAmC,EAAE,CAe3G;AA2CD,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,MAAM,EAAE,2BAA2B,GAAG,yBAAyB,EAAE,CAe9F"}
@@ -0,0 +1,206 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { defineMessages } from "react-intl";
3
+ import { MAX_DETAIL_LIST_ITEMS } from "./constants.js";
4
+ /** i18n message id per {@link GenAIAnswerOutput} value. */
5
+ const ANSWER_OUTPUT_LABEL_MESSAGES = defineMessages({
6
+ text: { id: "gd.gen-ai.interactionIntelligence.detail.output.text" },
7
+ visualization: { id: "gd.gen-ai.interactionIntelligence.detail.output.visualization" },
8
+ dashboard: { id: "gd.gen-ai.interactionIntelligence.detail.output.dashboard" },
9
+ keyDriverAnalysis: { id: "gd.gen-ai.interactionIntelligence.detail.output.keyDriverAnalysis" },
10
+ whatIf: { id: "gd.gen-ai.interactionIntelligence.detail.output.whatIf" },
11
+ searchResults: { id: "gd.gen-ai.interactionIntelligence.detail.output.searchResults" },
12
+ alertProposal: { id: "gd.gen-ai.interactionIntelligence.detail.output.alertProposal" },
13
+ });
14
+ /**
15
+ * Every message this file authors: the detail rows' labels, the count lines above their lists,
16
+ * the match-score suffix, and the excerpt fragments shown on a category's list row.
17
+ */
18
+ const MESSAGES = defineMessages({
19
+ query: { id: "gd.gen-ai.interactionIntelligence.detail.query" },
20
+ documents: { id: "gd.gen-ai.interactionIntelligence.detail.documents" },
21
+ bestMatch: { id: "gd.gen-ai.interactionIntelligence.detail.bestMatch" },
22
+ available: { id: "gd.gen-ai.interactionIntelligence.detail.available" },
23
+ activated: { id: "gd.gen-ai.interactionIntelligence.detail.activated" },
24
+ output: { id: "gd.gen-ai.interactionIntelligence.detail.output" },
25
+ model: { id: "gd.gen-ai.interactionIntelligence.detail.model" },
26
+ suggestedActions: { id: "gd.gen-ai.interactionIntelligence.detail.suggestedActions" },
27
+ searched: { id: "gd.gen-ai.interactionIntelligence.detail.searched" },
28
+ found: { id: "gd.gen-ai.interactionIntelligence.detail.found" },
29
+ used: { id: "gd.gen-ai.interactionIntelligence.detail.used" },
30
+ skillsCount: { id: "gd.gen-ai.interactionIntelligence.detail.skillsCount" },
31
+ foundGroup: { id: "gd.gen-ai.interactionIntelligence.detail.foundGroup" },
32
+ matchScore: { id: "gd.gen-ai.interactionIntelligence.detail.matchScore" },
33
+ excerptFound: { id: "gd.gen-ai.interactionIntelligence.excerpt.found" },
34
+ excerptUsed: { id: "gd.gen-ai.interactionIntelligence.excerpt.used" },
35
+ excerptDocuments: { id: "gd.gen-ai.interactionIntelligence.excerpt.documents" },
36
+ excerptActivated: { id: "gd.gen-ai.interactionIntelligence.excerpt.activated" },
37
+ });
38
+ /**
39
+ * The list row's right-hand excerpt for one occurrence of a category, built from the same
40
+ * `detail` its rows come from. At most two fragments (e.g. "2 found" + "1 used"). Counts are
41
+ * summed across a category's occurrences by the caller — this only reports one occurrence's own.
42
+ * @internal
43
+ */
44
+ export function excerptForDetail(detail) {
45
+ switch (detail.category) {
46
+ case "catalogSearch":
47
+ return catalogSearchExcerpt(detail);
48
+ case "knowledgeSearch":
49
+ return knowledgeSearchExcerpt(detail);
50
+ case "skillRouting":
51
+ return skillRoutingExcerpt(detail);
52
+ case "composeAnswer":
53
+ return composeAnswerExcerpt(detail);
54
+ // A category newer than this client contributes no excerpt rather than breaking the
55
+ // whole render model.
56
+ default:
57
+ return [];
58
+ }
59
+ }
60
+ function countFragment(id, count) {
61
+ return count > 0 ? [{ id, values: { count } }] : [];
62
+ }
63
+ function catalogSearchExcerpt(detail) {
64
+ const foundCount = detail.found.reduce((sum, group) => sum + group.titles.length, 0);
65
+ return [
66
+ ...countFragment(MESSAGES.excerptFound.id, foundCount),
67
+ ...countFragment(MESSAGES.excerptUsed.id, detail.used.length),
68
+ ];
69
+ }
70
+ function knowledgeSearchExcerpt(detail) {
71
+ return countFragment(MESSAGES.excerptDocuments.id, detail.documents.length);
72
+ }
73
+ function skillRoutingExcerpt(detail) {
74
+ return countFragment(MESSAGES.excerptActivated.id, detail.activated.length);
75
+ }
76
+ /**
77
+ * The message id for an output type, or `undefined` for one this client version does not know —
78
+ * a newer backend's value must degrade, not throw partway through building the render model.
79
+ */
80
+ function outputLabelId(output) {
81
+ return output ? ANSWER_OUTPUT_LABEL_MESSAGES[output]?.id : undefined;
82
+ }
83
+ function composeAnswerExcerpt(detail) {
84
+ const id = outputLabelId(detail.output);
85
+ return id ? [{ id }] : [];
86
+ }
87
+ /** The category's detail rows, built from one action's detail body. */
88
+ export function rowsForDetail(detail) {
89
+ switch (detail.category) {
90
+ case "catalogSearch":
91
+ return catalogSearchRows(detail);
92
+ case "knowledgeSearch":
93
+ return knowledgeSearchRows(detail);
94
+ case "skillRouting":
95
+ return skillRoutingRows(detail);
96
+ case "composeAnswer":
97
+ return composeAnswerRows(detail);
98
+ // A category newer than this client shows as a row with no detail content rather than
99
+ // breaking the whole render model.
100
+ default:
101
+ return [];
102
+ }
103
+ }
104
+ /**
105
+ * A row with a plain text value, or nothing when there is no text to show. `textId` is for a
106
+ * `text` drawn from a known/stable set (e.g. {@link ANSWER_OUTPUT_LABEL_MESSAGES}) — absent
107
+ * otherwise, when the text is never translated.
108
+ */
109
+ function textRow(labelId, text, textId) {
110
+ return text === undefined || text === ""
111
+ ? []
112
+ : [{ labelId, value: { kind: "text", text: String(text), textId } }];
113
+ }
114
+ /**
115
+ * A row listing `items`, truncated past {@link MAX_DETAIL_LIST_ITEMS}, or nothing when the list
116
+ * is empty. Without a `heading` the list renders unbulleted — the "plain stacked list" look used
117
+ * for match lists.
118
+ */
119
+ function listRow(labelId, items, heading) {
120
+ if (items.length === 0) {
121
+ return [];
122
+ }
123
+ return [
124
+ {
125
+ labelId,
126
+ value: {
127
+ kind: "list",
128
+ ...(heading === undefined
129
+ ? { bulleted: false }
130
+ : "id" in heading
131
+ ? { heading: heading.id, headingId: heading.id, headingValues: heading.values }
132
+ : { heading: heading.text }),
133
+ ...truncate(items),
134
+ },
135
+ },
136
+ ];
137
+ }
138
+ /** A relevance score as the card shows it, or no suffix when the action did not rank. */
139
+ function scoreMeta(score) {
140
+ return score === undefined
141
+ ? undefined
142
+ : { id: MESSAGES.matchScore.id, values: { percent: Math.round(score * 100) } };
143
+ }
144
+ function knowledgeSearchRows(detail) {
145
+ return [
146
+ ...textRow(MESSAGES.query.id, detail.query),
147
+ ...listRow(MESSAGES.documents.id, detail.documents.map((document) => ({ label: document.title, meta: scoreMeta(document.score) }))),
148
+ ...textRow(MESSAGES.bestMatch.id, detail.bestMatch),
149
+ ];
150
+ }
151
+ function skillRoutingRows(detail) {
152
+ const availableCount = detail.available.length;
153
+ return [
154
+ ...listRow(MESSAGES.available.id, detail.available.map((skill) => ({ label: skill })), { id: MESSAGES.skillsCount.id, values: { count: availableCount } }),
155
+ ...listRow(MESSAGES.activated.id, detail.activated.map((skill) => ({ label: skill }))),
156
+ ];
157
+ }
158
+ function composeAnswerRows(detail) {
159
+ return [
160
+ ...textRow(MESSAGES.output.id,
161
+ // `detail.output` is only shown verbatim if a future output type arrives with no
162
+ // matching message yet — never for an output type we already know.
163
+ detail.output, outputLabelId(detail.output)),
164
+ ...textRow(MESSAGES.model.id, detail.modelId),
165
+ ...textRow(MESSAGES.suggestedActions.id, detail.suggestedActions),
166
+ ];
167
+ }
168
+ function catalogSearchRows(detail) {
169
+ const found = detail.found.filter((group) => group.titles.length > 0);
170
+ return [
171
+ ...listRow(MESSAGES.query.id, detail.query.map((keyword) => ({ label: keyword }))),
172
+ ...listRow(MESSAGES.searched.id, detail.requestedTypes.map((type) => ({ label: type }))),
173
+ ...(found.length === 0
174
+ ? []
175
+ : [
176
+ {
177
+ labelId: MESSAGES.found.id,
178
+ value: {
179
+ kind: "groups",
180
+ // The count/type composition is translated; `objectType` (e.g. "metric")
181
+ // is a backend value, interpolated verbatim.
182
+ groups: found.map((group) => ({
183
+ heading: MESSAGES.foundGroup.id,
184
+ headingId: MESSAGES.foundGroup.id,
185
+ headingValues: {
186
+ count: group.titles.length,
187
+ objectType: group.objectType,
188
+ },
189
+ ...truncate(group.titles.map((title) => ({ label: title }))),
190
+ })),
191
+ },
192
+ },
193
+ ]),
194
+ ...listRow(MESSAGES.used.id, detail.used.map((match) => ({ label: match.title, meta: scoreMeta(match.score) }))),
195
+ ];
196
+ }
197
+ /** Caps a list at {@link MAX_DETAIL_LIST_ITEMS}, reporting the remainder as `truncatedCount`. */
198
+ function truncate(items) {
199
+ if (items.length <= MAX_DETAIL_LIST_ITEMS) {
200
+ return { items };
201
+ }
202
+ return {
203
+ items: items.slice(0, MAX_DETAIL_LIST_ITEMS),
204
+ truncatedCount: items.length - MAX_DETAIL_LIST_ITEMS,
205
+ };
206
+ }
@@ -0,0 +1,22 @@
1
+ import type { GenAIInteractionStepCategory } from "@gooddata/sdk-backend-spi";
2
+ import type { IconType } from "@gooddata/sdk-ui-kit";
3
+ /**
4
+ * Default icon shown for a category with no explicit mapping in {@link CATEGORY_ICONS}.
5
+ * @internal
6
+ */
7
+ export declare const DEFAULT_STEP_ICON: IconType;
8
+ /**
9
+ * Longest list rendered in a detail row before the rest collapse into a "…and N more". Applied
10
+ * both when a row is built and again after merging a category's occurrences.
11
+ * @internal
12
+ */
13
+ export declare const MAX_DETAIL_LIST_ITEMS = 5;
14
+ /**
15
+ * Category -> icon mapping. Typed by {@link GenAIInteractionStepCategory}, so adding a category to
16
+ * the backend's vocabulary fails to compile until its icon is chosen here. A category still
17
+ * missing at runtime (an older client meeting a newer backend) falls back to
18
+ * {@link DEFAULT_STEP_ICON}.
19
+ * @internal
20
+ */
21
+ export declare const CATEGORY_ICONS: Record<GenAIInteractionStepCategory, IconType>;
22
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/constants.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAyB,CAAC;AAE1D;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,4BAA4B,EAAE,QAAQ,CAOzE,CAAC"}
@@ -0,0 +1,27 @@
1
+ // (C) 2026 GoodData Corporation
2
+ /**
3
+ * Default icon shown for a category with no explicit mapping in {@link CATEGORY_ICONS}.
4
+ * @internal
5
+ */
6
+ export const DEFAULT_STEP_ICON = "questionMark";
7
+ /**
8
+ * Longest list rendered in a detail row before the rest collapse into a "…and N more". Applied
9
+ * both when a row is built and again after merging a category's occurrences.
10
+ * @internal
11
+ */
12
+ export const MAX_DETAIL_LIST_ITEMS = 5;
13
+ /**
14
+ * Category -> icon mapping. Typed by {@link GenAIInteractionStepCategory}, so adding a category to
15
+ * the backend's vocabulary fails to compile until its icon is chosen here. A category still
16
+ * missing at runtime (an older client meeting a newer backend) falls back to
17
+ * {@link DEFAULT_STEP_ICON}.
18
+ * @internal
19
+ */
20
+ export const CATEGORY_ICONS = {
21
+ applyMemory: "brain",
22
+ skillRouting: "genai2",
23
+ knowledgeSearch: "search",
24
+ catalogSearch: "search",
25
+ metricQuery: "metric",
26
+ composeAnswer: "speechBubble",
27
+ };
@@ -0,0 +1,23 @@
1
+ import type { IChatConversationResponseTrace } from "../../../types.js";
2
+ import type { IInteractionIntelligence, IInteractionIntelligenceTotals } from "./types.js";
3
+ /**
4
+ * Builds the render model for one response: a step carries timing/token spend but no category,
5
+ * the actions within it carry a category but no timing, and the two are joined here.
6
+ *
7
+ * Every action's category is kept, and time stays whole on the step's own tile — nothing is split
8
+ * or summed per category, so two categories highlighting the same tile is not double-counting. A
9
+ * category comes only from `detail.category`; an action without a `detail` yields no category row,
10
+ * though its step keeps its time regardless.
11
+ *
12
+ * A tile's `index` is its array position, not the backend's `stepIndex` — it is the highlight key.
13
+ * @internal
14
+ */
15
+ export declare function deriveInteractionIntelligenceFromSteps(responseId: string, trace: IChatConversationResponseTrace): IInteractionIntelligence;
16
+ /**
17
+ * The turn-level totals only, without resolving categories or building any detail rows — cheaper
18
+ * than {@link deriveInteractionIntelligenceFromSteps} for callers (e.g. the inline trigger) that
19
+ * only need the duration/token summary, and the single source of truth both callers share.
20
+ * @internal
21
+ */
22
+ export declare function deriveInteractionIntelligenceTotals(trace: IChatConversationResponseTrace): IInteractionIntelligenceTotals;
23
+ //# sourceMappingURL=deriveInteractionIntelligenceFromSteps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deriveInteractionIntelligenceFromSteps.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/deriveInteractionIntelligenceFromSteps.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,KAAK,EAIR,wBAAwB,EACxB,8BAA8B,EAEjC,MAAM,YAAY,CAAC;AAqBpB;;;;;;;;;;;GAWG;AACH,wBAAgB,sCAAsC,CAClD,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,8BAA8B,GACtC,wBAAwB,CAqD1B;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAC/C,KAAK,EAAE,8BAA8B,GACtC,8BAA8B,CAYhC"}
@@ -0,0 +1,109 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { defineMessages } from "react-intl";
3
+ import { excerptForDetail, rowsForDetail } from "./categoryDetailRows.js";
4
+ import { mergeDetailRows } from "./mergeDetailRows.js";
5
+ /**
6
+ * i18n message id per known category. Typed by {@link GenAIInteractionStepCategory}, so adding a
7
+ * category to the backend's vocabulary fails to compile until its label is authored here.
8
+ */
9
+ const CATEGORY_LABEL_MESSAGES = defineMessages({
10
+ applyMemory: { id: "gd.gen-ai.interactionIntelligence.category.applyMemory" },
11
+ catalogSearch: { id: "gd.gen-ai.interactionIntelligence.category.catalogSearch" },
12
+ knowledgeSearch: { id: "gd.gen-ai.interactionIntelligence.category.knowledgeSearch" },
13
+ skillRouting: { id: "gd.gen-ai.interactionIntelligence.category.skillRouting" },
14
+ metricQuery: { id: "gd.gen-ai.interactionIntelligence.category.metricQuery" },
15
+ composeAnswer: { id: "gd.gen-ai.interactionIntelligence.category.composeAnswer" },
16
+ });
17
+ /**
18
+ * Builds the render model for one response: a step carries timing/token spend but no category,
19
+ * the actions within it carry a category but no timing, and the two are joined here.
20
+ *
21
+ * Every action's category is kept, and time stays whole on the step's own tile — nothing is split
22
+ * or summed per category, so two categories highlighting the same tile is not double-counting. A
23
+ * category comes only from `detail.category`; an action without a `detail` yields no category row,
24
+ * though its step keeps its time regardless.
25
+ *
26
+ * A tile's `index` is its array position, not the backend's `stepIndex` — it is the highlight key.
27
+ * @internal
28
+ */
29
+ export function deriveInteractionIntelligenceFromSteps(responseId, trace) {
30
+ const sorted = [...trace.steps].sort((a, b) => a.stepIndex - b.stepIndex);
31
+ const byCategory = new Map();
32
+ const steps = sorted.map((step, index) => {
33
+ const actions = trace.detailsByStepId[step.stepId] ?? [];
34
+ const categoriesInStep = [];
35
+ for (const { detail } of actions) {
36
+ if (!detail) {
37
+ continue;
38
+ }
39
+ const { category } = detail;
40
+ if (!categoriesInStep.includes(category)) {
41
+ categoriesInStep.push(category);
42
+ }
43
+ const entry = byCategory.get(category) ?? { stepIndexes: [], details: [] };
44
+ byCategory.set(category, entry);
45
+ if (entry.stepIndexes.at(-1) !== index) {
46
+ entry.stepIndexes.push(index);
47
+ }
48
+ entry.details.push(detail);
49
+ }
50
+ return {
51
+ stepId: step.stepId,
52
+ index,
53
+ durationMs: step.durationMs,
54
+ tokens: step.tokens.total,
55
+ categories: categoriesInStep,
56
+ };
57
+ });
58
+ // Map insertion order already reflects each category's earliest step, since steps are
59
+ // walked in order above.
60
+ const categories = Array.from(byCategory.entries()).map(([category, entry]) => ({
61
+ category,
62
+ // Absent for a category newer than this client, which `resolveMessage` then renders as
63
+ // the raw category id rather than failing.
64
+ labelId: CATEGORY_LABEL_MESSAGES[category]?.id,
65
+ stepIndexes: entry.stepIndexes,
66
+ excerpt: excerptFor(entry.details),
67
+ detailRows: mergeDetailRows(entry.details.map(rowsForDetail)),
68
+ }));
69
+ return {
70
+ responseId,
71
+ totals: deriveInteractionIntelligenceTotals(trace),
72
+ steps,
73
+ categories,
74
+ traceId: trace.traceId,
75
+ };
76
+ }
77
+ /**
78
+ * The turn-level totals only, without resolving categories or building any detail rows — cheaper
79
+ * than {@link deriveInteractionIntelligenceFromSteps} for callers (e.g. the inline trigger) that
80
+ * only need the duration/token summary, and the single source of truth both callers share.
81
+ * @internal
82
+ */
83
+ export function deriveInteractionIntelligenceTotals(trace) {
84
+ const reported = trace.steps.filter((step) => step.tokens.total !== undefined);
85
+ return {
86
+ stepsCount: trace.steps.length,
87
+ durationMs: trace.steps.reduce((sum, step) => sum + step.durationMs, 0),
88
+ // Left undefined when no step reported a token total, so "unknown" never renders as "0".
89
+ tokens: reported.length === 0
90
+ ? undefined
91
+ : reported.reduce((sum, step) => sum + (step.tokens.total ?? 0), 0),
92
+ };
93
+ }
94
+ /**
95
+ * Merges a category's per-occurrence excerpt fragments by `id`, summing `count` values — so a
96
+ * category that ran across several steps shows one combined "5 found" rather than
97
+ * "2 found 3 found".
98
+ */
99
+ function excerptFor(details) {
100
+ const merged = new Map();
101
+ for (const fragment of details.flatMap(excerptForDetail)) {
102
+ const previousCount = merged.get(fragment.id)?.values?.["count"];
103
+ const count = fragment.values?.["count"];
104
+ merged.set(fragment.id, typeof previousCount === "number" && typeof count === "number"
105
+ ? { id: fragment.id, values: { ...fragment.values, count: previousCount + count } }
106
+ : fragment);
107
+ }
108
+ return merged.size === 0 ? undefined : { fragments: Array.from(merged.values()) };
109
+ }
@@ -0,0 +1,15 @@
1
+ import type { IInteractionStepDetailRow } from "./types.js";
2
+ /**
3
+ * Merges several occurrences' `detailRows` into one flat set for a category, grouping by
4
+ * `labelId`. A label appearing in only one occurrence keeps that row untouched. A label repeated
5
+ * across occurrences merges by value kind:
6
+ * - `list` rows concatenate `items` (and sum `truncatedCount`), keeping the first occurrence
7
+ * that authors a `heading`/`bulleted`.
8
+ * - `groups` rows concatenate the `groups` arrays across occurrences.
9
+ * - `text` rows become a plain, unheaded `list` of each occurrence's text as one item — the same
10
+ * "stacked plain list" look already used for single-occurrence match lists like "Used".
11
+ * - Mismatched kinds across occurrences fall back to the first occurrence's row.
12
+ * @internal
13
+ */
14
+ export declare function mergeDetailRows(rowGroups: IInteractionStepDetailRow[][]): IInteractionStepDetailRow[];
15
+ //# sourceMappingURL=mergeDetailRows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeDetailRows.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/mergeDetailRows.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA8B,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAExF;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,yBAAyB,EAAE,EAAE,GAAG,yBAAyB,EAAE,CAcrG"}