@gooddata/sdk-ui-gen-ai 11.52.0-alpha.5 → 11.52.0-alpha.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"GenAIChatAgentDropdown.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatAgentDropdown.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAc3D,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AA2B3E,MAAM,MAAM,2BAA2B,GAAG;IACtC,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACzC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9F,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EACnC,MAAM,EACN,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,SAAS,EACT,aAAa,EACb,gBAAwB,EACxB,cAAyB,EACzB,cAAc,EACjB,EAAE,2BAA2B,2CAiI7B"}
1
+ {"version":3,"file":"GenAIChatAgentDropdown.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatAgentDropdown.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAgB3D,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAkC3E,MAAM,MAAM,2BAA2B,GAAG;IACtC,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACzC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9F,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EACnC,MAAM,EACN,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,SAAS,EACT,aAAa,EACb,gBAAwB,EACxB,cAA+B,EAC/B,cAAc,EACjB,EAAE,2BAA2B,2CA0L7B"}
@@ -1,23 +1,30 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // (C) 2026 GoodData Corporation
3
- import { useEffect, useMemo } from "react";
3
+ import { useCallback, useEffect, useMemo } from "react";
4
4
  import cx from "classnames";
5
5
  import { defineMessages, useIntl } from "react-intl";
6
- import { DefaultUiMenuInteractiveItemWrapper, Dropdown, UiButton, UiIcon, UiMenu, UiSubmenuHeader, typedUiMenuContextStore, } from "@gooddata/sdk-ui-kit";
6
+ import { DefaultUiMenuInteractiveItemWrapper, Dropdown, UiButton, UiIcon, UiMenu, UiSubmenuHeader, typedUiMenuContextStore, useIdPrefixed, } from "@gooddata/sdk-ui-kit";
7
7
  import { GenAIChatReasoningMenuRow, REASONING_MENU_ITEM_ID, useReasoningMenuItems, useSelectedReasoningLabel, } from "./GenAIChatReasoningMenu.js";
8
8
  import { getEffectiveSelectedAgentId, selectDefaultAgentId } from "./utils/agentSelection.js";
9
+ import { DEFAULT_EFFORT } from "./utils/effortSelection.js";
9
10
  const msgs = defineMessages({
10
11
  agent: {
11
12
  id: "gd.gen-ai.agents",
12
13
  },
14
+ agentTriggerAriaLabel: {
15
+ id: "gd.gen-ai.agent.trigger.ariaLabel",
16
+ },
17
+ agentTriggerWithReasoningAriaLabel: {
18
+ id: "gd.gen-ai.agent.trigger.withReasoning.ariaLabel",
19
+ },
13
20
  loading: {
14
21
  id: "gd.gen-ai.agents.loading",
15
22
  },
16
- close: {
23
+ closeAgents: {
17
24
  id: "gd.gen-ai.close",
18
25
  },
19
26
  });
20
- export function GenAIChatAgentDropdown({ agents, conversations, conversationAgentId, selectedAgentId, isDisabled, isLoading, onSelectAgent, reasoningEnabled = false, selectedEffort = "MEDIUM", onSelectEffort, }) {
27
+ export function GenAIChatAgentDropdown({ agents, conversations, conversationAgentId, selectedAgentId, isDisabled, isLoading, onSelectAgent, reasoningEnabled = false, selectedEffort = DEFAULT_EFFORT, onSelectEffort, }) {
21
28
  const intl = useIntl();
22
29
  const effectiveSelectedAgentId = getEffectiveSelectedAgentId({
23
30
  agents,
@@ -33,6 +40,8 @@ export function GenAIChatAgentDropdown({ agents, conversations, conversationAgen
33
40
  onSelectEffort,
34
41
  });
35
42
  const reasoningValueLabel = useSelectedReasoningLabel(selectedEffort, "short");
43
+ const agentsTitleId = useIdPrefixed("agents-menu-title");
44
+ const agentTriggerId = useIdPrefixed("agent-dropdown-trigger");
36
45
  useEffect(() => {
37
46
  const isConversationAgentAvailable = !!conversationAgentId && agents.some((agent) => agent.id === conversationAgentId);
38
47
  const isSelectedAgentAvailable = !!selectedAgentId && agents.some((agent) => agent.id === selectedAgentId);
@@ -64,32 +73,75 @@ export function GenAIChatAgentDropdown({ agents, conversations, conversationAgen
64
73
  id: agent.id,
65
74
  stringTitle: agent.title,
66
75
  isSelected,
76
+ selectionRole: "radio",
67
77
  isDisabled: false,
68
78
  data: { type: "agent", agent },
69
79
  tooltip: agent.description || undefined,
70
- ariaAttributes: agent.description
71
- ? { "aria-label": `${agent.title}. ${agent.description}` }
72
- : undefined,
73
80
  iconRight: agent.description ? (_jsx(UiIcon, { type: "question", size: 12, color: "complementary-5", accessibilityConfig: { ariaHidden: true } })) : undefined,
74
81
  };
75
82
  });
76
- return [...agentItems, ...reasoningItems];
83
+ const agentGroupItems = agentItems.length
84
+ ? [
85
+ {
86
+ type: "group",
87
+ id: "agents-group",
88
+ stringTitle: "",
89
+ data: undefined,
90
+ subItems: agentItems,
91
+ },
92
+ ]
93
+ : [];
94
+ return [...agentGroupItems, ...reasoningItems];
77
95
  }, [agents, effectiveSelectedAgentId, reasoningItems]);
96
+ const AgentsMenuGroupItem = useCallback((props) => (_jsx(AgentsGroupItem, { ...props, titleId: agentsTitleId })), [agentsTitleId]);
97
+ const MenuHeader = useCallback(() => _jsx(AgentMenuHeader, { titleId: agentsTitleId }), [agentsTitleId]);
98
+ const agentTriggerAriaLabel = useMemo(() => {
99
+ if (isLoading) {
100
+ return loadingLabel;
101
+ }
102
+ const agentName = selectedAgent?.title ?? agentLabel;
103
+ if (reasoningEnabled && reasoningValueLabel) {
104
+ return intl.formatMessage(msgs.agentTriggerWithReasoningAriaLabel, {
105
+ agent: agentName,
106
+ effort: reasoningValueLabel,
107
+ });
108
+ }
109
+ return intl.formatMessage(msgs.agentTriggerAriaLabel, { agent: agentName });
110
+ }, [
111
+ agentLabel,
112
+ intl,
113
+ isLoading,
114
+ loadingLabel,
115
+ reasoningEnabled,
116
+ reasoningValueLabel,
117
+ selectedAgent?.title,
118
+ ]);
78
119
  return (_jsxs(_Fragment, { children: [
79
120
  _jsx("span", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: isLoading ? loadingLabel : "" }), _jsx(Dropdown, { className: cx("gd-gen-ai-chat__input__agent-dropdown", {
80
121
  "gd-gen-ai-chat__input__agent-dropdown--loading": isLoading,
81
- }), alignPoints: [{ align: "tr br", offset: { x: 0, y: 0 } }], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, accessibilityConfig: {}, renderButton: ({ isOpen, toggleDropdown, accessibilityConfig }) => (_jsx(UiButton, { label: isLoading ? loadingLabel : (selectedAgent?.title ?? agentLabel), badgeAfter: !isLoading && reasoningEnabled ? reasoningValueLabel : undefined, variant: "dropdownInline", size: "small", iconAfter: isLoading ? undefined : isOpen ? "navigateUp" : "navigateDown", isDisabled: isLoading || isDisabled || !agents.length, onClick: toggleDropdown, dataTestId: "agent_dropdown_button", accessibilityConfig: accessibilityConfig, disableIconAnimation: true })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx(UiMenu, { dataTestId: "agent_dropdown_menu", items: items, size: "small", minWidth: 200, maxWidth: 200, containerTopPadding: "small", containerBottomPadding: "small", MenuHeader: AgentMenuHeader, InteractiveItemWrapper: AgentMenuItemWrapper, onClose: closeDropdown, ariaAttributes: ariaAttributes, onSelect: (item) => {
82
- if (item.data.type === "agent") {
83
- onSelectAgent(item.data.agent.id, { showChangeEvent: true });
84
- closeDropdown();
85
- }
86
- } })) })] }));
122
+ }), alignPoints: [{ align: "tr br", offset: { x: 0, y: 0 } }], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, returnFocusTo: agentTriggerId, accessibilityConfig: { popupRole: "dialog" }, renderButton: ({ isOpen, toggleDropdown, accessibilityConfig }) => (_jsx(UiButton, { id: agentTriggerId, label: isLoading ? loadingLabel : (selectedAgent?.title ?? agentLabel), badgeAfter: !isLoading && reasoningEnabled ? reasoningValueLabel : undefined, variant: "dropdownInline", size: "small", iconAfter: isLoading ? undefined : isOpen ? "navigateUp" : "navigateDown", isDisabled: isLoading || isDisabled || !agents.length, onClick: toggleDropdown, dataTestId: "agent_dropdown_button", accessibilityConfig: {
123
+ ...accessibilityConfig,
124
+ ariaLabel: agentTriggerAriaLabel,
125
+ }, disableIconAnimation: true })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx("div", { ...ariaAttributes, "aria-labelledby": agentsTitleId, children: _jsx(UiMenu, { dataTestId: "agent_dropdown_menu", items: items, size: "small", minWidth: 200, maxWidth: 200, containerTopPadding: "small", containerBottomPadding: "small", MenuHeader: MenuHeader, GroupItem: AgentsMenuGroupItem, InteractiveItemWrapper: AgentMenuItemWrapper, onClose: closeDropdown, ariaAttributes: {
126
+ id: `${ariaAttributes.id}-menu`,
127
+ "aria-labelledby": agentsTitleId,
128
+ }, onSelect: (item) => {
129
+ if (item.data.type === "agent") {
130
+ onSelectAgent(item.data.agent.id, { showChangeEvent: true });
131
+ closeDropdown();
132
+ }
133
+ } }) })) })] }));
134
+ }
135
+ function AgentsGroupItem({ item, titleId }) {
136
+ const { useContextStore, createSelector } = typedUiMenuContextStore();
137
+ const ItemComponent = useContextStore(createSelector((ctx) => ctx.ItemComponent));
138
+ return (_jsx("ul", { className: "gd-ui-kit-menu__group", role: "group", "aria-labelledby": titleId, children: item.subItems.map((groupItem, index) => (_jsx(ItemComponent, { item: groupItem }, "id" in groupItem ? groupItem.id : index))) }));
87
139
  }
