@gooddata/sdk-ui-gen-ai 11.48.0-alpha.0 → 11.48.0-alpha.1

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 (68) hide show
  1. package/NOTICE +1 -1
  2. package/esm/components/GenAIChatContextIndicator.d.ts +7 -0
  3. package/esm/components/GenAIChatContextIndicator.d.ts.map +1 -0
  4. package/esm/components/GenAIChatContextIndicator.js +35 -0
  5. package/esm/components/GenAIChatDialogConnected.d.ts +8 -1
  6. package/esm/components/GenAIChatDialogConnected.d.ts.map +1 -1
  7. package/esm/components/GenAIChatDialogConnected.js +10 -2
  8. package/esm/components/GenAiChatAgentSwitching.d.ts +14 -0
  9. package/esm/components/GenAiChatAgentSwitching.d.ts.map +1 -0
  10. package/esm/components/GenAiChatAgentSwitching.js +81 -0
  11. package/esm/components/GenAiChatContextChooser.d.ts +8 -0
  12. package/esm/components/GenAiChatContextChooser.d.ts.map +1 -0
  13. package/esm/components/GenAiChatContextChooser.js +43 -0
  14. package/esm/components/Input.d.ts.map +1 -1
  15. package/esm/components/Input.js +23 -54
  16. package/esm/components/hooks/useContextItems.d.ts +7 -0
  17. package/esm/components/hooks/useContextItems.d.ts.map +1 -0
  18. package/esm/components/hooks/useContextItems.js +31 -0
  19. package/esm/components/utils/icons.d.ts +7 -0
  20. package/esm/components/utils/icons.d.ts.map +1 -0
  21. package/esm/components/utils/icons.js +16 -0
  22. package/esm/context/addContextReference.d.ts +4 -0
  23. package/esm/context/addContextReference.d.ts.map +1 -0
  24. package/esm/context/addContextReference.js +19 -0
  25. package/esm/context/build.d.ts +7 -0
  26. package/esm/context/build.d.ts.map +1 -0
  27. package/esm/context/build.js +18 -0
  28. package/esm/context/collectContextReferences.d.ts +11 -0
  29. package/esm/context/collectContextReferences.d.ts.map +1 -0
  30. package/esm/context/collectContextReferences.js +29 -0
  31. package/esm/context/dashboard.d.ts +21 -0
  32. package/esm/context/dashboard.d.ts.map +1 -0
  33. package/esm/context/dashboard.js +144 -0
  34. package/esm/context/isReferenceChanged.d.ts +3 -0
  35. package/esm/context/isReferenceChanged.d.ts.map +1 -0
  36. package/esm/context/isReferenceChanged.js +7 -0
  37. package/esm/context/referencedObjects.d.ts +10 -0
  38. package/esm/context/referencedObjects.d.ts.map +1 -0
  39. package/esm/context/referencedObjects.js +19 -0
  40. package/esm/context/removeContextReference.d.ts +4 -0
  41. package/esm/context/removeContextReference.d.ts.map +1 -0
  42. package/esm/context/removeContextReference.js +26 -0
  43. package/esm/context.d.ts +5 -0
  44. package/esm/context.d.ts.map +1 -0
  45. package/esm/context.js +6 -0
  46. package/esm/internal.d.ts +2 -2
  47. package/esm/internal.d.ts.map +1 -1
  48. package/esm/internal.js +2 -2
  49. package/esm/localization/bundles/en-US.localization-bundle.d.ts +4 -0
  50. package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  51. package/esm/localization/bundles/en-US.localization-bundle.js +4 -0
  52. package/esm/store/chatWindow/chatWindowSelectors.d.ts +9 -1
  53. package/esm/store/chatWindow/chatWindowSelectors.d.ts.map +1 -1
  54. package/esm/store/chatWindow/chatWindowSelectors.js +14 -1
  55. package/esm/store/chatWindow/chatWindowSlice.d.ts +20 -7
  56. package/esm/store/chatWindow/chatWindowSlice.d.ts.map +1 -1
  57. package/esm/store/chatWindow/chatWindowSlice.js +34 -4
  58. package/esm/store/sideEffects/onUserMessage.d.ts.map +1 -1
  59. package/esm/store/sideEffects/onUserMessage.js +14 -10
  60. package/esm/types.d.ts +20 -1
  61. package/esm/types.d.ts.map +1 -1
  62. package/package.json +21 -20
  63. package/styles/css/input.css +7 -0
  64. package/styles/css/input.css.map +1 -1
  65. package/styles/css/main.css +19 -1
  66. package/styles/css/main.css.map +1 -1
  67. package/styles/scss/input.scss +8 -0
  68. package/styles/scss/main.scss +11 -0
package/NOTICE CHANGED
@@ -9,7 +9,7 @@ The following 3rd-party software packages may be used by or distributed with goo
9
9
 
10
10
  Date generated: 2026-7-16
11
11
 
12
- Revision ID: a9c1bae6689fa76eb7a3de0ef1c0e7153ce0579c
12
+ Revision ID: 673cff1911eb24f1e212d2c51b5463b98c9b6c96
13
13
 
14
14
  ================================================================================
15
15
  ================================================================================
