@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.
- package/esm/components/GenAIChat.d.ts.map +1 -1
- package/esm/components/GenAIChat.js +2 -2
- package/esm/components/GenAiStore.d.ts +9 -0
- package/esm/components/GenAiStore.d.ts.map +1 -1
- package/esm/components/GenAiStore.js +2 -1
- package/esm/components/intelligence/GenAiInteractionIntelligence.d.ts +21 -0
- package/esm/components/intelligence/GenAiInteractionIntelligence.d.ts.map +1 -0
- package/esm/components/intelligence/GenAiInteractionIntelligence.js +57 -0
- package/esm/components/intelligence/InteractionIntelligenceTrigger.d.ts +15 -0
- package/esm/components/intelligence/InteractionIntelligenceTrigger.d.ts.map +1 -0
- package/esm/components/intelligence/InteractionIntelligenceTrigger.js +19 -0
- package/esm/components/intelligence/data/categoryDetailRows.d.ts +12 -0
- package/esm/components/intelligence/data/categoryDetailRows.d.ts.map +1 -0
- package/esm/components/intelligence/data/categoryDetailRows.js +206 -0
- package/esm/components/intelligence/data/constants.d.ts +22 -0
- package/esm/components/intelligence/data/constants.d.ts.map +1 -0
- package/esm/components/intelligence/data/constants.js +27 -0
- package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.d.ts +23 -0
- package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.d.ts.map +1 -0
- package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.js +109 -0
- package/esm/components/intelligence/data/mergeDetailRows.d.ts +15 -0
- package/esm/components/intelligence/data/mergeDetailRows.d.ts.map +1 -0
- package/esm/components/intelligence/data/mergeDetailRows.js +91 -0
- package/esm/components/intelligence/data/timeline.d.ts +18 -0
- package/esm/components/intelligence/data/timeline.d.ts.map +1 -0
- package/esm/components/intelligence/data/timeline.js +40 -0
- package/esm/components/intelligence/data/types.d.ts +159 -0
- package/esm/components/intelligence/data/types.d.ts.map +1 -0
- package/esm/components/intelligence/data/types.js +2 -0
- package/esm/components/intelligence/data/useInteractionIntelligenceData.d.ts +9 -0
- package/esm/components/intelligence/data/useInteractionIntelligenceData.d.ts.map +1 -0
- package/esm/components/intelligence/data/useInteractionIntelligenceData.js +20 -0
- package/esm/components/intelligence/data/useInteractionIntelligenceTotals.d.ts +9 -0
- package/esm/components/intelligence/data/useInteractionIntelligenceTotals.d.ts.map +1 -0
- package/esm/components/intelligence/data/useInteractionIntelligenceTotals.js +20 -0
- package/esm/components/intelligence/detail/DetailRowValue.d.ts +10 -0
- package/esm/components/intelligence/detail/DetailRowValue.d.ts.map +1 -0
- package/esm/components/intelligence/detail/DetailRowValue.js +23 -0
- package/esm/components/intelligence/detail/IntelligenceCategoryDetail.d.ts +17 -0
- package/esm/components/intelligence/detail/IntelligenceCategoryDetail.d.ts.map +1 -0
- package/esm/components/intelligence/detail/IntelligenceCategoryDetail.js +21 -0
- package/esm/components/intelligence/detail/IntelligenceDetailHeader.d.ts +12 -0
- package/esm/components/intelligence/detail/IntelligenceDetailHeader.d.ts.map +1 -0
- package/esm/components/intelligence/detail/IntelligenceDetailHeader.js +19 -0
- package/esm/components/intelligence/detail/IntelligenceDetailRows.d.ts +11 -0
- package/esm/components/intelligence/detail/IntelligenceDetailRows.d.ts.map +1 -0
- package/esm/components/intelligence/detail/IntelligenceDetailRows.js +16 -0
- package/esm/components/intelligence/detail/IntelligenceStepCarousel.d.ts +12 -0
- package/esm/components/intelligence/detail/IntelligenceStepCarousel.d.ts.map +1 -0
- package/esm/components/intelligence/detail/IntelligenceStepCarousel.js +21 -0
- package/esm/components/intelligence/format/formatDuration.d.ts +23 -0
- package/esm/components/intelligence/format/formatDuration.d.ts.map +1 -0
- package/esm/components/intelligence/format/formatDuration.js +38 -0
- package/esm/components/intelligence/format/formatTokens.d.ts +8 -0
- package/esm/components/intelligence/format/formatTokens.d.ts.map +1 -0
- package/esm/components/intelligence/format/formatTokens.js +10 -0
- package/esm/components/intelligence/format/resolveMessage.d.ts +9 -0
- package/esm/components/intelligence/format/resolveMessage.d.ts.map +1 -0
- package/esm/components/intelligence/format/resolveMessage.js +10 -0
- package/esm/components/intelligence/intelligenceBem.d.ts +7 -0
- package/esm/components/intelligence/intelligenceBem.d.ts.map +1 -0
- package/esm/components/intelligence/intelligenceBem.js +8 -0
- package/esm/components/intelligence/panel/IconCircle.d.ts +10 -0
- package/esm/components/intelligence/panel/IconCircle.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IconCircle.js +12 -0
- package/esm/components/intelligence/panel/IntelligenceCategoryList.d.ts +13 -0
- package/esm/components/intelligence/panel/IntelligenceCategoryList.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IntelligenceCategoryList.js +10 -0
- package/esm/components/intelligence/panel/IntelligenceCategoryRow.d.ts +14 -0
- package/esm/components/intelligence/panel/IntelligenceCategoryRow.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IntelligenceCategoryRow.js +19 -0
- package/esm/components/intelligence/panel/IntelligenceDurationTokens.d.ts +12 -0
- package/esm/components/intelligence/panel/IntelligenceDurationTokens.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IntelligenceDurationTokens.js +19 -0
- package/esm/components/intelligence/panel/IntelligenceFooter.d.ts +10 -0
- package/esm/components/intelligence/panel/IntelligenceFooter.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IntelligenceFooter.js +20 -0
- package/esm/components/intelligence/panel/IntelligenceHeader.d.ts +8 -0
- package/esm/components/intelligence/panel/IntelligenceHeader.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IntelligenceHeader.js +15 -0
- package/esm/components/intelligence/panel/IntelligenceStepTooltip.d.ts +12 -0
- package/esm/components/intelligence/panel/IntelligenceStepTooltip.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IntelligenceStepTooltip.js +18 -0
- package/esm/components/intelligence/panel/IntelligenceTimeline.d.ts +15 -0
- package/esm/components/intelligence/panel/IntelligenceTimeline.d.ts.map +1 -0
- package/esm/components/intelligence/panel/IntelligenceTimeline.js +16 -0
- package/esm/components/intelligence/panel/TimelineBar.d.ts +19 -0
- package/esm/components/intelligence/panel/TimelineBar.d.ts.map +1 -0
- package/esm/components/intelligence/panel/TimelineBar.js +34 -0
- package/esm/components/messages/AssistantItem.d.ts.map +1 -1
- package/esm/components/messages/AssistantItem.js +15 -1
- package/esm/components/messages/AssistantItemFeedback.d.ts +6 -1
- package/esm/components/messages/AssistantItemFeedback.d.ts.map +1 -1
- package/esm/components/messages/AssistantItemFeedback.js +11 -4
- package/esm/hooks/useGenAIStore.d.ts +1 -0
- package/esm/hooks/useGenAIStore.d.ts.map +1 -1
- package/esm/hooks/useGenAIStore.js +3 -3
- package/esm/index.d.ts +2 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +2 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts +184 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-US.localization-bundle.js +184 -0
- package/esm/sdk-ui-gen-ai.d.ts +36 -0
- package/esm/store/chatWindow/chatWindowSelectors.d.ts +2 -0
- package/esm/store/chatWindow/chatWindowSelectors.d.ts.map +1 -1
- package/esm/store/chatWindow/chatWindowSelectors.js +5 -0
- package/esm/store/chatWindow/chatWindowSlice.d.ts +7 -1
- package/esm/store/chatWindow/chatWindowSlice.d.ts.map +1 -1
- package/esm/store/chatWindow/chatWindowSlice.js +3 -1
- package/esm/store/messages/messagesSelectors.d.ts +6 -0
- package/esm/store/messages/messagesSelectors.d.ts.map +1 -1
- package/esm/store/messages/messagesSelectors.js +9 -0
- package/esm/store/messages/messagesSlice.d.ts +11 -3
- package/esm/store/messages/messagesSlice.d.ts.map +1 -1
- package/esm/store/messages/messagesSlice.js +34 -1
- package/esm/store/sideEffects/onUserMessage.d.ts.map +1 -1
- package/esm/store/sideEffects/onUserMessage.js +40 -6
- package/esm/store/store.d.ts +1 -1
- package/esm/store/store.d.ts.map +1 -1
- package/esm/store/store.js +2 -2
- package/esm/types.d.ts +33 -1
- package/esm/types.d.ts.map +1 -1
- package/package.json +20 -20
- package/styles/css/intelligence.css +300 -0
- package/styles/css/intelligence.css.map +1 -0
- package/styles/css/main.css +304 -1
- package/styles/css/main.css.map +1 -1
- package/styles/css/messages.css +5 -1
- package/styles/css/messages.css.map +1 -1
- package/styles/scss/intelligence.scss +328 -0
- package/styles/scss/main.scss +1 -0
- 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,
|
|
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;
|
|
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"}
|