@gooddata/sdk-ui-gen-ai 11.47.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.
- package/NOTICE +1 -1
- package/esm/components/GenAIChatContextIndicator.d.ts +7 -0
- package/esm/components/GenAIChatContextIndicator.d.ts.map +1 -0
- package/esm/components/GenAIChatContextIndicator.js +35 -0
- package/esm/components/GenAIChatDialogConnected.d.ts +8 -1
- package/esm/components/GenAIChatDialogConnected.d.ts.map +1 -1
- package/esm/components/GenAIChatDialogConnected.js +10 -2
- package/esm/components/GenAiChatAgentSwitching.d.ts +14 -0
- package/esm/components/GenAiChatAgentSwitching.d.ts.map +1 -0
- package/esm/components/GenAiChatAgentSwitching.js +81 -0
- package/esm/components/GenAiChatContextChooser.d.ts +8 -0
- package/esm/components/GenAiChatContextChooser.d.ts.map +1 -0
- package/esm/components/GenAiChatContextChooser.js +43 -0
- package/esm/components/Input.d.ts.map +1 -1
- package/esm/components/Input.js +23 -54
- package/esm/components/hooks/useContextItems.d.ts +7 -0
- package/esm/components/hooks/useContextItems.d.ts.map +1 -0
- package/esm/components/hooks/useContextItems.js +31 -0
- package/esm/components/utils/icons.d.ts +7 -0
- package/esm/components/utils/icons.d.ts.map +1 -0
- package/esm/components/utils/icons.js +16 -0
- package/esm/context/addContextReference.d.ts +4 -0
- package/esm/context/addContextReference.d.ts.map +1 -0
- package/esm/context/addContextReference.js +19 -0
- package/esm/context/build.d.ts +7 -0
- package/esm/context/build.d.ts.map +1 -0
- package/esm/context/build.js +18 -0
- package/esm/context/collectContextReferences.d.ts +11 -0
- package/esm/context/collectContextReferences.d.ts.map +1 -0
- package/esm/context/collectContextReferences.js +29 -0
- package/esm/context/dashboard.d.ts +21 -0
- package/esm/context/dashboard.d.ts.map +1 -0
- package/esm/context/dashboard.js +144 -0
- package/esm/context/isReferenceChanged.d.ts +3 -0
- package/esm/context/isReferenceChanged.d.ts.map +1 -0
- package/esm/context/isReferenceChanged.js +7 -0
- package/esm/context/referencedObjects.d.ts +10 -0
- package/esm/context/referencedObjects.d.ts.map +1 -0
- package/esm/context/referencedObjects.js +19 -0
- package/esm/context/removeContextReference.d.ts +4 -0
- package/esm/context/removeContextReference.d.ts.map +1 -0
- package/esm/context/removeContextReference.js +26 -0
- package/esm/context.d.ts +5 -0
- package/esm/context.d.ts.map +1 -0
- package/esm/context.js +6 -0
- package/esm/internal.d.ts +2 -2
- package/esm/internal.d.ts.map +1 -1
- package/esm/internal.js +2 -2
- package/esm/localization/bundles/en-US.localization-bundle.d.ts +4 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-US.localization-bundle.js +4 -0
- package/esm/store/chatWindow/chatWindowSelectors.d.ts +9 -1
- package/esm/store/chatWindow/chatWindowSelectors.d.ts.map +1 -1
- package/esm/store/chatWindow/chatWindowSelectors.js +14 -1
- package/esm/store/chatWindow/chatWindowSlice.d.ts +20 -7
- package/esm/store/chatWindow/chatWindowSlice.d.ts.map +1 -1
- package/esm/store/chatWindow/chatWindowSlice.js +34 -4
- package/esm/store/sideEffects/onUserMessage.d.ts.map +1 -1
- package/esm/store/sideEffects/onUserMessage.js +14 -10
- package/esm/types.d.ts +20 -1
- package/esm/types.d.ts.map +1 -1
- package/package.json +21 -20
- package/styles/css/input.css +7 -0
- package/styles/css/input.css.map +1 -1
- package/styles/css/main.css +19 -1
- package/styles/css/main.css.map +1 -1
- package/styles/scss/input.scss +8 -0
- 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:
|
|
12
|
+
Revision ID: 673cff1911eb24f1e212d2c51b5463b98c9b6c96
|
|
13
13
|
|
|
14
14
|
================================================================================
|
|
15
15
|
================================================================================
|
|
@@ -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":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAqD,MAAM,OAAO,CAAC;AAE1F,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI7F,OAAO,EACH,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,+BAA+B,EACpC,KAAK,iCAAiC,EACtC,KAAK,oBAAoB,EAW5B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D;;;;;;;;;GASG;AACH,MAAM,MAAM,uBAAuB,GAC7B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,yBAAyB,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,4BAA4B,CAAC;IAAC,OAAO,EAAE,iCAAiC,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,0BAA0B,CAAC;IAAC,OAAO,EAAE,+BAA+B,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,wBAAwB,CAAA;CAAE,CAAC;AAIvE;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC3C,uEAAuE;IACvE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAElC,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sGAAsG;IACtG,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,sGAAsG;IACtG,YAAY,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GenAIChatDialogConnected.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatDialogConnected.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAqD,MAAM,OAAO,CAAC;AAE1F,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI7F,OAAO,EACH,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,+BAA+B,EACpC,KAAK,iCAAiC,EACtC,KAAK,oBAAoB,EAW5B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D;;;;;;;;;GASG;AACH,MAAM,MAAM,uBAAuB,GAC7B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,yBAAyB,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,4BAA4B,CAAC;IAAC,OAAO,EAAE,iCAAiC,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,0BAA0B,CAAC;IAAC,OAAO,EAAE,+BAA+B,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,wBAAwB,CAAA;CAAE,CAAC;AAIvE;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC3C,uEAAuE;IACvE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAElC,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sGAAsG;IACtG,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,iBAAiB,CAAC;IACvC,sGAAsG;IACtG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,wGAAwG;IACxG,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAEhC,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACnD,sFAAsF;IACtF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAExC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE,iDAAiD;IACjD,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC;CAC1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,EACrC,OAAO,EACP,SAAS,EACT,MAAM,EACN,SAAS,EACT,UAAU,EACV,cAAc,EACd,QAAQ,EACR,MAAM,EACN,MAAM,EACN,OAAO,EACP,aAAa,EACb,MAAM,EACN,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EAAE,mBAAmB,EAChC,OAAO,EACP,UAAU,EACV,cAAc,EACd,SAAS,EACT,YAAY,EACZ,gBAAuB,EACvB,WAAW,EACX,aAAa,EAChB,EAAE,8BAA8B,2CAoIhC"}
|
|
@@ -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,
|
|
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"}
|
package/esm/components/Input.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2024-2026 GoodData Corporation
|
|
3
|
-
import {
|
|
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
|
|
7
|
+
import { SyntaxHighlightingInput } from "@gooddata/sdk-ui-kit";
|
|
8
8
|
import { makeTextContents, makeUserItem, makeUserMessage, } from "../model.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
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 {
|
|
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,
|
|
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 ||
|
|
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
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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(
|
|
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"}
|