@@ -0,0 +1,7 @@
1
+ import { type FC } from "react";
2
+ type GenAIChatContextIndicatorOwnProps = {
3
+ onDelete?: () => void;
4
+ };
5
+ export declare const GenAIChatContextIndicator: FC<GenAIChatContextIndicatorOwnProps>;
6
+ export {};
7
+ //# sourceMappingURL=GenAIChatContextIndicator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenAIChatContextIndicator.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatContextIndicator.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,EAAe,MAAM,OAAO,CAAC;AAY7C,KAAK,iCAAiC,GAAG;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAoDF,eAAO,MAAM,yBAAyB,EAAE,EAAE,CAAC,iCAAiC,CAG5C,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback } from "react";
4
+ import { connect, useSelector } from "react-redux";
5
+ import { UiChip } from "@gooddata/sdk-ui-kit";
6
+ import { collectContextReferences } from "../context/collectContextReferences.js";
7
+ import { effectiveContextSelector } from "../store/chatWindow/chatWindowSelectors.js";
8
+ import { removeAmbientUserContextAction } from "../store/chatWindow/chatWindowSlice.js";
9
+ import { getIconByType } from "./utils/icons.js";
10
+ /**
11
+ * Shows what ambient context the assistant is answering about — the open dashboard and its live
12
+ * filters (e.g. "Answering about: Revenue Dashboard · Region: Europe · Q1 2026"). Renders nothing
13
+ * when no ambient dashboard context is present. Re-renders whenever the host re-syncs the context,
14
+ * so filter changes on the dashboard are reflected immediately.
15
+ *
16
+ * @internal
17
+ */
18
+ function GenAIChatContextIndicatorCore({ removeAmbientUserContext, onDelete, }) {
19
+ const { ambient } = useSelector(effectiveContextSelector);
20
+ const ambientReferences = collectContextReferences(ambient, "ambient");
21
+ const onAmbientDelete = useCallback(() => {
22
+ return () => {
23
+ removeAmbientUserContext();
24
+ onDelete?.();
25
+ };
26
+ }, [removeAmbientUserContext, onDelete]);
27
+ if (ambientReferences.length === 0) {
28
+ return null;
29
+ }
30
+ return (_jsx("div", { className: "gd-gen-ai-chat__context-indicator", "aria-live": "polite", children: ambientReferences.map((reference, index) => (_jsx(UiChip, { ...getIconByType(reference.type), label: reference.title, isExpandable: false, isDeletable: true, onDelete: onAmbientDelete() }, index))) }));
31
+ }
32
+ const mapDispatchToProps = {
33
+ removeAmbientUserContext: removeAmbientUserContextAction,
34
+ };
35
+ export const GenAIChatContextIndicator = connect(null, mapDispatchToProps)(GenAIChatContextIndicatorCore);
@@ -72,6 +72,13 @@ export interface IGenAIChatDialogConnectedProps {
72
72
  askSeq?: number;
73
73
  /** Context of the user's location when the question was asked, sent alongside the seeded question. */
74
74
  userContext?: IGenAIUserContext;
75
+ /**
76
+ * Ambient user context kept in sync by the host (e.g. the open dashboard and its live filter
77
+ * state). Unlike the one-shot `userContext` it persists across messages: it is attached to
78
+ * every message that carries no one-shot context and drives the context indicator in the chat.
79
+ * Pass `undefined` to clear it (e.g. when the user leaves the dashboard).
80
+ */
81
+ ambientUserContext?: IGenAIUserContext;
75
82
  /** When true, the seeded question is appended to the existing thread instead of clearing it first. */
76
83
  appendToChat?: boolean;
77
84
  /** Object-search tag scope reflecting the caller's current view. */
@@ -104,5 +111,5 @@ export interface IGenAIChatDialogConnectedProps {
104
111
  *
105
112
  * @internal
106
113
  */
107
- export declare function GenAIChatDialogConnected({ backend, workspace, locale, canManage, canAnalyze, canFullControl, settings, isOpen, onOpen, onClose, askedQuestion, askSeq, userContext, appendToChat, includeTags, excludeTags, objectTypes: objectTypesOverride, onEvent, onAnyEvent, dialogPosition, className, colorPalette, allowNativeLinks, onLinkClick, returnFocusTo }: IGenAIChatDialogConnectedProps): import("react/jsx-runtime").JSX.Element;
114
+ export declare function GenAIChatDialogConnected({ backend, workspace, locale, canManage, canAnalyze, canFullControl, settings, isOpen, onOpen, onClose, askedQuestion, askSeq, userContext, ambientUserContext, appendToChat, includeTags, excludeTags, objectTypes: objectTypesOverride, onEvent, onAnyEvent, dialogPosition, className, colorPalette, allowNativeLinks, onLinkClick, returnFocusTo }: IGenAIChatDialogConnectedProps): import("react/jsx-runtime").JSX.Element;
108
115
  //# sourceMappingURL=GenAIChatDialogConnected.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GenAIChatDialogConnected.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatDialogConnected.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GenAIChatDialogConnected.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatDialogConnected.tsx"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // (C) 2026 GoodData Corporation
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { makeTextContents, makeUserItem, makeUserMessage } from "../model.js";
5
- import { setUserContextAction } from "../store/chatWindow/chatWindowSlice.js";
5
+ import { setAmbientUserContextAction, setUserContextAction } from "../store/chatWindow/chatWindowSlice.js";
6
6
  import { isChatAssistantMessageEvent, isChatClosedEvent, isChatCopyToClipboardEvent, isChatFeedbackErrorEvent, isChatFeedbackEvent, isChatOpenedEvent, isChatResetEvent, isChatSaveVisualizationErrorEvent, isChatSaveVisualizationSuccessEvent, isChatUserMessageEvent, } from "../store/events.js";
7
7
  import { clearThreadAction, newMessageAction } from "../store/messages/messagesSlice.js";
8
8
  import { GenAIChatDialog } from "./GenAIChatDialog.js";
@@ -17,7 +17,7 @@ import { GenAIChatDialog } from "./GenAIChatDialog.js";
17
17
  *
18
18
  * @internal
19
19
  */
20
- export function GenAIChatDialogConnected({ backend, workspace, locale, canManage, canAnalyze, canFullControl, settings, isOpen, onOpen, onClose, askedQuestion, askSeq, userContext, appendToChat, includeTags, excludeTags, objectTypes: objectTypesOverride, onEvent, onAnyEvent, dialogPosition, className, colorPalette, allowNativeLinks = true, onLinkClick, returnFocusTo, }) {
20
+ export function GenAIChatDialogConnected({ backend, workspace, locale, canManage, canAnalyze, canFullControl, settings, isOpen, onOpen, onClose, askedQuestion, askSeq, userContext, ambientUserContext, appendToChat, includeTags, excludeTags, objectTypes: objectTypesOverride, onEvent, onAnyEvent, dialogPosition, className, colorPalette, allowNativeLinks = true, onLinkClick, returnFocusTo, }) {
21
21
  const defaultLinkClick = useCallback(({ itemUrl, newTab, preventDefault }) => {
22
22
  if (itemUrl) {
23
23
  preventDefault();
@@ -86,6 +86,14 @@ export function GenAIChatDialogConnected({ backend, workspace, locale, canManage
86
86
  const onDispatcher = useCallback((dispatcher) => {
87
87
  setDispatcher(() => dispatcher);
88
88
  }, []);
89
+ // Mirror the host-provided ambient context into the chat store whenever it changes,
90
+ // including `undefined` to clear it when the user leaves the context (e.g. the dashboard).
91
+ useEffect(() => {
92
+ if (!chatDispatcher) {
93
+ return;
94
+ }
95
+ chatDispatcher(setAmbientUserContextAction({ userContext: ambientUserContext }));
96
+ }, [chatDispatcher, ambientUserContext]);
89
97
  // The token of the last seed we applied. Each ask is identified by `askSeq` (bumped on every ask,
90
98
  // so even a repeated identical question re-seeds); we seed once per token. Without this guard the
91
99
  // effect would replay the question whenever `settings`/`userContext` merely change object identity.
@@ -0,0 +1,14 @@
1
+ import { type FC, type MouseEvent, type ReactNode } from "react";
2
+ type GenAiChatAgentSwitchingOwnProps = {
3
+ disabled: boolean;
4
+ agentDropdownDisabled: boolean;
5
+ isAssistantLoading: boolean;
6
+ handleSubmit: () => void;
7
+ onMouseDown?: (event: MouseEvent<HTMLDivElement>) => void;
8
+ setBusy: (busy: boolean) => void;
9
+ setNoAgents: (noAgents: boolean) => void;
10
+ leftContent?: ReactNode;
11
+ };
12
+ export declare const GenAiChatAgentSwitching: FC<GenAiChatAgentSwitchingOwnProps>;
13
+ export {};
14
+ //# sourceMappingURL=GenAiChatAgentSwitching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenAiChatAgentSwitching.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatAgentSwitching.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAA0B,MAAM,OAAO,CAAC;AAkCzF,KAAK,+BAA+B,GAAG;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC1D,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,SAAS,CAAC;CAC3B,CAAC;AA0LF,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,+BAA+B,CAG1C,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback, useEffect } from "react";
4
+ import cx from "classnames";
5
+ import { defineMessages, useIntl } from "react-intl";
6
+ import { connect } from "react-redux";
7
+ import { UiIconButton, UiTooltip } from "@gooddata/sdk-ui-kit";
8
+ import { agentSwitchingActiveSelector, agentSwitchingEnabledSelector, } from "../store/chatWindow/chatWindowSelectors.js";
9
+ import { agentsSelector, conversationSelector, conversationsLoadedSelector, conversationsSelector, selectedAgentIdSelector, } from "../store/messages/messagesSelectors.js";
10
+ import { setSelectedAgentAction } from "../store/messages/messagesSlice.js";
11
+ import { GenAIChatAgentDropdown } from "./GenAIChatAgentDropdown.js";
12
+ import { getAgentSelectionStatus } from "./utils/agentSelection.js";
13
+ const msgs = defineMessages({
14
+ send: {
15
+ id: "gd.gen-ai.button.send",
16
+ },
17
+ noAgentAvailable: {
18
+ id: "gd.gen-ai.agent.unavailable",
19
+ },
20
+ });
21
+ function GenAiChatAgentSwitchingCore({ agentSwitchingEnabled, isAssistantLoading, handleSubmit, conversations, conversation, agentDropdownDisabled, conversationsLoaded, agents, selectedAgentId, agentSwitchingActive, disabled, onMouseDown, setSelectedAgent, setBusy, setNoAgents, leftContent, }) {
22
+ const intl = useIntl();
23
+ const sendLabel = intl.formatMessage(msgs.send);
24
+ const noAgentAvailableLabel = intl.formatMessage(msgs.noAgentAvailable);
25
+ const { availableAgents, hasNoAgents, isSelectionLoading } = getAgentSelectionStatus({
26
+ agentSwitchingActive,
27
+ assistantLoading: isAssistantLoading,
28
+ conversationsLoaded,
29
+ agents,
30
+ selectedAgentId,
31
+ });
32
+ const buttonDisabled = disabled || (agentSwitchingActive && hasNoAgents);
33
+ const isBusy = agentSwitchingActive && (hasNoAgents || isSelectionLoading);
34
+ const handleSubmitHandler = useCallback(() => {
35
+ if (agentSwitchingActive && hasNoAgents) {
36
+ return;
37
+ }
38
+ if (isBusy) {
39
+ return;
40
+ }
41
+ handleSubmit();
42
+ }, [agentSwitchingActive, handleSubmit, hasNoAgents, isBusy]);
43
+ const handleSelectAgent = useCallback((agentId, options) => {
44
+ setSelectedAgent({
45
+ agentId,
46
+ previousAgentId: conversation?.agentId ?? selectedAgentId,
47
+ showChangeEvent: options?.showChangeEvent,
48
+ });
49
+ }, [conversation?.agentId, selectedAgentId, setSelectedAgent]);
50
+ useEffect(() => {
51
+ setBusy?.(isBusy);
52
+ }, [isBusy, setBusy]);
53
+ useEffect(() => {
54
+ setNoAgents?.(hasNoAgents);
55
+ }, [setNoAgents, hasNoAgents]);
56
+ return (_jsxs("div", { className: cx({
57
+ "gd-gen-ai-chat__input__actions": agentSwitchingEnabled,
58
+ "gd-gen-ai-chat__input__send_button": !agentSwitchingEnabled,
59
+ "gd-gen-ai-chat__input__send_button--disabled": !agentSwitchingEnabled && buttonDisabled,
60
+ }), onMouseDown: agentSwitchingEnabled ? onMouseDown : undefined, children: [leftContent, agentSwitchingActive && hasNoAgents ? (_jsx("span", { className: "gd-gen-ai-chat__input__no-agent", "data-testid": "no_agent_available", role: "status", "aria-live": "polite", "aria-atomic": "true", children: noAgentAvailableLabel })) : agentSwitchingEnabled ? (_jsxs(_Fragment, { children: [agentSwitchingActive ? (_jsx(GenAIChatAgentDropdown, { agents: availableAgents, conversations: conversations, conversationAgentId: conversation?.agentId, selectedAgentId: selectedAgentId, isDisabled: agentDropdownDisabled || isSelectionLoading, isLoading: isSelectionLoading, onSelectAgent: handleSelectAgent })) : null, _jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "arrowUp", variant: "primary", size: "small", dataTestId: "send_message", isDisabled: buttonDisabled, onClick: buttonDisabled ? undefined : handleSubmitHandler, accessibilityConfig: {
61
+ ariaLabel: sendLabel,
62
+ } }), content: sendLabel })
63
+ ] })) : (_jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "send", variant: "tertiary", size: "medium", dataTestId: "send_message", isDisabled: buttonDisabled, onClick: buttonDisabled ? undefined : handleSubmitHandler, accessibilityConfig: {
64
+ ariaLabel: sendLabel,
65
+ } }), content: sendLabel }))] }));
66
+ }
67
+ const mapStateToProps = (state) => {
68
+ return {
69
+ conversation: conversationSelector(state),
70
+ conversations: conversationsSelector(state),
71
+ conversationsLoaded: conversationsLoadedSelector(state),
72
+ agents: agentsSelector(state),
73
+ agentSwitchingEnabled: agentSwitchingEnabledSelector(state),
74
+ agentSwitchingActive: agentSwitchingActiveSelector(state),
75
+ selectedAgentId: selectedAgentIdSelector(state),
76
+ };
77
+ };
78
+ const mapDispatchToProps = {
79
+ setSelectedAgent: setSelectedAgentAction,
80
+ };
81
+ export const GenAiChatAgentSwitching = connect(mapStateToProps, mapDispatchToProps)(GenAiChatAgentSwitchingCore);
@@ -0,0 +1,8 @@
1
+ import { type FC } from "react";
2
+ import { type IGenAIContextObject } from "../context/collectContextReferences.js";
3
+ type GenAiChatContextChooserOwnProps = {
4
+ onAddContext?: (context: IGenAIContextObject) => void;
5
+ };
6
+ export declare const GenAiChatContextChooser: FC<GenAiChatContextChooserOwnProps>;
7
+ export {};
8
+ //# sourceMappingURL=GenAiChatContextChooser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenAiChatContextChooser.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooser.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAQhC,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAOlF,KAAK,+BAA+B,GAAG;IACnC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACzD,CAAC;AA4FF,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,+BAA+B,CAG1C,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { defineMessages, useIntl } from "react-intl";
3
+ import { connect } from "react-redux";
4
+ import { Dropdown, UiIconButton, UiMenu, UiSubmenuHeader } from "@gooddata/sdk-ui-kit";
5
+ import { ambientContextSelector, effectiveContextSelector } from "../store/chatWindow/chatWindowSelectors.js";
6
+ import { addContextReferenceAction } from "../store/chatWindow/chatWindowSlice.js";
7
+ import { useContextItems } from "./hooks/useContextItems.js";
8
+ const msgs = defineMessages({
9
+ add: {
10
+ id: "gd.gen-ai.context.add_context",
11
+ },
12
+ });
13
+ function GenAiChatContextChooserCore({ currentAmbient, selectedAmbient, addContextReference, onAddContext, }) {
14
+ const intl = useIntl();
15
+ const items = useContextItems(currentAmbient, selectedAmbient, "ambient");
16
+ if (!currentAmbient) {
17
+ return null;
18
+ }
19
+ return (_jsx("div", { className: "gd-gen-ai-chat__input__context", children: _jsx(Dropdown, { alignPoints: [{ align: "tl bl", offset: { x: 0, y: 0 } }], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, accessibilityConfig: {}, renderButton: ({ isOpen, toggleDropdown, accessibilityConfig }) => (_jsx(UiIconButton, { icon: "plus", variant: "tertiary", size: "small", dataTestId: "choose_context", isActive: isOpen, accessibilityConfig: {
20
+ ...accessibilityConfig,
21
+ ariaLabel: intl.formatMessage(msgs.add),
22
+ }, onClick: toggleDropdown, isDisabled: !items.length })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx(UiMenu, { dataTestId: "agent_dropdown_menu", items: items, size: "medium", minWidth: 245, maxWidth: 245, containerTopPadding: "small", containerBottomPadding: "small", MenuHeader: ContextMenuHeader, ariaAttributes: ariaAttributes, onSelect: (item) => {
23
+ addContextReference({ object: item.data });
24
+ onAddContext?.(item.data);
25
+ closeDropdown();
26
+ } })) }) }));
27
+ }
28
+ const mapStateToProps = (state) => {
29
+ const currentAmbient = ambientContextSelector(state);
30
+ const { ambient } = effectiveContextSelector(state);
31
+ return {
32
+ currentAmbient,
33
+ selectedAmbient: ambient,
34
+ };
35
+ };
36
+ const mapDispatchToProps = {
37
+ addContextReference: addContextReferenceAction,
38
+ };
39
+ export const GenAiChatContextChooser = connect(mapStateToProps, mapDispatchToProps)(GenAiChatContextChooserCore);
40
+ function ContextMenuHeader() {
41
+ const intl = useIntl();
42
+ return _jsx(UiSubmenuHeader, { title: intl.formatMessage(msgs.add), height: "medium" });
43
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,EAAE,EACP,KAAK,SAAS,EASjB,MAAM,OAAO,CAAC;AAyCf,MAAM,MAAM,aAAa,GAAG;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;CACzC,CAAC;AAiYF,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,aAAa,CAAgE,CAAC"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,EAAE,EACP,KAAK,SAAS,EAQjB,MAAM,OAAO,CAAC;AAmCf,MAAM,MAAM,aAAa,GAAG;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;CACzC,CAAC;AAqRF,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,aAAa,CAAgE,CAAC"}
@@ -1,20 +1,21 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // (C) 2024-2026 GoodData Corporation
3
- import { useCallback, useEffect, useMemo, useReducer, useRef, useState, } from "react";
3
+ import { useEffect, useMemo, useReducer, useRef, useState, } from "react";
4
4
  import cx from "classnames";
5
5
  import { FormattedMessage, defineMessages, useIntl } from "react-intl";
6
6
  import { connect } from "react-redux";
7
- import { SyntaxHighlightingInput, UiIconButton, UiTooltip } from "@gooddata/sdk-ui-kit";
7
+ import { SyntaxHighlightingInput } from "@gooddata/sdk-ui-kit";
8
8
  import { makeTextContents, makeUserItem, makeUserMessage, } from "../model.js";
9
- import { agentSwitchingActiveSelector, agentSwitchingEnabledSelector, } from "../store/chatWindow/chatWindowSelectors.js";
10
- import { agentsSelector, asyncProcessSelector, conversationMessagesSelector, conversationSelector, conversationsLoadedSelector, conversationsSelector, messagesSelector, selectedAgentIdSelector, } from "../store/messages/messagesSelectors.js";
9
+ import { agentSwitchingEnabledSelector } from "../store/chatWindow/chatWindowSelectors.js";
10
+ import { asyncProcessSelector, conversationMessagesSelector, conversationSelector, messagesSelector, } from "../store/messages/messagesSelectors.js";
11
11
  import { newMessageAction, setSelectedAgentAction } from "../store/messages/messagesSlice.js";
12
12
  import { collectReferences } from "./completion/references.js";
13
13
  import { useCompletion } from "./completion/useCompletion.js";
14
- import { GenAIChatAgentDropdown } from "./GenAIChatAgentDropdown.js";
14
+ import { GenAiChatAgentSwitching } from "./GenAiChatAgentSwitching.js";
15
+ import { GenAiChatContextChooser } from "./GenAiChatContextChooser.js";
16
+ import { GenAIChatContextIndicator } from "./GenAIChatContextIndicator.js";
15
17
  import { useHighlight } from "./highlight/useHighlight.js";
16
18
  import { useFullscreenCheck } from "./hooks/useFullscreenCheck.js";
17
- import { getAgentSelectionStatus } from "./utils/agentSelection.js";
18
19
  import { escapeMarkdown } from "./utils/markdownUtils.js";
19
20
  const msgs = defineMessages({
20
21
  placeholder: {
@@ -26,31 +27,20 @@ const msgs = defineMessages({
26
27
  labelWin: {
27
28
  id: "gd.gen-ai.input-label.win",
28
29
  },
29
- send: {
30
- id: "gd.gen-ai.button.send",
31
- },
32
- noAgentAvailable: {
33
- id: "gd.gen-ai.agent.unavailable",
34
- },
35
30
  });
36
31
  const isMac = typeof navigator !== "undefined" &&
37
32
  (navigator.platform.toUpperCase().indexOf("MAC") >= 0 || navigator.userAgent.includes("Macintosh"));
38
- function InputComponent({ isBusy, isEvaluating, newMessage, autofocus = false, canManage, canAnalyze, targetRef, messages, conversation, conversations, conversationsLoaded, items, agents, agentSwitchingEnabled, agentSwitchingActive, loading, selectedAgentId, setSelectedAgent, }) {
33
+ function InputComponent({ isBusy, isEvaluating, newMessage, autofocus = false, canManage, canAnalyze, targetRef, messages, conversation, items, agentSwitchingEnabled, loading, }) {
39
34
  const intl = useIntl();
40
35
  const { isBigScreen, isSmallScreen, isFullscreen } = useFullscreenCheck();
41
36
  const isLoading = loading === "loading" || loading === "clearing";
42
37
  const isAssistantLoading = isLoading || loading === "restoring";
43
38
  const isEmpty = conversation ? !items?.length && !isLoading : !messages?.length && !isLoading;
44
39
  const [value, setValue] = useState("");
40
+ const [areAgentsBusy, setAreAgentsBusy] = useState(true);
41
+ const [hasNoAgents, setHasNoAgents] = useState(false);
45
42
  const [editorApi, setApi] = useState(null);
46
43
  const [focused, setFocused] = useState(false);
47
- const { availableAgents, hasNoAgents, isSelectionLoading } = getAgentSelectionStatus({
48
- agentSwitchingActive,
49
- assistantLoading: isAssistantLoading,
50
- conversationsLoaded,
51
- agents,
52
- selectedAgentId,
53
- });
54
44
  const { onCompletion, used } = useCompletion([], { canManage, canAnalyze });
55
45
  const { highlightExtension, atomicCursorExtension } = useHighlight(used);
56
46
  const beforeExtensions = useMemo(() => [atomicCursorExtension], [atomicCursorExtension]);
@@ -87,9 +77,6 @@ function InputComponent({ isBusy, isEvaluating, newMessage, autofocus = false, c
87
77
  forceFocusOnce.current = true;
88
78
  }, []);
89
79
  const handleSubmit = () => {
90
- if (agentSwitchingActive && hasNoAgents) {
91
- return;
92
- }
93
80
  let item;
94
81
  if (conversation) {
95
82
  item = makeUserItem({
@@ -109,7 +96,7 @@ function InputComponent({ isBusy, isEvaluating, newMessage, autofocus = false, c
109
96
  const handleKeyDown = (e) => {
110
97
  if (e.key === "Enter" && !e.shiftKey) {
111
98
  const trimmed = value.trim();
112
- if (isBusy || !trimmed || (agentSwitchingActive && (hasNoAgents || isSelectionLoading))) {
99
+ if (isBusy || !trimmed || areAgentsBusy) {
113
100
  return true;
114
101
  }
115
102
  e.preventDefault();
@@ -126,17 +113,15 @@ function InputComponent({ isBusy, isEvaluating, newMessage, autofocus = false, c
126
113
  e.preventDefault();
127
114
  editorApi?.focus();
128
115
  };
129
- const agentDropdownDisabled = isBusy || isEvaluating || isSelectionLoading;
130
- const buttonDisabled = !value.trim() || agentDropdownDisabled || (agentSwitchingActive && hasNoAgents);
131
- const handleSelectAgent = useCallback((agentId, options) => {
132
- setSelectedAgent({
133
- agentId,
134
- previousAgentId: conversation?.agentId ?? selectedAgentId,
135
- showChangeEvent: options?.showChangeEvent,
136
- });
137
- }, [conversation?.agentId, selectedAgentId, setSelectedAgent]);
138
- const sendLabel = intl.formatMessage(msgs.send);
139
- const noAgentAvailableLabel = intl.formatMessage(msgs.noAgentAvailable);
116
+ const handleContextMouseDown = (e) => {
117
+ e.preventDefault();
118
+ editorApi?.focus();
119
+ };
120
+ const handleOnFocus = () => {
121
+ editorApi?.focus();
122
+ };
123
+ const agentDropdownDisabled = isBusy || isEvaluating;
124
+ const buttonDisabled = !value.trim() || agentDropdownDisabled;
140
125
  return (_jsx("div", { className: cx("gd-gen-ai-chat__input", {
141
126
  focused,
142
127
  "gd-gen-ai-chat__input--fullscreen": isFullscreen,
@@ -147,9 +132,7 @@ function InputComponent({ isBusy, isEvaluating, newMessage, autofocus = false, c
147
132
  "gd-gen-ai-chat__input--no-agents": hasNoAgents,
148
133
  }), children: _jsxs("div", { className: "gd-gen-ai-chat__input__content", children: [
149
134
  _jsx(HintText, { focused: focused, where: "top" }), _jsxs("div", { className: "gd-gen-ai-chat__input__container", children: [
150
- _jsx("div", { ref: targetRef, onFocus: () => {
151
- editorApi?.focus();
152
- } }), _jsx("div", { className: "gd-gen-ai-chat__input__text", children: _jsx(SyntaxHighlightingInput, { className: "gd-gen-ai-chat__input__mc", placeholder: intl.formatMessage(msgs.placeholder), label: isMac ? intl.formatMessage(msgs.labelMac) : intl.formatMessage(msgs.labelWin), value: value, autocompletion: {
135
+ _jsx("div", { className: "gd-gen-ai-chat__input__context", onMouseDown: handleContextMouseDown, children: _jsx(GenAIChatContextIndicator, { onDelete: handleOnFocus }) }), _jsx("div", { ref: targetRef, onFocus: handleOnFocus }), _jsx("div", { className: "gd-gen-ai-chat__input__text", children: _jsx(SyntaxHighlightingInput, { className: "gd-gen-ai-chat__input__mc", placeholder: intl.formatMessage(msgs.placeholder), label: isMac ? intl.formatMessage(msgs.labelMac) : intl.formatMessage(msgs.labelWin), value: value, autocompletion: {
153
136
  aboveCursor: true,
154
137
  whenTyping: true,
155
138
  whenTypingDelay: 300,
@@ -157,16 +140,7 @@ function InputComponent({ isBusy, isEvaluating, newMessage, autofocus = false, c
157
140
  setFocused(true);
158
141
  }, onBlur: () => {
159
142
  setFocused(false);
160
- }, onKeyDown: handleKeyDown, onCompletion: onCompletion }) }), _jsx("div", { className: cx({
161
- "gd-gen-ai-chat__input__actions": agentSwitchingEnabled,
162
- "gd-gen-ai-chat__input__send_button": !agentSwitchingEnabled,
163
- "gd-gen-ai-chat__input__send_button--disabled": !agentSwitchingEnabled && buttonDisabled,
164
- }), onMouseDown: agentSwitchingEnabled ? handleActionsMouseDown : undefined, children: agentSwitchingActive && hasNoAgents ? (_jsx("span", { className: "gd-gen-ai-chat__input__no-agent", "data-testid": "no_agent_available", role: "status", "aria-live": "polite", "aria-atomic": "true", children: noAgentAvailableLabel })) : agentSwitchingEnabled ? (_jsxs(_Fragment, { children: [agentSwitchingActive ? (_jsx(GenAIChatAgentDropdown, { agents: availableAgents, conversations: conversations, conversationAgentId: conversation?.agentId, selectedAgentId: selectedAgentId, isDisabled: agentDropdownDisabled, isLoading: isSelectionLoading, onSelectAgent: handleSelectAgent })) : null, _jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "arrowUp", variant: "primary", size: "small", dataTestId: "send_message", isDisabled: buttonDisabled, onClick: buttonDisabled ? undefined : handleSubmit, accessibilityConfig: {
165
- ariaLabel: sendLabel,
166
- } }), content: sendLabel })
167
- ] })) : (_jsx(UiTooltip, { triggerBy: ["focus", "hover"], arrowPlacement: "bottom", anchor: _jsx(UiIconButton, { icon: "send", variant: "tertiary", size: "medium", dataTestId: "send_message", isDisabled: buttonDisabled, onClick: buttonDisabled ? undefined : handleSubmit, accessibilityConfig: {
168
- ariaLabel: sendLabel,
169
- } }), content: sendLabel })) })
143
+ }, onKeyDown: handleKeyDown, onCompletion: onCompletion }) }), _jsx(GenAiChatAgentSwitching, { disabled: buttonDisabled, isAssistantLoading: isAssistantLoading, agentDropdownDisabled: agentDropdownDisabled, handleSubmit: handleSubmit, onMouseDown: handleActionsMouseDown, setBusy: setAreAgentsBusy, setNoAgents: setHasNoAgents, leftContent: _jsx(GenAiChatContextChooser, { onAddContext: handleOnFocus }) })
170
144
  ] }), _jsx(HintText, { focused: focused, where: "bottom" })
171
145
  ] }) }));
172
146
  }
@@ -185,15 +159,10 @@ const mapStateToProps = (state) => {
185
159
  const asyncState = asyncProcessSelector(state);
186
160
  return {
187
161
  conversation: conversationSelector(state),
188
- conversations: conversationsSelector(state),
189
- conversationsLoaded: conversationsLoadedSelector(state),
190
162
  items: conversationMessagesSelector(state),
191
163
  messages: messagesSelector(state),
192
164
  loading: asyncState,
193
- agents: agentsSelector(state),
194
165
  agentSwitchingEnabled: agentSwitchingEnabledSelector(state),
195
- agentSwitchingActive: agentSwitchingActiveSelector(state),
196
- selectedAgentId: selectedAgentIdSelector(state),
197
166
  isBusy: !!asyncState,
198
167
  isEvaluating: asyncState === "evaluating",
199
168
  };
@@ -0,0 +1,7 @@
1
+ import { type IGenAIUserContext } from "@gooddata/sdk-model";
2
+ import { type IUiMenuItem } from "@gooddata/sdk-ui-kit";
3
+ import { type IGenAIContextObject } from "../../context/collectContextReferences.js";
4
+ export declare function useContextItems(current: IGenAIUserContext | undefined, selected: IGenAIUserContext | undefined, type: "ambient" | "user"): IUiMenuItem<{
5
+ interactive: IGenAIContextObject;
6
+ }>[];
7
+ //# sourceMappingURL=useContextItems.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useContextItems.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useContextItems.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,KAAK,WAAW,EAAU,MAAM,sBAAsB,CAAC;AAEhE,OAAO,EACH,KAAK,mBAAmB,EAE3B,MAAM,2CAA2C,CAAC;AAGnD,wBAAgB,eAAe,CAC3B,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,QAAQ,EAAE,iBAAiB,GAAG,SAAS,EACvC,IAAI,EAAE,SAAS,GAAG,MAAM,GACzB,WAAW,CAAC;IAAE,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,EAAE,CAgCrD"}
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useMemo } from "react";
4
+ import { UiIcon } from "@gooddata/sdk-ui-kit";
5
+ import { collectContextReferences, } from "../../context/collectContextReferences.js";
6
+ import { getIconByType } from "../utils/icons.js";
7
+ export function useContextItems(current, selected, type) {
8
+ return useMemo(() => {
9
+ const items = [];
10
+ const currentReferences = collectContextReferences(current, type);
11
+ const selectedReferences = collectContextReferences(selected, type);
12
+ currentReferences.forEach((reference) => {
13
+ const isSelected = selectedReferences.some((selectedReference) => selectedReference.id === reference.id && selectedReference.type === reference.type);
14
+ if (!isSelected) {
15
+ const icon = getIconByType(reference.type);
16
+ items.push({
17
+ type: "interactive",
18
+ id: reference.id,
19
+ data: reference,
20
+ stringTitle: reference.title,
21
+ ...(icon.iconBefore
22
+ ? {
23
+ iconLeft: _jsx(UiIcon, { type: icon.iconBefore, color: icon.iconColor }),
24
+ }
25
+ : {}),
26
+ });
27
+ }
28
+ });
29
+ return items;
30
+ }, [current, selected, type]);
31
+ }
@@ -0,0 +1,7 @@
1
+ import { type GenAIObjectType } from "@gooddata/sdk-model";
2
+ import { type IconType, type ThemeColor } from "@gooddata/sdk-ui-kit";
3
+ export declare function getIconByType(type: GenAIObjectType): {
4
+ iconBefore?: IconType;
5
+ iconColor?: ThemeColor;
6
+ };
7
+ //# sourceMappingURL=icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/components/utils/icons.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEtE,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG;IAAE,UAAU,CAAC,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,UAAU,CAAA;CAAE,CActG"}
@@ -0,0 +1,16 @@
1
+ // (C) 2026 GoodData Corporation
2
+ export function getIconByType(type) {
3
+ switch (type) {
4
+ case "dashboard":
5
+ return {
6
+ iconBefore: "dashboard",
7
+ iconColor: "complementary-6",
8
+ };
9
+ case "visualization":
10
+ return {
11
+ iconBefore: "visualization",
12
+ };
13
+ default:
14
+ return {};
15
+ }
16
+ }
@@ -0,0 +1,4 @@
1
+ import { type StoreContext } from "../types.js";
2
+ import type { IGenAIContextObject } from "./collectContextReferences.js";
3
+ export declare function addContextReference(context: StoreContext, reference?: IGenAIContextObject): StoreContext;
4
+ //# sourceMappingURL=addContextReference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addContextReference.d.ts","sourceRoot":"","sources":["../../src/context/addContextReference.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,mBAAmB,GAAG,YAAY,CAoBxG"}
@@ -0,0 +1,19 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { areObjRefsEqual } from "@gooddata/sdk-model";
3
+ export function addContextReference(context, reference) {
4
+ const { ambient } = context;
5
+ if (!reference) {
6
+ return context;
7
+ }
8
+ if (reference.where === "view.dashboard") {
9
+ const ambientRef = ambient?.view?.dashboard?.ref;
10
+ const ref = reference.ref;
11
+ if (areObjRefsEqual(ambientRef, ref)) {
12
+ return {
13
+ ...context,
14
+ ambientMode: "enabled",
15
+ };
16
+ }
17
+ }
18
+ return context;
19
+ }
@@ -0,0 +1,7 @@
1
+ import type { IGenAIUserContext } from "@gooddata/sdk-model";
2
+ export declare function buildContext(props: Partial<IGenAIUserContext>): IGenAIUserContext;
3
+ /**
4
+ * @internal
5
+ */
6
+ export declare function mergeContexts(...contexts: IGenAIUserContext[]): IGenAIUserContext;
7
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/context/build.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,CAIjF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,QAAQ,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,CAQjF"}
@@ -0,0 +1,18 @@
1
+ // (C) 2026 GoodData Corporation
2
+ export function buildContext(props) {
3
+ return {
4
+ ...props,
5
+ };
6
+ }
7
+ /**
8
+ * @internal
9
+ */
10
+ export function mergeContexts(...contexts) {
11
+ return contexts.reduce((acc, context) => {
12
+ return {
13
+ view: context.view ?? acc.view,
14
+ activeObject: context.activeObject ?? acc.activeObject,
15
+ referencedObjects: [...(acc?.referencedObjects ?? []), ...(context?.referencedObjects ?? [])],
16
+ };
17
+ }, {});
18
+ }
@@ -0,0 +1,11 @@
1
+ import { type GenAIObjectType, type IGenAIUserContext, type ObjRef } from "@gooddata/sdk-model";
2
+ export interface IGenAIContextObject {
3
+ id: string;
4
+ ref: ObjRef;
5
+ title: string;
6
+ type: GenAIObjectType;
7
+ where: "view.dashboard";
8
+ nesting: number;
9
+ }
10
+ export declare function collectContextReferences(context: IGenAIUserContext | undefined, type: "ambient" | "user"): IGenAIContextObject[];
11
+ //# sourceMappingURL=collectContextReferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collectContextReferences.d.ts","sourceRoot":"","sources":["../../src/context/collectContextReferences.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,MAAM,EAEd,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,mBAAmB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,wBAAwB,CACpC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,IAAI,EAAE,SAAS,GAAG,MAAM,GACzB,mBAAmB,EAAE,CA6BvB"}