@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
@@ -0,0 +1,38 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { defineMessages } from "react-intl";
3
+ /**
4
+ * Splits a millisecond duration into minutes/seconds, keeping one decimal place of precision
5
+ * below a minute (0.2, 13.6), so a short step doesn't collapse to "0".
6
+ * @internal
7
+ */
8
+ export function computeDurationParts(ms) {
9
+ const totalSeconds = Math.max(ms, 0) / 1000;
10
+ if (totalSeconds < 60) {
11
+ const seconds = Math.round(totalSeconds * 10) / 10;
12
+ // Rounding can reach a full minute (59.95s -> 60.0), which must not render as "60s".
13
+ return seconds < 60 ? { minutes: 0, seconds } : { minutes: 1, seconds: 0 };
14
+ }
15
+ const minutes = Math.floor(totalSeconds / 60);
16
+ const seconds = Math.round(totalSeconds % 60);
17
+ // Same carry one level up: 119.5s rounds to 60 within the minute, so it becomes "2m".
18
+ return seconds < 60 ? { minutes, seconds } : { minutes: minutes + 1, seconds: 0 };
19
+ }
20
+ const messages = defineMessages({
21
+ seconds: { id: "gd.gen-ai.interactionIntelligence.duration.seconds" },
22
+ minutesAndSeconds: { id: "gd.gen-ai.interactionIntelligence.duration.minutesAndSeconds" },
23
+ minutes: { id: "gd.gen-ai.interactionIntelligence.duration.minutes" },
24
+ });
25
+ /**
26
+ * Formats a millisecond duration as a translated string, e.g. "0.2s", "13.6s", "1m 5s", "1m".
27
+ * @internal
28
+ */
29
+ export function formatDuration(intl, ms) {
30
+ const { minutes, seconds } = computeDurationParts(ms);
31
+ if (minutes === 0) {
32
+ return intl.formatMessage(messages.seconds, { seconds });
33
+ }
34
+ if (seconds === 0) {
35
+ return intl.formatMessage(messages.minutes, { minutes });
36
+ }
37
+ return intl.formatMessage(messages.minutesAndSeconds, { minutes, seconds });
38
+ }
@@ -0,0 +1,8 @@
1
+ import type { IntlShape } from "react-intl";
2
+ /**
3
+ * Formats a token count as a translated, locale-aware string, compacting large counts (e.g.
4
+ * "4K tokens" instead of "4,000 tokens") while keeping singular/plural driven by the real count.
5
+ * @internal
6
+ */
7
+ export declare function formatTokens(intl: IntlShape, count: number): string;
8
+ //# sourceMappingURL=formatTokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatTokens.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/format/formatTokens.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnE"}
@@ -0,0 +1,10 @@
1
+ // (C) 2026 GoodData Corporation
2
+ /**
3
+ * Formats a token count as a translated, locale-aware string, compacting large counts (e.g.
4
+ * "4K tokens" instead of "4,000 tokens") while keeping singular/plural driven by the real count.
5
+ * @internal
6
+ */
7
+ export function formatTokens(intl, count) {
8
+ const formattedCount = intl.formatNumber(count, { notation: "compact" });
9
+ return intl.formatMessage({ id: "gd.gen-ai.interactionIntelligence.summary.tokens" }, { count, formattedCount });
10
+ }
@@ -0,0 +1,9 @@
1
+ import type { IntlShape } from "react-intl";
2
+ /**
3
+ * Resolves an authored label/value: translates `id` when present, falling back to the verbatim
4
+ * authored text otherwise. Shared by every `xxxId ?? xxx` field in the Interaction Intelligence
5
+ * render model (step/category labels, row labels, list headings, text values).
6
+ * @internal
7
+ */
8
+ export declare function resolveMessage(intl: IntlShape, id: string | undefined, fallback: string, values?: Record<string, string | number>): string;
9
+ //# sourceMappingURL=resolveMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/format/resolveMessage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,cAAc,CAC1B,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GACzC,MAAM,CAER"}
@@ -0,0 +1,10 @@
1
+ // (C) 2026 GoodData Corporation
2
+ /**
3
+ * Resolves an authored label/value: translates `id` when present, falling back to the verbatim
4
+ * authored text otherwise. Shared by every `xxxId ?? xxx` field in the Interaction Intelligence
5
+ * render model (step/category labels, row labels, list headings, text values).
6
+ * @internal
7
+ */
8
+ export function resolveMessage(intl, id, fallback, values) {
9
+ return id ? intl.formatMessage({ id }, values) : fallback;
10
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared BEM class name helper for every Interaction Intelligence component, scoped to the
3
+ * `gd-gen-ai-chat__interaction-intelligence` block.
4
+ * @internal
5
+ */
6
+ export declare const b: (props?: import("@gooddata/sdk-ui-kit").StyleProps | undefined) => string, e: (element: string, props?: import("@gooddata/sdk-ui-kit").StyleProps | undefined) => string;
7
+ //# sourceMappingURL=intelligenceBem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intelligenceBem.d.ts","sourceRoot":"","sources":["../../../src/components/intelligence/intelligenceBem.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAQ,CAAC,6EAAE,CAAC,4FAA2D,CAAC"}
@@ -0,0 +1,8 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { bemFactory } from "@gooddata/sdk-ui-kit";
3
+ /**
4
+ * Shared BEM class name helper for every Interaction Intelligence component, scoped to the
5
+ * `gd-gen-ai-chat__interaction-intelligence` block.
6
+ * @internal
7
+ */
8
+ export const { b, e } = bemFactory("gd-gen-ai-chat__interaction-intelligence");
@@ -0,0 +1,10 @@
1
+ import type { GenAIInteractionStepCategory } from "@gooddata/sdk-backend-spi";
2
+ export interface IIconCircleProps {
3
+ category: GenAIInteractionStepCategory;
4
+ }
5
+ /**
6
+ * Circular chip showing the icon for a category, falling back to a default icon for a category
7
+ * missing from {@link CATEGORY_ICONS} at runtime (an older client meeting a newer backend).
8
+ */
9
+ export declare function IconCircle({ category }: IIconCircleProps): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=IconCircle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IconCircle.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IconCircle.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAM9E,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,4BAA4B,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CAaxD"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { UiIcon } from "@gooddata/sdk-ui-kit";
3
+ import { CATEGORY_ICONS, DEFAULT_STEP_ICON } from "../data/constants.js";
4
+ import { e } from "../intelligenceBem.js";
5
+ /**
6
+ * Circular chip showing the icon for a category, falling back to a default icon for a category
7
+ * missing from {@link CATEGORY_ICONS} at runtime (an older client meeting a newer backend).
8
+ */
9
+ export function IconCircle({ category }) {
10
+ const icon = CATEGORY_ICONS[category] ?? DEFAULT_STEP_ICON;
11
+ return (_jsx("div", { className: e("icon-circle"), children: _jsx(UiIcon, { type: icon, size: 14, color: "complementary-7", accessibilityConfig: { ariaHidden: true } }) }));
12
+ }
@@ -0,0 +1,13 @@
1
+ import type { IInteractionCategory } from "../data/types.js";
2
+ export interface IIntelligenceCategoryListProps {
3
+ categories: IInteractionCategory[];
4
+ onSelectCategory: (index: number) => void;
5
+ /** Lifts the hovered category's step indexes so the sibling timeline can highlight them. */
6
+ onHoveredStepIndexesChange: (stepIndexes: number[] | undefined) => void;
7
+ }
8
+ /**
9
+ * The list of category rows. Hovering a row reports its step indexes up so the timeline above
10
+ * can highlight the tiles where that category occurred — the list itself renders no timeline.
11
+ */
12
+ export declare function IntelligenceCategoryList({ categories, onSelectCategory, onHoveredStepIndexesChange }: IIntelligenceCategoryListProps): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=IntelligenceCategoryList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntelligenceCategoryList.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceCategoryList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAK7D,MAAM,WAAW,8BAA8B;IAC3C,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,4FAA4F;IAC5F,0BAA0B,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,KAAK,IAAI,CAAC;CAC3E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,EACrC,UAAU,EACV,gBAAgB,EAChB,0BAA0B,EAC7B,EAAE,8BAA8B,2CAehC"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { e } from "../intelligenceBem.js";
3
+ import { IntelligenceCategoryRow } from "./IntelligenceCategoryRow.js";
4
+ /**
5
+ * The list of category rows. Hovering a row reports its step indexes up so the timeline above
6
+ * can highlight the tiles where that category occurred — the list itself renders no timeline.
7
+ */
8
+ export function IntelligenceCategoryList({ categories, onSelectCategory, onHoveredStepIndexesChange, }) {
9
+ return (_jsx("div", { className: e("category-list"), children: categories.map((category, index) => (_jsx(IntelligenceCategoryRow, { category: category, onSelect: () => onSelectCategory(index), onHoverChange: (isHovered) => onHoveredStepIndexesChange(isHovered ? category.stepIndexes : undefined) }, category.category))) }));
10
+ }
@@ -0,0 +1,14 @@
1
+ import type { IInteractionCategory } from "../data/types.js";
2
+ export interface IIntelligenceCategoryRowProps {
3
+ category: IInteractionCategory;
4
+ onSelect: () => void;
5
+ onHoverChange: (isHovered: boolean) => void;
6
+ }
7
+ /**
8
+ * One list row: the category's icon, its label, a content excerpt on the right (never a
9
+ * duration — that figure was always a fabricated per-category aggregate), and a chevron to open
10
+ * its detail view. Reports its own hover state up so the shared timeline can highlight the
11
+ * steps this category occurred in.
12
+ */
13
+ export declare function IntelligenceCategoryRow({ category, onSelect, onHoverChange }: IIntelligenceCategoryRowProps): import("react/jsx-runtime").JSX.Element;
14
+ //# sourceMappingURL=IntelligenceCategoryRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntelligenceCategoryRow.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceCategoryRow.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,WAAW,6BAA6B;IAC1C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACpC,QAAQ,EACR,QAAQ,EACR,aAAa,EAChB,EAAE,6BAA6B,2CAgC/B"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { UiIcon } from "@gooddata/sdk-ui-kit";
5
+ import { resolveMessage } from "../format/resolveMessage.js";
6
+ import { e } from "../intelligenceBem.js";
7
+ import { IconCircle } from "./IconCircle.js";
8
+ /**
9
+ * One list row: the category's icon, its label, a content excerpt on the right (never a
10
+ * duration — that figure was always a fabricated per-category aggregate), and a chevron to open
11
+ * its detail view. Reports its own hover state up so the shared timeline can highlight the
12
+ * steps this category occurred in.
13
+ */
14
+ export function IntelligenceCategoryRow({ category, onSelect, onHoverChange, }) {
15
+ const intl = useIntl();
16
+ return (_jsxs("button", { type: "button", className: e("category-row"), onClick: onSelect, onMouseEnter: () => onHoverChange(true), onMouseLeave: () => onHoverChange(false), onFocus: () => onHoverChange(true), onBlur: () => onHoverChange(false), children: [
17
+ _jsx(IconCircle, { category: category.category }), _jsx("span", { className: e("category-row__label"), children: resolveMessage(intl, category.labelId, category.category) }), category.excerpt ? (_jsx("span", { className: e("category-row__excerpt"), children: category.excerpt.fragments.map((fragment, index) => (_jsx("span", { children: intl.formatMessage({ id: fragment.id }, fragment.values) }, index))) })) : null, _jsx(UiIcon, { type: "navigateRight", size: 16, color: "complementary-6", accessibilityConfig: { ariaHidden: true } })
18
+ ] }));
19
+ }
@@ -0,0 +1,12 @@
1
+ import type { IInteractionIntelligenceTotals } from "../data/types.js";
2
+ export interface IIntelligenceDurationTokensProps {
3
+ totals: Pick<IInteractionIntelligenceTotals, "durationMs" | "tokens">;
4
+ /** The trigger shows a dimmed "/" between the two figures; the timeline tooltip omits it. */
5
+ showSlash?: boolean;
6
+ }
7
+ /**
8
+ * The "{duration} / {tokens}" fragment shown by the inline Interaction Intelligence trigger,
9
+ * omitting the tokens segment when `tokens` is unknown.
10
+ */
11
+ export declare function IntelligenceDurationTokens({ totals, showSlash }: IIntelligenceDurationTokensProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=IntelligenceDurationTokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntelligenceDurationTokens.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceDurationTokens.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAKvE,MAAM,WAAW,gCAAgC;IAC7C,MAAM,EAAE,IAAI,CAAC,8BAA8B,EAAE,YAAY,GAAG,QAAQ,CAAC,CAAC;IACtE,6FAA6F;IAC7F,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,MAAM,EAAE,SAAgB,EAAE,EAAE,gCAAgC,2CAcxG"}
@@ -0,0 +1,19 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { formatDuration } from "../format/formatDuration.js";
5
+ import { formatTokens } from "../format/formatTokens.js";
6
+ import { e } from "../intelligenceBem.js";
7
+ /**
8
+ * The "{duration} / {tokens}" fragment shown by the inline Interaction Intelligence trigger,
9
+ * omitting the tokens segment when `tokens` is unknown.
10
+ */
11
+ export function IntelligenceDurationTokens({ totals, showSlash = true }) {
12
+ const intl = useIntl();
13
+ if (totals.tokens === undefined) {
14
+ return _jsx("span", { children: formatDuration(intl, totals.durationMs) });
15
+ }
16
+ return (_jsxs(_Fragment, { children: [
17
+ _jsx("span", { children: formatDuration(intl, totals.durationMs) }), " ", showSlash ? _jsx("span", { className: e("duration-tokens__separator"), children: "/ " }) : null, _jsx("span", { children: formatTokens(intl, totals.tokens) })
18
+ ] }));
19
+ }
@@ -0,0 +1,10 @@
1
+ export interface IIntelligenceFooterProps {
2
+ traceId: string;
3
+ }
4
+ /**
5
+ * The panel's footer: the response's backend trace id. The "Trace ID:" label is the tooltip
6
+ * trigger, explaining what it is for; the id itself is plain text. Renders nothing when there
7
+ * is no trace id to show.
8
+ */
9
+ export declare function IntelligenceFooter({ traceId }: IIntelligenceFooterProps): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=IntelligenceFooter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntelligenceFooter.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceFooter.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,wBAAwB;IACrC,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,EAAE,wBAAwB,2CAuBvE"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { UiTooltip } from "@gooddata/sdk-ui-kit";
5
+ import { e } from "../intelligenceBem.js";
6
+ /**
7
+ * The panel's footer: the response's backend trace id. The "Trace ID:" label is the tooltip
8
+ * trigger, explaining what it is for; the id itself is plain text. Renders nothing when there
9
+ * is no trace id to show.
10
+ */
11
+ export function IntelligenceFooter({ traceId }) {
12
+ const intl = useIntl();
13
+ const tooltipText = intl.formatMessage({
14
+ id: "gd.gen-ai.interactionIntelligence.footer.traceId.tooltip",
15
+ });
16
+ const label = intl.formatMessage({ id: "gd.gen-ai.interactionIntelligence.footer.traceId.label" });
17
+ return (_jsxs("div", { className: e("footer"), children: [
18
+ _jsx(UiTooltip, { triggerBy: ["hover", "focus"], arrowPlacement: "top", width: 260, anchor: _jsx("span", { className: e("footer__hint"), tabIndex: 0, children: label }), content: tooltipText }), _jsx("span", { className: e("footer__trace-id"), children: traceId })
19
+ ] }));
20
+ }
@@ -0,0 +1,8 @@
1
+ export interface IIntelligenceHeaderProps {
2
+ onClose: () => void;
3
+ }
4
+ /**
5
+ * The panel's list-mode header: the "Interaction Intelligence" title and a close button.
6
+ */
7
+ export declare function IntelligenceHeader({ onClose }: IIntelligenceHeaderProps): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=IntelligenceHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntelligenceHeader.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceHeader.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,wBAAwB;IACrC,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,EAAE,wBAAwB,2CAkBvE"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { UiIconButton } from "@gooddata/sdk-ui-kit";
5
+ import { e } from "../intelligenceBem.js";
6
+ /**
7
+ * The panel's list-mode header: the "Interaction Intelligence" title and a close button.
8
+ */
9
+ export function IntelligenceHeader({ onClose }) {
10
+ const intl = useIntl();
11
+ const closeLabel = intl.formatMessage({ id: "gd.gen-ai.interactionIntelligence.close" });
12
+ return (_jsxs("div", { className: e("header"), children: [
13
+ _jsx("span", { className: e("header__title"), children: intl.formatMessage({ id: "gd.gen-ai.interactionIntelligence.title" }) }), _jsx(UiIconButton, { icon: "cross", variant: "tertiary", size: "medium", onClick: onClose, accessibilityConfig: { ariaLabel: closeLabel } })
14
+ ] }));
15
+ }
@@ -0,0 +1,12 @@
1
+ import type { IInteractionCategory, IInteractionStepTile } from "../data/types.js";
2
+ export interface IIntelligenceStepTooltipProps {
3
+ step: IInteractionStepTile;
4
+ /** All of the turn's categories, to resolve the step's category ids to display labels. */
5
+ categories: IInteractionCategory[];
6
+ }
7
+ /**
8
+ * The hover tooltip for one timeline tile: an "ACTIVITY" eyebrow with the categories that ran
9
+ * within the step (omitted when it ran none), a divider, and the step's own duration/tokens.
10
+ */
11
+ export declare function IntelligenceStepTooltip({ step, categories }: IIntelligenceStepTooltipProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=IntelligenceStepTooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntelligenceStepTooltip.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceStepTooltip.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAMnF,MAAM,WAAW,6BAA6B;IAC1C,IAAI,EAAE,oBAAoB,CAAC;IAC3B,0FAA0F;IAC1F,UAAU,EAAE,oBAAoB,EAAE,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,6BAA6B,2CA0B1F"}
@@ -0,0 +1,18 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { resolveMessage } from "../format/resolveMessage.js";
5
+ import { e } from "../intelligenceBem.js";
6
+ import { IntelligenceDurationTokens } from "./IntelligenceDurationTokens.js";
7
+ /**
8
+ * The hover tooltip for one timeline tile: an "ACTIVITY" eyebrow with the categories that ran
9
+ * within the step (omitted when it ran none), a divider, and the step's own duration/tokens.
10
+ */
11
+ export function IntelligenceStepTooltip({ step, categories }) {
12
+ const intl = useIntl();
13
+ const labelIdByCategory = new Map(categories.map((category) => [category.category, category.labelId]));
14
+ return (_jsxs("div", { className: e("step-tooltip"), children: [step.categories.length > 0 ? (_jsxs(_Fragment, { children: [
15
+ _jsx("div", { className: e("step-tooltip__eyebrow"), children: intl.formatMessage({ id: "gd.gen-ai.interactionIntelligence.tooltip.activity" }) }), _jsx("div", { className: e("step-tooltip__activity-list"), children: step.categories.map((category) => (_jsx("div", { children: resolveMessage(intl, labelIdByCategory.get(category), category) }, category))) }), _jsx("div", { className: e("step-tooltip__divider") })
16
+ ] })) : null, _jsx("div", { className: e("step-tooltip__footer"), children: _jsx(IntelligenceDurationTokens, { totals: step, showSlash: false }) })
17
+ ] }));
18
+ }
@@ -0,0 +1,15 @@
1
+ import type { IInteractionCategory, IInteractionStepTile } from "../data/types.js";
2
+ export interface IIntelligenceTimelineProps {
3
+ steps: IInteractionStepTile[];
4
+ totalDurationMs: number;
5
+ categories: IInteractionCategory[];
6
+ /** Step indexes to highlight — a category's occurrences, or none in the plain list view. */
7
+ highlightedStepIndexes?: number[];
8
+ }
9
+ /**
10
+ * The single timeline track shared by the list view and every category's detail view: one tile
11
+ * per interaction step, with a hover tooltip listing that step's activities and its own
12
+ * duration/tokens. Never navigable — highlighting is driven entirely by `highlightedStepIndexes`.
13
+ */
14
+ export declare function IntelligenceTimeline({ steps, totalDurationMs, categories, highlightedStepIndexes }: IIntelligenceTimelineProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=IntelligenceTimeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntelligenceTimeline.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceTimeline.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAMnF,MAAM,WAAW,0BAA0B;IACvC,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,8FAA4F;IAC5F,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,KAAK,EACL,eAAe,EACf,UAAU,EACV,sBAAsB,EACzB,EAAE,0BAA0B,2CAc5B"}
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useMemo } from "react";
4
+ import { computeSegments } from "../data/timeline.js";
5
+ import { e } from "../intelligenceBem.js";
6
+ import { IntelligenceStepTooltip } from "./IntelligenceStepTooltip.js";
7
+ import { TimelineBar } from "./TimelineBar.js";
8
+ /**
9
+ * The single timeline track shared by the list view and every category's detail view: one tile
10
+ * per interaction step, with a hover tooltip listing that step's activities and its own
11
+ * duration/tokens. Never navigable — highlighting is driven entirely by `highlightedStepIndexes`.
12
+ */
13
+ export function IntelligenceTimeline({ steps, totalDurationMs, categories, highlightedStepIndexes, }) {
14
+ const segments = useMemo(() => computeSegments(steps, totalDurationMs), [steps, totalDurationMs]);
15
+ return (_jsx("div", { className: e("timeline-wrapper"), children: _jsx(TimelineBar, { segments: segments, highlightedStepIndexes: highlightedStepIndexes, renderTooltip: (segment) => (_jsx(IntelligenceStepTooltip, { step: steps[segment.stepIndex], categories: categories })) }) }));
16
+ }
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from "react";
2
+ import type { ITimelineSegment } from "../data/types.js";
3
+ export interface ITimelineBarProps {
4
+ /** The shared, ordered segment sequence for the whole turn — one tile per step. */
5
+ segments: ITimelineSegment[];
6
+ /** Step indexes to highlight. Every other tile dims once at least one is highlighted. */
7
+ highlightedStepIndexes?: number[];
8
+ /** Hover content for one tile. Absent renders plain, non-interactive tiles. */
9
+ renderTooltip?: (segment: ITimelineSegment) => ReactNode;
10
+ }
11
+ /**
12
+ * The single shared timeline track: one tile per interaction step, tiling the full turn in
13
+ * order. Purely informational — a tile is never clickable, only hoverable when `renderTooltip`
14
+ * is given. Tiles in `highlightedStepIndexes` render highlighted; every other tile dims once
15
+ * that list is non-empty, and all tiles render at the same neutral shade when it's absent (the
16
+ * list view's resting state).
17
+ */
18
+ export declare function TimelineBar({ segments, highlightedStepIndexes, renderTooltip }: ITimelineBarProps): import("react/jsx-runtime").JSX.Element;
19
+ //# sourceMappingURL=TimelineBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimelineBar.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/TimelineBar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAMzD,MAAM,WAAW,iBAAiB;IAC9B,qFAAmF;IACnF,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,yFAAyF;IACzF,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,+EAA+E;IAC/E,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,SAAS,CAAC;CAC5D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,sBAAsB,EAAE,aAAa,EAAE,EAAE,iBAAiB,2CAuCjG"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { UiTooltip } from "@gooddata/sdk-ui-kit";
3
+ import { e } from "../intelligenceBem.js";
4
+ /** Gap between two tiles, matching `$timeline-gap` in intelligence.scss. */
5
+ const TIMELINE_GAP_PX = 1;
6
+ /**
7
+ * The single shared timeline track: one tile per interaction step, tiling the full turn in
8
+ * order. Purely informational — a tile is never clickable, only hoverable when `renderTooltip`
9
+ * is given. Tiles in `highlightedStepIndexes` render highlighted; every other tile dims once
10
+ * that list is non-empty, and all tiles render at the same neutral shade when it's absent (the
11
+ * list view's resting state).
12
+ */
13
+ export function TimelineBar({ segments, highlightedStepIndexes, renderTooltip }) {
14
+ const highlighted = new Set(highlightedStepIndexes);
15
+ // Widths sum to exactly 100%, so each tile has to give back its share of the 1px gaps
16
+ // between them — otherwise the track overflows and clips its last tile.
17
+ const totalGapPx = TIMELINE_GAP_PX * Math.max(segments.length - 1, 0);
18
+ return (_jsx("div", { className: e("timeline"), role: "presentation", children: segments.map((segment) => {
19
+ const isHighlighted = highlighted.has(segment.stepIndex);
20
+ const isDimmed = !isHighlighted && highlighted.size > 0;
21
+ const className = e("timeline-segment", { highlighted: isHighlighted, dimmed: isDimmed });
22
+ // The pixel term is resolved here, so `calc()` only ever subtracts a plain length.
23
+ const gapShare = (totalGapPx * segment.widthPct) / 100;
24
+ const style = {
25
+ width: gapShare === 0
26
+ ? `${segment.widthPct}%`
27
+ : `calc(${segment.widthPct}% - ${gapShare}px)`,
28
+ };
29
+ if (!renderTooltip) {
30
+ return _jsx("div", { className: className, style: style }, segment.stepId);
31
+ }
32
+ return (_jsx(UiTooltip, { triggerBy: ["hover", "focus"], arrowPlacement: "bottom", variant: "none", anchorWrapperStyles: { flex: "0 0 auto", width: style.width }, anchor: _jsx("div", { className: className }), content: () => renderTooltip(segment) }, segment.stepId));
33
+ }) }));
34
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantItem.d.ts","sourceRoot":"","sources":["../../../src/components/messages/AssistantItem.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAQnE,KAAK,kBAAkB,GAAG;IACtB,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,OAAO,EAAE,0BAA0B,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,kBAAkB,kDAmDrF"}
1
+ {"version":3,"file":"AssistantItem.d.ts","sourceRoot":"","sources":["../../../src/components/messages/AssistantItem.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAMjE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAQnE,KAAK,kBAAkB,GAAG;IACtB,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,OAAO,EAAE,0BAA0B,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,kBAAkB,kDAgFrF"}
@@ -1,8 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // (C) 2024-2026 GoodData Corporation
3
+ import { useState } from "react";
3
4
  import cx from "classnames";
4
5
  import { useIntl } from "react-intl";
6
+ import { useSelector } from "react-redux";
7
+ import { interactionIntelligenceEnabledSelector } from "../../store/chatWindow/chatWindowSelectors.js";
5
8
  import { useToolsReferences } from "../completion/useToolsReferences.js";
9
+ import { useInteractionIntelligenceTotals } from "../intelligence/data/useInteractionIntelligenceTotals.js";
10
+ import { GenAiInteractionIntelligence } from "../intelligence/GenAiInteractionIntelligence.js";
11
+ import { InteractionIntelligenceTrigger } from "../intelligence/InteractionIntelligenceTrigger.js";
6
12
  import { AssistantItemFeedback } from "./AssistantItemFeedback.js";
7
13
  import { AssistantItemSuggestions } from "./AssistantItemSuggestions.js";
8
14
  import { ReasoningIcon } from "./contents/ReasoningIcon.js";
@@ -13,6 +19,13 @@ export function AssistantItemComponent({ message, groups, isLast }) {
13
19
  const group = groups[groups.length - 1];
14
20
  const messageState = getItemState(message);
15
21
  const references = useToolsReferences(groups);
22
+ const [isInteractionIntelligenceOpen, setIsInteractionIntelligenceOpen] = useState(false);
23
+ const interactionIntelligenceEnabled = useSelector(interactionIntelligenceEnabledSelector);
24
+ const showInteractionIntelligence = interactionIntelligenceEnabled && !!message.responseId;
25
+ const interactionIntelligenceTotals = useInteractionIntelligenceTotals(showInteractionIntelligence ? message.responseId : "");
26
+ // The trigger only renders once its totals exist, so this is what actually shares the actions
27
+ // row with feedback — a message with no trace keeps its feedback exactly as before.
28
+ const hasInteractionIntelligenceTrigger = showInteractionIntelligence && !!interactionIntelligenceTotals;
16
29
  const classNames = cx("gd-gen-ai-chat__messages__conversation", "gd-gen-ai-chat__messages__conversation--assistant", `gd-gen-ai-chat__messages__conversation--${message.content.type}`, messageState === "cancelled" && "gd-gen-ai-chat__messages__conversation--cancelled", isLast && "gd-gen-ai-chat__messages__conversation--isLast");
17
30
  //NOTE: For now we want to hide all tool calls
18
31
  if (message.content.type === "toolCall" || message.content.type === "toolResult") {
@@ -23,6 +36,7 @@ export function AssistantItemComponent({ message, groups, isLast }) {
23
36
  return null;
24
37
  }
25
38
  return (_jsxs("div", { className: classNames, "data-state": messageState, "data-testid": "gen-ai-conversation-assistant-message", children: [
26
- _jsx("span", { className: "gd-gen-ai-chat__visually__hidden", children: intl.formatMessage({ id: "gd.gen-ai.message.label.assistant" }) }), _jsx(ReasoningIcon, { content: message.content }), _jsx(ConversationItemContents, { role: "assistant", message: message, references: references, isLoading: messageState === "loading", isLast: isLast }), _jsx(AssistantItemSuggestions, { type: "followUp", content: message.content, showSuggestions: true, references: references }), _jsx(AssistantItemFeedback, { group: group, message: message, isLast: isLast }), _jsx(AssistantItemSuggestions, { type: "actions", content: message.content, showSuggestions: isLast })
39
+ _jsx("span", { className: "gd-gen-ai-chat__visually__hidden", children: intl.formatMessage({ id: "gd.gen-ai.message.label.assistant" }) }), _jsx(ReasoningIcon, { content: message.content }), _jsx(ConversationItemContents, { role: "assistant", message: message, references: references, isLoading: messageState === "loading", isLast: isLast }), _jsx(AssistantItemSuggestions, { type: "followUp", content: message.content, showSuggestions: true, references: references }), _jsxs("div", { className: "gd-gen-ai-chat__conversation__item__actions", children: [
40
+ _jsx(AssistantItemFeedback, { group: group, message: message, isLast: isLast, hasInteractionIntelligenceTrigger: hasInteractionIntelligenceTrigger }), showInteractionIntelligence ? (_jsx(InteractionIntelligenceTrigger, { totals: interactionIntelligenceTotals, isOpen: isInteractionIntelligenceOpen, onToggle: () => setIsInteractionIntelligenceOpen((current) => !current) })) : null] }), showInteractionIntelligence && isInteractionIntelligenceOpen ? (_jsx(GenAiInteractionIntelligence, { responseId: message.responseId, onClose: () => setIsInteractionIntelligenceOpen(false) })) : null, _jsx(AssistantItemSuggestions, { type: "actions", content: message.content, showSuggestions: isLast })
27
41
  ] }));
28
42
  }
@@ -4,6 +4,11 @@ export interface IAssistantItemFeedbackProps {
4
4
  group: IChatMessagesGroup;
5
5
  message: IChatConversationLocalItem;
6
6
  isLast?: boolean;
7
+ /**
8
+ * Whether the Interaction Intelligence trigger actually shares this actions row. With it,
9
+ * feedback stops being hover-revealed on older messages so the trigger sits flush left.
10
+ */
11
+ hasInteractionIntelligenceTrigger?: boolean;
7
12
  }
8
- export declare function AssistantItemFeedback({ message, group, isLast }: IAssistantItemFeedbackProps): import("react/jsx-runtime").JSX.Element | null;
13
+ export declare function AssistantItemFeedback({ message, group, isLast, hasInteractionIntelligenceTrigger }: IAssistantItemFeedbackProps): import("react/jsx-runtime").JSX.Element | null;
9
14
  //# sourceMappingURL=AssistantItemFeedback.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantItemFeedback.d.ts","sourceRoot":"","sources":["../../../src/components/messages/AssistantItemFeedback.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAKnE,MAAM,WAAW,2BAA2B;IACxC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,0BAA0B,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,2BAA2B,kDA8E5F"}
1
+ {"version":3,"file":"AssistantItemFeedback.d.ts","sourceRoot":"","sources":["../../../src/components/messages/AssistantItemFeedback.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAKnE,MAAM,WAAW,2BAA2B;IACxC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,0BAA0B,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,iCAAiC,CAAC,EAAE,OAAO,CAAC;CAC/C;AAED,wBAAgB,qBAAqB,CAAC,EAClC,OAAO,EACP,KAAK,EACL,MAAM,EACN,iCAAiC,EACpC,EAAE,2BAA2B,kDAsF7B"}
@@ -8,7 +8,7 @@ import { UiIconButton, UiTooltip } from "@gooddata/sdk-ui-kit";
8
8
  import { setUserFeedback } from "../../store/messages/messagesSlice.js";
9
9
  import { FeedbackPopup } from "./FeedbackPopup.js";
10
10
  import { useUserFeedback } from "./useUserFeedback.js";
11
- export function AssistantItemFeedback({ message, group, isLast }) {
11
+ export function AssistantItemFeedback({ message, group, isLast, hasInteractionIntelligenceTrigger, }) {
12
12
  const intl = useIntl();
13
13
  const dispatch = useDispatch();
14
14
  const setUserFeedbackAction = useCallback((payload) => {
@@ -24,16 +24,23 @@ export function AssistantItemFeedback({ message, group, isLast }) {
24
24
  const thumbsUpLabel = intl.formatMessage({ id: "gd.gen-ai.feedback.like" });
25
25
  const thumbsDownLabel = intl.formatMessage({ id: "gd.gen-ai.feedback.dislike" });
26
26
  const type = message.feedback?.feedback;
27
+ const isAssigned = type ? type !== "NONE" : false;
28
+ // With the Interaction Intelligence trigger sharing this row, feedback is fully hidden on
29
+ // older unrated messages instead of hover-revealed, so the trigger isn't pushed away from
30
+ // the left edge.
31
+ if (hasInteractionIntelligenceTrigger && !isLast && !isAssigned) {
32
+ return null;
33
+ }
27
34
  return (_jsxs("div", { className: cx({
28
35
  "gd-gen-ai-chat__conversation__item__feedback": true,
29
- "gd-gen-ai-chat__conversation__item__feedback--assigned": type ? type !== "NONE" : false,
36
+ "gd-gen-ai-chat__conversation__item__feedback--assigned": isAssigned,
30
37
  "gd-gen-ai-chat__conversation__item__feedback--last": isLast,
31
38
  }), children: [
32
- _jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "thumbsUp", variant: "tertiary", size: "small", isActive: type === "POSITIVE", onClick: handlePositiveFeedbackClick, accessibilityConfig: {
39
+ _jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "thumbsUp", variant: "tertiary", size: "medium", isActive: type === "POSITIVE", onClick: handlePositiveFeedbackClick, accessibilityConfig: {
33
40
  ariaLabel: thumbsUpLabel,
34
41
  ariaPressed: type === "POSITIVE" ? "true" : "false",
35
42
  } }), content: thumbsUpLabel }), _jsx(FeedbackPopup, { anchor: (opened) => {
36
- return (_jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "thumbsDown", variant: "tertiary", size: "small", isActive: type === "NEGATIVE" || opened, onClick: handleNegativeFeedbackClick, accessibilityConfig: {
43
+ return (_jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "thumbsDown", variant: "tertiary", size: "medium", isActive: type === "NEGATIVE" || opened, onClick: handleNegativeFeedbackClick, accessibilityConfig: {
37
44
  ariaLabel: thumbsDownLabel,
38
45
  ariaPressed: type === "NEGATIVE" ? "true" : "false",
39
46
  } }), content: thumbsDownLabel }));
@@ -11,6 +11,7 @@ export declare const useGenAIStore: (backend: IAnalyticalBackend, workspace: str
11
11
  excludeTags?: string[] | undefined;
12
12
  catalogItems?: CatalogItem[] | undefined;
13
13
  isPreview?: boolean | undefined;
14
+ allowInteractionIntelligence?: boolean | undefined;
14
15
  onLinkClick?: ((linkClickEvent: LinkHandlerEvent) => string | undefined) | undefined;
15
16
  allowNativeLinks?: boolean | undefined;
16
17
  mode?: GenAIAssistantMode | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"useGenAIStore.d.ts","sourceRoot":"","sources":["../../src/hooks/useGenAIStore.ts"],"names":[],"mappings":"AAMA,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;AAEjG,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAU3F,OAAO,EAAE,KAAK,gBAAgB,EAAmB,MAAM,oBAAoB,CAAC;AAI5E,eAAO,MAAM,aAAa;;;;;;;;;;;;wEAuHzB,CAAC"}
1
+ {"version":3,"file":"useGenAIStore.d.ts","sourceRoot":"","sources":["../../src/hooks/useGenAIStore.ts"],"names":[],"mappings":"AAMA,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;AAEjG,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAU3F,OAAO,EAAE,KAAK,gBAAgB,EAAmB,MAAM,oBAAoB,CAAC;AAI5E,eAAO,MAAM,aAAa;;;;;;;;;;;;;wEAgIzB,CAAC"}
@@ -5,7 +5,7 @@ import { EventDispatcher } from "../store/events.js";
5
5
  import { OptionsDispatcher } from "../store/options.js";
6
6
  import { getStore } from "../store/store.js";
7
7
  export const useGenAIStore = (backend, workspace, opts) => {
8
- const { eventHandlers, colorPalette, settings, objectTypes, includeTags, excludeTags, catalogItems, isPreview, onLinkClick, allowNativeLinks, mode, } = opts;
8
+ const { eventHandlers, colorPalette, settings, objectTypes, includeTags, excludeTags, catalogItems, isPreview, allowInteractionIntelligence, onLinkClick, allowNativeLinks, mode, } = opts;
9
9
  // Instantiate EventDispatcher. It's a designed to hold a reference to the handlers, so that
10
10
  // we don't update the context every time a new array of handlers is passed.
11
11
  // Similar to how React handles event listeners.
@@ -15,8 +15,8 @@ export const useGenAIStore = (backend, workspace, opts) => {
15
15
  // Initialize new Redux Store for each instance of GenAI Chat
16
16
  // It OK to discard the store when backend or workspace changes
17
17
  const store = useMemo(() => {
18
- return getStore(backend, workspace, eventDispatcher, optionsDispatcher, isPreview);
19
- }, [backend, workspace, eventDispatcher, optionsDispatcher, isPreview]);
18
+ return getStore(backend, workspace, eventDispatcher, optionsDispatcher, isPreview, allowInteractionIntelligence);
19
+ }, [backend, workspace, eventDispatcher, optionsDispatcher, isPreview, allowInteractionIntelligence]);
20
20
  useEffect(() => {
21
21
  if (colorPalette) {
22
22
  optionsDispatcher.setColorPalette(colorPalette);