88
- function AgentMenuHeader() {
140
+ function AgentMenuHeader({ titleId }) {
89
141
  const intl = useIntl();
90
142
  const { useContextStore, createSelector } = typedUiMenuContextStore();
91
143
  const onClose = useContextStore(createSelector((ctx) => ctx.onClose));
92
- return (_jsx(UiSubmenuHeader, { title: intl.formatMessage(msgs.agent), height: "medium", onClose: onClose, closeAriaLabel: intl.formatMessage(msgs.close) }));
144
+ return (_jsx(UiSubmenuHeader, { title: intl.formatMessage(msgs.agent), titleId: titleId, height: "medium", onClose: onClose, closeAriaLabel: intl.formatMessage(msgs.closeAgents) }));
93
145
  }
94
146
  function AgentMenuItemWrapper(props) {
95
147
  if (props.item.id === REASONING_MENU_ITEM_ID) {
@@ -1 +1 @@
1
- {"version":3,"file":"GenAIChatEffortDropdown.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatEffortDropdown.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAe3D,MAAM,MAAM,4BAA4B,GAAG;IACvC,cAAc,EAAE,eAAe,CAAC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACpC,cAAc,EACd,UAAU,EACV,cAAc,EACjB,EAAE,4BAA4B,2CA8C9B"}
1
+ {"version":3,"file":"GenAIChatEffortDropdown.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatEffortDropdown.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAmB3D,MAAM,MAAM,4BAA4B,GAAG;IACvC,cAAc,EAAE,eAAe,CAAC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACpC,cAAc,EACd,UAAU,EACV,cAAc,EACjB,EAAE,4BAA4B,2CAwE9B"}
@@ -1,12 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // (C) 2026 GoodData Corporation
3
+ import { useCallback, useMemo } from "react";
3
4
  import { defineMessages, useIntl } from "react-intl";
4
- import { Dropdown, UiButton, UiMenu, UiSubmenuHeader } from "@gooddata/sdk-ui-kit";
5
- import { useReasoningOptionItems, useSelectedReasoningLabel, } from "./GenAIChatReasoningMenu.js";
5
+ import { Dropdown, UiButton, UiMenu, useIdPrefixed } from "@gooddata/sdk-ui-kit";
6
+ import { ReasoningEffortMenuHeader, useReasoningOptionItems, useSelectedReasoningLabel, } from "./GenAIChatReasoningMenu.js";
6
7
  const msgs = defineMessages({
7
8
  reasoning: {
8
9
  id: "gd.gen-ai.reasoning",
9
10
  },
11
+ effortTriggerAriaLabel: {
12
+ id: "gd.gen-ai.effort.trigger.ariaLabel",
13
+ },
10
14
  });
11
15
  /**
12
16
  * Standalone reasoning-effort dropdown, structured like GenAIChatAgentDropdown but listing effort
@@ -18,12 +22,20 @@ export function GenAIChatEffortDropdown({ selectedEffort, isDisabled, onSelectEf
18
22
  const reasoningLabel = intl.formatMessage(msgs.reasoning);
19
23
  const options = useReasoningOptionItems(selectedEffort, "full");
20
24
  const valueLabel = useSelectedReasoningLabel(selectedEffort, "full");
21
- return (_jsx(Dropdown, { className: "gd-gen-ai-chat__input__effort-dropdown", alignPoints: [{ align: "tr br", offset: { x: 0, y: 0 } }], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, accessibilityConfig: {}, renderButton: ({ isOpen, toggleDropdown, accessibilityConfig }) => (_jsx(UiButton, { label: valueLabel ?? reasoningLabel, variant: "dropdownInline", size: "small", iconAfter: isOpen ? "navigateUp" : "navigateDown", isDisabled: isDisabled, onClick: toggleDropdown, dataTestId: "effort_dropdown_button", accessibilityConfig: accessibilityConfig, disableIconAnimation: true })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx(UiMenu, { dataTestId: "effort_dropdown_menu", items: options, size: "small", minWidth: 200, maxWidth: 260, containerTopPadding: "small", containerBottomPadding: "small", MenuHeader: EffortMenuHeader, ariaAttributes: ariaAttributes, onSelect: (item) => {
22
- onSelectEffort(item.data.effort);
23
- closeDropdown();
24
- } })) }));
25
- }
26
- function EffortMenuHeader() {
27
- const intl = useIntl();
28
- return _jsx(UiSubmenuHeader, { title: intl.formatMessage(msgs.reasoning), height: "medium" });
25
+ const effortTitleId = useIdPrefixed("effort-menu-title");
26
+ const effortTriggerId = useIdPrefixed("effort-dropdown-trigger");
27
+ const MenuHeader = useCallback(() => _jsx(ReasoningEffortMenuHeader, { titleId: effortTitleId }), [effortTitleId]);
28
+ const effortTriggerAriaLabel = useMemo(() => intl.formatMessage(msgs.effortTriggerAriaLabel, {
29
+ effort: valueLabel ?? reasoningLabel,
30
+ }), [intl, reasoningLabel, valueLabel]);
31
+ return (_jsx(Dropdown, { className: "gd-gen-ai-chat__input__effort-dropdown", alignPoints: [{ align: "tr br", offset: { x: 0, y: 0 } }], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, returnFocusTo: effortTriggerId, accessibilityConfig: { popupRole: "dialog" }, renderButton: ({ isOpen, toggleDropdown, accessibilityConfig }) => (_jsx(UiButton, { id: effortTriggerId, label: valueLabel ?? reasoningLabel, variant: "dropdownInline", size: "small", iconAfter: isOpen ? "navigateUp" : "navigateDown", isDisabled: isDisabled, onClick: toggleDropdown, dataTestId: "effort_dropdown_button", accessibilityConfig: {
32
+ ...accessibilityConfig,
33
+ ariaLabel: effortTriggerAriaLabel,
34
+ }, disableIconAnimation: true })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx("div", { ...ariaAttributes, "aria-labelledby": effortTitleId, children: _jsx(UiMenu, { dataTestId: "effort_dropdown_menu", items: options, size: "small", minWidth: 200, maxWidth: 260, containerTopPadding: "small", containerBottomPadding: "small", MenuHeader: MenuHeader, onClose: closeDropdown, ariaAttributes: {
35
+ id: `${ariaAttributes.id}-menu`,
36
+ "aria-labelledby": effortTitleId,
37
+ }, onSelect: (item) => {
38
+ onSelectEffort(item.data.effort);
39
+ closeDropdown();
40
+ } }) })) }));
29
41
  }
@@ -51,6 +51,13 @@ export type EffortMenuItemData = {
51
51
  * @internal
52
52
  */
53
53
  export declare function useReasoningOptionItems(selectedEffort: GenAIChatEffort, labelMode: ReasoningLabelMode): IUiMenuItem<EffortMenuItemData>[];
54
+ /**
55
+ * Header for the standalone effort dropdown (dialog with close control).
56
+ * @internal
57
+ */
58
+ export declare function ReasoningEffortMenuHeader({ titleId }: {
59
+ titleId: string;
60
+ }): import("react/jsx-runtime").JSX.Element;
54
61
  /**
55
62
  * The "Reasoning" row rendered inside the agent menu. It is a self-contained Dropdown whose trigger
56
63
  * is the row and whose body is the effort options — opened as its own overlay on the left of the row.
@@ -1 +1 @@
1
- {"version":3,"file":"GenAIChatReasoningMenu.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatReasoningMenu.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAEH,KAAK,kCAAkC,EACvC,KAAK,WAAW,EAInB,MAAM,sBAAsB,CAAC;AA0B9B;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,cAAc,EAAE,eAAe,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,CAAC;AAmBlD;;;;GAIG;AACH,wBAAgB,yBAAyB,CACrC,cAAc,EAAE,eAAe,EAC/B,SAAS,EAAE,kBAAkB,GAC9B,MAAM,GAAG,SAAS,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAClC,OAAO,EACP,cAAc,EACd,cAAc,EACjB,EAAE;IACC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,eAAe,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACtD,GAAG,WAAW,CAAC;IAAE,WAAW,EAAE,qBAAqB,CAAA;CAAE,CAAC,EAAE,CAmBxD;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC7B,WAAW,EAAE;QAAE,MAAM,EAAE,eAAe,CAAA;KAAE,CAAC;CAC5C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,uBAAuB,CACnC,cAAc,EAAE,eAAe,EAC/B,SAAS,EAAE,kBAAkB,GAC9B,WAAW,CAAC,kBAAkB,CAAC,EAAE,CA8BnC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EACtC,IAAI,EACP,EAAE,kCAAkC,CAAC;IAAE,WAAW,EAAE,qBAAqB,CAAA;CAAE,CAAC,2CAwD5E"}
1
+ {"version":3,"file":"GenAIChatReasoningMenu.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatReasoningMenu.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAEH,KAAK,kCAAkC,EACvC,KAAK,WAAW,EAMnB,MAAM,sBAAsB,CAAC;AAkC9B;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,cAAc,EAAE,eAAe,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,CAAC;AAqBlD;;;;GAIG;AACH,wBAAgB,yBAAyB,CACrC,cAAc,EAAE,eAAe,EAC/B,SAAS,EAAE,kBAAkB,GAC9B,MAAM,GAAG,SAAS,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAClC,OAAO,EACP,cAAc,EACd,cAAc,EACjB,EAAE;IACC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,eAAe,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACtD,GAAG,WAAW,CAAC;IAAE,WAAW,EAAE,qBAAqB,CAAA;CAAE,CAAC,EAAE,CAmBxD;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC7B,WAAW,EAAE;QAAE,MAAM,EAAE,eAAe,CAAA;KAAE,CAAC;CAC5C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,uBAAuB,CACnC,cAAc,EAAE,eAAe,EAC/B,SAAS,EAAE,kBAAkB,GAC9B,WAAW,CAAC,kBAAkB,CAAC,EAAE,CA8BnC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,2CAczE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EACtC,IAAI,EACP,EAAE,kCAAkC,CAAC;IAAE,WAAW,EAAE,qBAAqB,CAAA;CAAE,CAAC,2CAiE5E"}
@@ -2,11 +2,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // (C) 2026 GoodData Corporation
3
3
  import { useMemo } from "react";
4
4
  import { defineMessages, useIntl } from "react-intl";
5
- import { Dropdown, UiIcon, UiMenu, typedUiMenuContextStore, } from "@gooddata/sdk-ui-kit";
5
+ import { Dropdown, UiIcon, UiMenu, UiSubmenuHeader, typedUiMenuContextStore, useIdPrefixed, } from "@gooddata/sdk-ui-kit";
6
+ import { SUPPORTED_EFFORTS } from "./utils/effortSelection.js";
6
7
  const msgs = defineMessages({
7
8
  reasoning: {
8
9
  id: "gd.gen-ai.reasoning",
9
10
  },
11
+ reasoningRowAriaLabel: {
12
+ id: "gd.gen-ai.reasoning.row.ariaLabel",
13
+ },
14
+ closeReasoning: {
15
+ id: "gd.gen-ai.close.reasoning",
16
+ },
10
17
  quick: {
11
18
  id: "gd.gen-ai.reasoning.quick",
12
19
  },
@@ -27,18 +34,20 @@ const msgs = defineMessages({
27
34
  },
28
35
  });
29
36
  export const REASONING_MENU_ITEM_ID = "reasoning";
30
- const REASONING_OPTIONS = [
31
- {
32
- effort: "LOW",
37
+ const REASONING_COPY = {
38
+ LOW: {
33
39
  labels: { short: msgs.quick, full: msgs.quickFull },
34
40
  description: msgs.quickDescription,
35
41
  },
36
- {
37
- effort: "MEDIUM",
42
+ MEDIUM: {
38
43
  labels: { short: msgs.thinking, full: msgs.thinkingFull },
39
44
  description: msgs.thinkingDescription,
40
45
  },
41
- ];
46
+ };
47
+ const REASONING_OPTIONS = SUPPORTED_EFFORTS.map((effort) => ({
48
+ effort,
49
+ ...REASONING_COPY[effort],
50
+ }));
42
51
  /**
43
52
  * Localized label of the currently selected reasoning mode ("Quick" or "Quick answer", depending on
44
53
  * the label mode), or undefined otherwise.
@@ -87,14 +96,24 @@ export function useReasoningOptionItems(selectedEffort, labelMode) {
87
96
  id: `reasoning-${effort}`,
88
97
  stringTitle: title,
89
98
  isSelected: effort === selectedEffort,
99
+ selectionRole: "radio",
90
100
  isDisabled: false,
91
101
  data: { effort },
92
102
  tooltip: descriptionText,
93
- ariaAttributes: { "aria-label": `${title}. ${descriptionText}` },
94
103
  iconRight: (_jsx(UiIcon, { type: "question", size: 12, color: "complementary-5", accessibilityConfig: { ariaHidden: true } })),
95
104
  };
96
105
  }), [intl, selectedEffort, labelMode]);
97
106
  }
107
+ /**
108
+ * Header for the standalone effort dropdown (dialog with close control).
109
+ * @internal
110
+ */
111
+ export function ReasoningEffortMenuHeader({ titleId }) {
112
+ const intl = useIntl();
113
+ const { useContextStore, createSelector } = typedUiMenuContextStore();
114
+ const onClose = useContextStore(createSelector((ctx) => ctx.onClose));
115
+ return (_jsx(UiSubmenuHeader, { title: intl.formatMessage(msgs.reasoning), titleId: titleId, height: "medium", onClose: onClose, closeAriaLabel: intl.formatMessage(msgs.closeReasoning) }));
116
+ }
98
117
  /**
99
118
  * The "Reasoning" row rendered inside the agent menu. It is a self-contained Dropdown whose trigger
100
119
  * is the row and whose body is the effort options — opened as its own overlay on the left of the row.
@@ -108,12 +127,16 @@ export function GenAIChatReasoningMenuRow({ item, }) {
108
127
  const options = useReasoningOptionItems(selectedEffort, "short");
109
128
  const { useContextStore, createSelector } = typedUiMenuContextStore();
110
129
  const closeParentMenu = useContextStore(createSelector((ctx) => ctx.onClose));
130
+ const reasoningTriggerId = useIdPrefixed("reasoning-row-trigger");
131
+ const reasoningRowAriaLabel = intl.formatMessage(msgs.reasoningRowAriaLabel, {
132
+ effort: valueLabel ?? reasoningLabel,
133
+ });
111
134
  return (_jsx("li", { role: "none", className: "gd-gen-ai-chat__reasoning-row", children: _jsx(Dropdown, { alignPoints: [
112
135
  { align: "tr tl", offset: { x: -4, y: 0 } },
113
136
  { align: "tl tr", offset: { x: 4, y: 0 } },
114
- ], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, accessibilityConfig: {}, renderButton: ({ isOpen, toggleDropdown }) => (_jsxs("button", { type: "button", className: "gd-gen-ai-chat__reasoning-row__button", "aria-haspopup": "menu", "aria-expanded": isOpen, onClick: toggleDropdown, children: [
137
+ ], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, returnFocusTo: reasoningTriggerId, accessibilityConfig: {}, renderButton: ({ isOpen, toggleDropdown }) => (_jsxs("button", { type: "button", id: reasoningTriggerId, className: "gd-gen-ai-chat__reasoning-row__button", "aria-label": reasoningRowAriaLabel, "aria-haspopup": "menu", "aria-expanded": isOpen, onClick: toggleDropdown, children: [
115
138
  _jsx("span", { className: "gd-gen-ai-chat__reasoning-row__title", children: reasoningLabel }), valueLabel ? (_jsx("span", { className: "gd-gen-ai-chat__reasoning-row__value", children: valueLabel })) : null, _jsx("i", { className: "gd-icon-navigateright" })
116
- ] })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx(UiMenu, { dataTestId: "reasoning_dropdown_menu", items: options, size: "small", minWidth: 200, maxWidth: 260, containerTopPadding: "small", containerBottomPadding: "small", ariaAttributes: ariaAttributes, onSelect: (option) => {
139
+ ] })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx(UiMenu, { dataTestId: "reasoning_dropdown_menu", items: options, size: "small", minWidth: 200, maxWidth: 260, containerTopPadding: "small", containerBottomPadding: "small", ariaAttributes: ariaAttributes, onClose: closeDropdown, onSelect: (option) => {
117
140
  onSelectEffort?.(option.data.effort);
118
141
  closeDropdown();
119
142
  closeParentMenu?.();
@@ -0,0 +1,11 @@
1
+ import { type GenAIChatEffort } from "@gooddata/sdk-model";
2
+ import { type IChatConversationLocalItem } from "../../model.js";
3
+ export declare const SUPPORTED_EFFORTS: readonly ["LOW", "MEDIUM"];
4
+ export type SupportedEffort = (typeof SUPPORTED_EFFORTS)[number];
5
+ export declare const DEFAULT_EFFORT: SupportedEffort;
6
+ export declare function sanitizeEffort(effort: GenAIChatEffort | undefined): SupportedEffort | undefined;
7
+ /**
8
+ * The effort a conversation was last using, or undefined when its history records none.
9
+ */
10
+ export declare function deriveConversationEffort(items: IChatConversationLocalItem[] | undefined): SupportedEffort | undefined;
11
+ //# sourceMappingURL=effortSelection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effortSelection.d.ts","sourceRoot":"","sources":["../../../src/components/utils/effortSelection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAGjE,eAAO,MAAM,iBAAiB,4BAAsE,CAAC;AAErG,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,eAAO,MAAM,cAAc,EAAE,eAA0B,CAAC;AAExD,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,CAE/F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,0BAA0B,EAAE,GAAG,SAAS,GAChD,eAAe,GAAG,SAAS,CAQ7B"}
@@ -0,0 +1,17 @@
1
+ // (C) 2026 GoodData Corporation
2
+ // Efforts the UI can represent, in menu order. The backend enum is wider (it also has HIGH).
3
+ export const SUPPORTED_EFFORTS = ["LOW", "MEDIUM"];
4
+ export const DEFAULT_EFFORT = "MEDIUM";
5
+ export function sanitizeEffort(effort) {
6
+ return SUPPORTED_EFFORTS.find((supported) => supported === effort);
7
+ }
8
+ /**
9
+ * The effort a conversation was last using, or undefined when its history records none.
10
+ */
11
+ export function deriveConversationEffort(items) {
12
+ const lastUserItem = items?.filter((item) => item.role === "user" && item.id).pop();
13
+ if (!lastUserItem) {
14
+ return undefined;
15
+ }
16
+ return sanitizeEffort(lastUserItem.reasoningEffort) ?? DEFAULT_EFFORT;
17
+ }
@@ -14,7 +14,7 @@ export declare function buildFiltersContext(filters: FilterContextItem[], displa
14
14
  /**
15
15
  * @internal
16
16
  */
17
- export declare function buildWidgetsContext(widgetsMap: Pick<Map<ObjRef, IWidget>, "values" | "get"> | undefined, resultsIdMap?: Pick<Map<string, string | undefined>, "values" | "get">): {
17
+ export declare function buildWidgetsContext(widgetsMap: Pick<Map<ObjRef, IWidget>, "values" | "get"> | undefined, resultsIdMap?: Pick<Map<string, string | undefined>, "values" | "get">, visualizationSwitcherActiveVisualizations?: Record<string, string>): {
18
18
  widgets: IGenAIWidgetDescriptor[];
19
19
  referencedObjects: IGenAIObjectReference[];
20
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/context/dashboard.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,mCAAmC,EACxC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EAEtB,KAAK,sBAAsB,EAC3B,KAAK,OAAO,EACZ,KAAK,MAAM,EASd,MAAM,qBAAqB,CAAC;AAM7B;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,sBAAsB,GAAG,iBAAiB,CAM1F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,SAAS,GAAG,uBAAuB,GAAG,UAAU,EAC5D,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,WAAW,GAAG,YAAY,CAAC,CAAC,GACpF,sBAAsB,CAOxB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,mCAAmC,CAAC,EAAE,KAAK,CAAC,GAC7E,sBAAsB,EAAE,CA2E1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC,GAAG,SAAS,EACpE,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC,GACvE;IAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAAC,iBAAiB,EAAE,qBAAqB,EAAE,CAAA;CAAE,CAmEnF"}
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/context/dashboard.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,mCAAmC,EACxC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EAEtB,KAAK,sBAAsB,EAC3B,KAAK,OAAO,EACZ,KAAK,MAAM,EASd,MAAM,qBAAqB,CAAC;AAM7B;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,sBAAsB,GAAG,iBAAiB,CAM1F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,SAAS,GAAG,uBAAuB,GAAG,UAAU,EAC5D,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,WAAW,GAAG,YAAY,CAAC,CAAC,GACpF,sBAAsB,CAOxB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,mCAAmC,CAAC,EAAE,KAAK,CAAC,GAC7E,sBAAsB,EAAE,CA2E1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC,GAAG,SAAS,EACpE,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC,EACtE,yCAAyC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnE;IAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAAC,iBAAiB,EAAE,qBAAqB,EAAE,CAAA;CAAE,CAuEnF"}
@@ -91,7 +91,7 @@ export function buildFiltersContext(filters, displayForms) {
91
91
  /**
92
92
  * @internal
93
93
  */
94
- export function buildWidgetsContext(widgetsMap, resultsIdMap) {
94
+ export function buildWidgetsContext(widgetsMap, resultsIdMap, visualizationSwitcherActiveVisualizations) {
95
95
  const widgets = [];
96
96
  const referencedObjects = [];
97
97
  if (!widgetsMap) {
@@ -116,7 +116,9 @@ export function buildWidgetsContext(widgetsMap, resultsIdMap) {
116
116
  }
117
117
  }
118
118
  if (isVisualizationSwitcherWidget(widget)) {
119
- const activeVisualization = widget.visualizations[0];
119
+ const activeVisualizationId = visualizationSwitcherActiveVisualizations?.[objRefToString(widget.ref)];
120
+ const activeVisualization = widget.visualizations.find((v) => v.identifier === activeVisualizationId) ??
121
+ widget.visualizations[0];
120
122
  widgets.push(buildWidgetContext(widget.title || activeVisualization?.title, widget.ref, "visualizationSwitcher", {
121
123
  insightRef: activeVisualization?.insight,
122
124
  resultId: activeVisualization
@@ -135,6 +135,14 @@ export declare const en_US: {
135
135
  text: string;
136
136
  crowdinContext: string;
137
137
  };
138
+ "gd.gen-ai.agent.trigger.ariaLabel": {
139
+ text: string;
140
+ crowdinContext: string;
141
+ };
142
+ "gd.gen-ai.agent.trigger.withReasoning.ariaLabel": {
143
+ text: string;
144
+ crowdinContext: string;
145
+ };
138
146
  "gd.gen-ai.agent.unavailable": {
139
147
  text: string;
140
148
  crowdinContext: string;
@@ -151,10 +159,22 @@ export declare const en_US: {
151
159
  text: string;
152
160
  crowdinContext: string;
153
161
  };
162
+ "gd.gen-ai.close.reasoning": {
163
+ text: string;
164
+ crowdinContext: string;
165
+ };
166
+ "gd.gen-ai.effort.trigger.ariaLabel": {
167
+ text: string;
168
+ crowdinContext: string;
169
+ };
154
170
  "gd.gen-ai.reasoning": {
155
171
  text: string;
156
172
  crowdinContext: string;
157
173
  };
174
+ "gd.gen-ai.reasoning.row.ariaLabel": {
175
+ text: string;
176
+ crowdinContext: string;
177
+ };
158
178
  "gd.gen-ai.reasoning.quick": {
159
179
  text: string;
160
180
  crowdinContext: string;
@@ -1 +1 @@
1
- {"version":3,"file":"en-US.localization-bundle.d.ts","sourceRoot":"","sources":["../../../src/localization/bundles/en-US.localization-bundle.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAixBjB,CAAC"}
1
+ {"version":3,"file":"en-US.localization-bundle.d.ts","sourceRoot":"","sources":["../../../src/localization/bundles/en-US.localization-bundle.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqyBjB,CAAC"}
@@ -137,6 +137,14 @@ export const en_US = {
137
137
  "text": "Loading",
138
138
  "crowdinContext": "Label shown on the AI chatbot agent selector while the available agents are loading"
139
139
  },
140
+ "gd.gen-ai.agent.trigger.ariaLabel": {
141
+ "text": "Agent: {agent}.",
142
+ "crowdinContext": "Accessibility label for the AI chatbot agent selector trigger in the chat input"
143
+ },
144
+ "gd.gen-ai.agent.trigger.withReasoning.ariaLabel": {
145
+ "text": "Agent: {agent}. Reasoning effort: {effort}.",
146
+ "crowdinContext": "Accessibility label for the AI chatbot agent selector trigger when the current reasoning effort is shown next to the agent name"
147
+ },
140
148
  "gd.gen-ai.agent.unavailable": {
141
149
  "text": "No agent available",
142
150
  "crowdinContext": "Message shown in the AI chatbot input when no agent can answer prompts"
@@ -150,13 +158,25 @@ export const en_US = {
150
158
  "crowdinContext": "Divider message shown in an AI chatbot conversation after the user switches to another agent"
151
159
  },
152
160
  "gd.gen-ai.close": {
153
- "text": "Close",
154
- "crowdinContext": "Accessibility label for the button that closes the AI chatbot agent dropdown"
161
+ "text": "Close agents",
162
+ "crowdinContext": "Accessibility label for the button that closes the AI chatbot agents dialog"
163
+ },
164
+ "gd.gen-ai.close.reasoning": {
165
+ "text": "Close reasoning effort",
166
+ "crowdinContext": "Accessibility label for the button that closes the AI chatbot reasoning-effort dialog"
167
+ },
168
+ "gd.gen-ai.effort.trigger.ariaLabel": {
169
+ "text": "Reasoning effort: {effort}.",
170
+ "crowdinContext": "Accessibility label for the standalone reasoning-effort selector trigger in the chat input"
155
171
  },
156
172
  "gd.gen-ai.reasoning": {
157
173
  "text": "Reasoning effort",
158
174
  "crowdinContext": "Label for the reasoning-effort row in the AI chatbot agent dropdown, where the user picks how much effort the assistant spends on the answer"
159
175
  },
176
+ "gd.gen-ai.reasoning.row.ariaLabel": {
177
+ "text": "Reasoning effort: {effort}.",
178
+ "crowdinContext": "Accessibility label for the reasoning-effort row in the agents dialog"
179
+ },
160
180
  "gd.gen-ai.reasoning.quick": {
161
181
  "text": "Quick",
162
182
  "crowdinContext": "Option in the AI chatbot reasoning selector for a quick, concise answer, shown next to the agent name"
@@ -18,6 +18,7 @@ export declare const conversationMessagesByIdSelector: (state: RootState, conver
18
18
  export declare const conversationSelector: (state: RootState) => IChatConversationLocal | undefined;
19
19
  export declare const selectedAgentIdSelector: (state: RootState) => string | undefined;
20
20
  export declare const selectedEffortSelector: (state: RootState) => GenAIChatEffort;
21
+ export declare const conversationEffortSelector: (state: RootState, conversationLocalId?: string | undefined) => GenAIChatEffort;
21
22
  export declare const agentsSelector: ((state: RootState) => import("../../model.js").GenAIAgent[] | undefined) & {
22
23
  clearCache: () => void;
23
24
  resultsCount: () => number;
@@ -1 +1 @@
1
- {"version":3,"file":"messagesSelectors.d.ts","sourceRoot":"","sources":["../../../src/store/messages/messagesSelectors.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAE,KAAK,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5G,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C,eAAO,MAAM,gBAAgB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,EAG3D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAGlD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAGrD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,GAAG,SAGjE,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OASvD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAC/B,KAAK,EAAE,SAAS,KACf,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,SAS1D,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;aAIgD,CAAC;AAExF,eAAO,MAAM,mBAAmB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAGjF,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,GAAG,SAG7D,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,0BAA0B,EAIrF,CAAC;AAEP,eAAO,MAAM,gCAAgC,EAAE,CAC3C,KAAK,EAAE,SAAS,EAChB,cAAc,CAAC,EAAE,MAAM,KACtB,0BAA0B,EAU9B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,sBAAsB,GAAG,SAGjF,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,GAAG,SAGpE,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,eAG1D,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAiE,CAAC;AAE7F,eAAO,MAAM,uBAAuB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,GAAG,SAGrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,CACnC,KAAK,EAAE,SAAS,EAChB,cAAc,EAAE,MAAM,KACrB,sBAAsB,GAAG,SAI7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,sBAAsB,EAAE,GAAG,SACZ,CAAC;AAE1E,eAAO,MAAM,2BAA2B,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAG/D,CAAC"}
1
+ {"version":3,"file":"messagesSelectors.d.ts","sourceRoot":"","sources":["../../../src/store/messages/messagesSelectors.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D,OAAO,EAAE,KAAK,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5G,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C,eAAO,MAAM,gBAAgB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,EAG3D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAGlD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAGrD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,GAAG,SAGjE,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OASvD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAC/B,KAAK,EAAE,SAAS,KACf,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,SAS1D,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;aAIgD,CAAC;AAExF,eAAO,MAAM,mBAAmB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAGjF,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,GAAG,SAG7D,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,0BAA0B,EAIrF,CAAC;AAEP,eAAO,MAAM,gCAAgC,EAAE,CAC3C,KAAK,EAAE,SAAS,EAChB,cAAc,CAAC,EAAE,MAAM,KACtB,0BAA0B,EAU9B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,sBAAsB,GAAG,SAGjF,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,GAAG,SAGpE,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,eAQ1D,CAAC;AAEF,eAAO,MAAM,0BAA0B,iFACqE,CAAC;AAE7G,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAiE,CAAC;AAE7F,eAAO,MAAM,uBAAuB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,GAAG,SAGrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,CACnC,KAAK,EAAE,SAAS,EAChB,cAAc,EAAE,MAAM,KACrB,sBAAsB,GAAG,SAI7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,sBAAsB,EAAE,GAAG,SACZ,CAAC;AAE1E,eAAO,MAAM,2BAA2B,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAG/D,CAAC"}
@@ -1,5 +1,6 @@
1
1
  // (C) 2024-2026 GoodData Corporation
2
2
  import { createSelector } from "@reduxjs/toolkit";
3
+ import { DEFAULT_EFFORT } from "../../components/utils/effortSelection.js";
3
4
  import { messagesSliceName } from "./messagesSlice.js";
4
5
  const messagesSliceSelector = (state) => state[messagesSliceName];
5
6
  export const messagesSelector = createSelector(messagesSliceSelector, (state) => state.messageOrder.map((id) => state.messages[id]));
@@ -36,7 +37,13 @@ export const conversationMessagesByIdSelector = createSelector([messagesSliceSel
36
37
  });
37
38
  export const conversationSelector = createSelector(messagesSliceSelector, (state) => state.currentConversation);
38
39
  export const selectedAgentIdSelector = createSelector(messagesSliceSelector, (state) => state.selectedAgentId);
39
- export const selectedEffortSelector = createSelector(messagesSliceSelector, (state) => state.selectedEffort);
40
+ export const selectedEffortSelector = createSelector(messagesSliceSelector, (state) => {
41
+ if (!state.currentConversation) {
42
+ return state.selectedEffort;
43
+ }
44
+ return state.conversationsData[state.currentConversation.localId]?.reasoningEffort ?? DEFAULT_EFFORT;
45
+ });
46
+ export const conversationEffortSelector = (state, conversationLocalId) => state[messagesSliceName].conversationsData[conversationLocalId ?? ""]?.reasoningEffort ?? DEFAULT_EFFORT;
40
47
  export const agentsSelector = createSelector(messagesSliceSelector, (state) => state.agents);
41
48
  export const agentsAvailableSelector = createSelector(agentsSelector, (agents) => (agents ? agents.length > 0 : undefined));
42
49
  export const conversationByIdSelector = createSelector([messagesSliceSelector, (_state, conversationId) => conversationId], (state, conversationId) => state.conversations?.find((conversation) => conversation.localId === conversationId));
@@ -47,7 +47,8 @@ type MessagesSliceState = {
47
47
  */
48
48
  selectedAgentId: string | undefined;
49
49
  /**
50
- * The effort level the user selected for the next message.
50
+ * The effort level the user selected for the next message, used only while no conversation is
51
+ * selected. With conversations the effort lives per conversation in conversationsData.
51
52
  */
52
53
  selectedEffort: GenAIChatEffort;
53
54
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"messagesSlice.d.ts","sourceRoot":"","sources":["../../../src/store/messages/messagesSlice.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messagesSlice.d.ts","sourceRoot":"","sources":["../../../src/store/messages/messagesSlice.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  // (C) 2024-2026 GoodData Corporation
2
2
  import { createSlice } from "@reduxjs/toolkit";
3
3
  import { selectDefaultAgentId } from "../../components/utils/agentSelection.js";
4
+ import { DEFAULT_EFFORT, deriveConversationEffort } from "../../components/utils/effortSelection.js";
4
5
  import { isAssistantMessage, isChatConversationLocalItem, isUserMessage, isVisualizationContents, makeAgentChangeItem, makeErrorContent, makeErrorContents, } from "../../model.js";
5
6
  import { convertMessageToChatConversation } from "../sideEffects/utils.js";
6
7
  import { createEmptyConversation, getConversationData, getConversationLocalId, isConversationWithLocalId, } from "../utils.js";
@@ -29,7 +30,7 @@ const initialState = {
29
30
  currentConversation: undefined,
30
31
  conversationsLoaded: false,
31
32
  selectedAgentId: undefined,
32
- selectedEffort: "MEDIUM",
33
+ selectedEffort: DEFAULT_EFFORT,
33
34
  agents: undefined,
34
35
  conversationsData: {},
35
36
  };
@@ -72,6 +73,13 @@ const setNormalizedConversation = (state, conversation, conversationItems) => {
72
73
  data.items = normalizedItems;
73
74
  }
74
75
  };
76
+ const seedConversationEffort = (state, conversationLocalId) => {
77
+ const data = getConversationData(state.conversationsData, conversationLocalId);
78
+ if (!data || data.reasoningEffort !== undefined) {
79
+ return;
80
+ }
81
+ data.reasoningEffort = deriveConversationEffort(data.order.map((localId) => data.items[localId]));
82
+ };
75
83
  const setConversationInProgress = (state, inProgress, localConversationId) => {
76
84
  if (!localConversationId) {
77
85
  return;
@@ -217,6 +225,7 @@ const messagesSlice = createSlice({
217
225
  loadConversationSuccessAction: (state, { payload: { currentConversation, conversationItems, threadId }, }) => {
218
226
  setNormalizedConversation(state, currentConversation, conversationItems);
219
227
  state.selectedAgentId = currentConversation.agentId ?? state.selectedAgentId;
228
+ seedConversationEffort(state, currentConversation.localId);
220
229
  state.threadId = threadId;
221
230
  if (state.currentConversation) {
222
231
  const data = getConversationData(state.conversationsData, state.currentConversation.localId);
@@ -483,6 +492,7 @@ const messagesSlice = createSlice({
483
492
  state.loaded = true;
484
493
  }
485
494
  state.selectedAgentId = payload.conversation.agentId ?? state.selectedAgentId;
495
+ seedConversationEffort(state, state.currentConversation?.localId);
486
496
  },
487
497
  setSelectedAgentAction: (state, { payload, }) => {
488
498
  const previousAgentId = state.currentConversation?.agentId;
@@ -519,7 +529,13 @@ const messagesSlice = createSlice({
519
529
  }
520
530
  },
521
531
  setSelectedEffortAction: (state, { payload }) => {
522
- state.selectedEffort = payload.effort;
532
+ const data = getConversationData(state.conversationsData, state.currentConversation?.localId);
533
+ if (data) {
534
+ data.reasoningEffort = payload.effort;
535
+ }
536
+ else {
537
+ state.selectedEffort = payload.effort;
538
+ }
523
539
  },
524
540
  applyPendingAgentSwitchAction: (state, { payload }) => {
525
541
  const data = state.conversationsData[payload.conversationLocalId];
@@ -4,7 +4,7 @@ import { isChatConversationError, isChatConversationItem, } from "@gooddata/sdk-
4
4
  import { isChatConversationLocalItem, isTextContents, isUserMessage, makeAssistantItem, makeAssistantMessage, } from "../../model.js";
5
5
  import { generateTitleFromQuestion } from "../../utils.js";
6
6
  import { agentSwitchingActiveSelector, allowedRelationshipTypesSelector, objectTypesSelector, settingsSelector, tagsSelector, userContextSelector, } from "../chatWindow/chatWindowSelectors.js";
7
- import { conversationMessagesByIdSelector, conversationSelector, messagesSelector, pendingAgentSwitchSelector, selectedAgentIdSelector, selectedEffortSelector, } from "../messages/messagesSelectors.js";
7
+ import { conversationEffortSelector, conversationMessagesByIdSelector, conversationSelector, messagesSelector, pendingAgentSwitchSelector, selectedAgentIdSelector, } from "../messages/messagesSelectors.js";
8
8
  import { applyPendingAgentSwitchAction, evaluateMessageAction, evaluateMessageCompleteAction, evaluateMessageErrorAction, evaluateMessageStreamingAction, evaluateMessageUpdateAction, revertAgentSwitchAction, setCurrentConversationAction, } from "../messages/messagesSlice.js";
9
9
  import { processContents } from "./converters/interactionsToMessages.js";
10
10
  import { convertToLocalContent } from "./converters/toLocalContent.js";
@@ -328,7 +328,7 @@ function* evaluateUserConversationMessage(conversation, userMessage, assistantMe
328
328
  const { includeTags, excludeTags } = yield select(tagsSelector);
329
329
  const allowedRelationshipTypes = yield select(allowedRelationshipTypesSelector);
330
330
  const context = yield select(userContextSelector);
331
- const selectedEffort = yield select(selectedEffortSelector);
331
+ const selectedEffort = yield select(conversationEffortSelector, conversation.localId);
332
332
  // Track interaction ID to assistant message mapping
333
333
  let currentUserMessage = userMessage;
334
334
  let currentAssistantMessage = assistantMessage;
package/esm/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type IChatConversationVisualisationContent } from "@gooddata/sdk-backend-spi";
2
- import { type GenAIObjectType, type IGenAIObjectReference, type IGenAIUserContext, type IGenAIVisualization, type ObjRef } from "@gooddata/sdk-model";
2
+ import { type GenAIChatEffort, type GenAIObjectType, type IGenAIObjectReference, type IGenAIUserContext, type IGenAIVisualization, type ObjRef } from "@gooddata/sdk-model";
3
3
  import { type IChatConversationLocalItem } from "./model.js";
4
4
  export type Config = IGenAIVisualization["config"] | NonNullable<IChatConversationVisualisationContent["visualization"]>["insight"]["properties"]["controls"];
5
5
  export type StoredConversation = {
@@ -34,6 +34,12 @@ export type StoredConversation = {
34
34
  agentId: string;
35
35
  previousAgentId: string | undefined;
36
36
  };
37
+ /**
38
+ * The effort this conversation runs at, seeded from its history when it is opened and
39
+ * overwritten whenever the user picks a different one. Undefined means nothing is recorded
40
+ * yet, the conversation runs at the default effort.
41
+ */
42
+ reasoningEffort?: GenAIChatEffort;
37
43
  };
38
44
  export type StoreContext = {
39
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,qCAAqC,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EACH,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,MAAM,EACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,MAAM,MAAM,GACZ,mBAAmB,CAAC,QAAQ,CAAC,GAC7B,WAAW,CACP,qCAAqC,CAAC,eAAe,CAAC,CACzD,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,CAAC;AAE7C,MAAM,MAAM,kBAAkB,GAAG;IAC7B;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IAClD;;;OAGG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,CAAC;IACnE;;;OAGG;IACH,kBAAkB,CAAC,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;KACvC,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B;;OAEG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,eAAe,GAAG,QAAQ,CAAC;IACjC,KAAK,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;IAC9C,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACnC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,qCAAqC,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EACH,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,MAAM,EACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,MAAM,MAAM,GACZ,mBAAmB,CAAC,QAAQ,CAAC,GAC7B,WAAW,CACP,qCAAqC,CAAC,eAAe,CAAC,CACzD,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,CAAC;AAE7C,MAAM,MAAM,kBAAkB,GAAG;IAC7B;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IAClD;;;OAGG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,CAAC;IACnE;;;OAGG;IACH,kBAAkB,CAAC,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;KACvC,CAAC;IACF;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B;;OAEG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,eAAe,GAAG,QAAQ,CAAC;IACjC,KAAK,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;IAC9C,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACnC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-gen-ai",
3
- "version": "11.52.0-alpha.5",
3
+ "version": "11.52.0-alpha.6",
4
4
  "description": "GoodData GenAI SDK",
5
5
  "license": "MIT",
6
6
  "author": "GoodData Corporation",
@@ -57,18 +57,18 @@
57
57
  "reselect": "5.1.1",
58
58
  "tslib": "2.8.1",
59
59
  "uuid": "11.1.1",
60
- "@gooddata/api-client-tiger": "11.52.0-alpha.5",
61
- "@gooddata/sdk-model": "11.52.0-alpha.5",
62
- "@gooddata/sdk-ui": "11.52.0-alpha.5",
63
- "@gooddata/sdk-backend-spi": "11.52.0-alpha.5",
64
- "@gooddata/sdk-ui-charts": "11.52.0-alpha.5",
65
- "@gooddata/sdk-ui-filters": "11.52.0-alpha.5",
66
- "@gooddata/sdk-ui-dashboard": "11.52.0-alpha.5",
67
- "@gooddata/sdk-ui-kit": "11.52.0-alpha.5",
68
- "@gooddata/sdk-ui-pivot": "11.52.0-alpha.5",
69
- "@gooddata/sdk-ui-semantic-search": "11.52.0-alpha.5",
70
- "@gooddata/util": "11.52.0-alpha.5",
71
- "@gooddata/sdk-ui-theme-provider": "11.52.0-alpha.5"
60
+ "@gooddata/api-client-tiger": "11.52.0-alpha.6",
61
+ "@gooddata/sdk-backend-spi": "11.52.0-alpha.6",
62
+ "@gooddata/sdk-model": "11.52.0-alpha.6",
63
+ "@gooddata/sdk-ui": "11.52.0-alpha.6",
64
+ "@gooddata/sdk-ui-charts": "11.52.0-alpha.6",
65
+ "@gooddata/sdk-ui-dashboard": "11.52.0-alpha.6",
66
+ "@gooddata/sdk-ui-filters": "11.52.0-alpha.6",
67
+ "@gooddata/sdk-ui-kit": "11.52.0-alpha.6",
68
+ "@gooddata/sdk-ui-pivot": "11.52.0-alpha.6",
69
+ "@gooddata/sdk-ui-semantic-search": "11.52.0-alpha.6",
70
+ "@gooddata/sdk-ui-theme-provider": "11.52.0-alpha.6",
71
+ "@gooddata/util": "11.52.0-alpha.6"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@microsoft/api-documenter": "^7.17.0",
@@ -111,13 +111,13 @@
111
111
  "typescript": "5.9.3",
112
112
  "vitest": "4.1.8",
113
113
  "vitest-dom": "0.1.1",
114
- "@gooddata/eslint-config": "11.52.0-alpha.5",
115
- "@gooddata/i18n-toolkit": "11.52.0-alpha.5",
116
- "@gooddata/oxlint-config": "11.52.0-alpha.5",
117
- "@gooddata/reference-workspace": "11.52.0-alpha.5",
118
- "@gooddata/sdk-backend-mockingbird": "11.52.0-alpha.5",
119
- "@gooddata/sdk-ui-theme-provider": "11.52.0-alpha.5",
120
- "@gooddata/stylelint-config": "11.52.0-alpha.5"
114
+ "@gooddata/eslint-config": "11.52.0-alpha.6",
115
+ "@gooddata/i18n-toolkit": "11.52.0-alpha.6",
116
+ "@gooddata/reference-workspace": "11.52.0-alpha.6",
117
+ "@gooddata/sdk-backend-mockingbird": "11.52.0-alpha.6",
118
+ "@gooddata/sdk-ui-theme-provider": "11.52.0-alpha.6",
119
+ "@gooddata/oxlint-config": "11.52.0-alpha.6",
120
+ "@gooddata/stylelint-config": "11.52.0-alpha.6"
121
121
  },
122
122
  "peerDependencies": {
123
123
  "react": "^18.0.0 || ^19.0.0",