@gooddata/sdk-ui-gen-ai 11.43.0-alpha.3 → 11.43.0-alpha.4

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 (58) hide show
  1. package/esm/components/ConfigContext.d.ts +5 -5
  2. package/esm/components/ConfigContext.d.ts.map +1 -1
  3. package/esm/components/ConfigContext.js +17 -8
  4. package/esm/components/GenAIChat.d.ts +1 -1
  5. package/esm/components/GenAIChat.d.ts.map +1 -1
  6. package/esm/components/GenAIChat.js +5 -4
  7. package/esm/components/GenAIChatDialog.d.ts +2 -2
  8. package/esm/components/GenAIChatDialog.d.ts.map +1 -1
  9. package/esm/components/GenAIChatDialog.js +4 -4
  10. package/esm/components/GenAiConversations.d.ts.map +1 -1
  11. package/esm/components/GenAiConversations.js +2 -2
  12. package/esm/components/GenAiStore.d.ts +9 -0
  13. package/esm/components/GenAiStore.d.ts.map +1 -1
  14. package/esm/components/GenAiStore.js +7 -4
  15. package/esm/components/hooks/useEndpointCheck.d.ts +1 -1
  16. package/esm/components/hooks/useEndpointCheck.d.ts.map +1 -1
  17. package/esm/components/messages/AssistantItem.d.ts +1 -1
  18. package/esm/components/messages/AssistantItem.d.ts.map +1 -1
  19. package/esm/components/messages/AssistantItem.js +8 -0
  20. package/esm/components/messages/AssistantItemFeedback.d.ts.map +1 -1
  21. package/esm/components/messages/AssistantItemFeedback.js +3 -0
  22. package/esm/components/messages/ItemsGroup.js +8 -10
  23. package/esm/components/messages/ToolItem.d.ts +1 -1
  24. package/esm/components/messages/ToolItem.d.ts.map +1 -1
  25. package/esm/components/messages/ToolItem.js +28 -14
  26. package/esm/components/messages/components/SemanticSearchTreeView.d.ts.map +1 -1
  27. package/esm/components/messages/components/SemanticSearchTreeView.js +2 -0
  28. package/esm/components/messages/contents/VisualizationContents.d.ts.map +1 -1
  29. package/esm/components/messages/contents/VisualizationContents.js +18 -3
  30. package/esm/components/messages/conversationContents/ConversationReasoningContent.d.ts.map +1 -1
  31. package/esm/components/messages/conversationContents/ConversationReasoningContent.js +1 -3
  32. package/esm/components/messages/conversationContents/ConversationVisualizationContent.d.ts.map +1 -1
  33. package/esm/components/messages/conversationContents/ConversationVisualizationContent.js +20 -5
  34. package/esm/hooks/useGenAIStore.d.ts +3 -0
  35. package/esm/hooks/useGenAIStore.d.ts.map +1 -1
  36. package/esm/hooks/useGenAIStore.js +4 -1
  37. package/esm/localization/bundles/en-US.localization-bundle.d.ts +0 -16
  38. package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  39. package/esm/localization/bundles/en-US.localization-bundle.js +0 -16
  40. package/esm/sdk-ui-gen-ai.d.ts +9 -1
  41. package/esm/store/messages/messagesSlice.d.ts +3 -1
  42. package/esm/store/messages/messagesSlice.d.ts.map +1 -1
  43. package/esm/store/messages/messagesSlice.js +37 -1
  44. package/esm/store/options.d.ts +8 -0
  45. package/esm/store/options.d.ts.map +1 -1
  46. package/esm/store/options.js +12 -0
  47. package/esm/store/sideEffects/onThreadLoad.d.ts +8 -3
  48. package/esm/store/sideEffects/onThreadLoad.d.ts.map +1 -1
  49. package/esm/store/sideEffects/onThreadLoad.js +24 -1
  50. package/esm/store/sideEffects/onVisualizationSuccessSave.d.ts +2 -1
  51. package/esm/store/sideEffects/onVisualizationSuccessSave.d.ts.map +1 -1
  52. package/esm/store/sideEffects/onVisualizationSuccessSave.js +29 -2
  53. package/package.json +20 -20
  54. package/styles/css/main.css +18 -0
  55. package/styles/css/main.css.map +1 -1
  56. package/styles/css/messages.css +18 -0
  57. package/styles/css/messages.css.map +1 -1
  58. package/styles/scss/messages.scss +23 -0
@@ -5,7 +5,7 @@ import { EventDispatcher } from "../store/events.js";
5
5
  import { OptionsDispatcher } from "../store/options.js";
6
6
  import { getStore } from "../store/store.js";
7
7
  export const useGenAIStore = (backend, workspace, opts) => {
8
- const { eventHandlers, colorPalette, settings, objectTypes, includeTags, excludeTags, catalogItems, isPreview, } = opts;
8
+ const { eventHandlers, colorPalette, settings, objectTypes, includeTags, excludeTags, catalogItems, isPreview, onLinkClick, allowNativeLinks, } = opts;
9
9
  // Instantiate EventDispatcher. It's a designed to hold a reference to the handlers, so that
10
10
  // we don't update the context every time a new array of handlers is passed.
11
11
  // Similar to how React handles event listeners.
@@ -25,6 +25,9 @@ export const useGenAIStore = (backend, workspace, opts) => {
25
25
  }));
26
26
  }
27
27
  }, [colorPalette, optionsDispatcher, store]);
28
+ useEffect(() => {
29
+ optionsDispatcher.setOnLinkClick(onLinkClick, allowNativeLinks);
30
+ }, [allowNativeLinks, colorPalette, onLinkClick, optionsDispatcher, store]);
28
31
  useEffect(() => {
29
32
  if (settings) {
30
33
  optionsDispatcher.setSettings(settings);
@@ -611,18 +611,10 @@ export declare const en_US: {
611
611
  text: string;
612
612
  crowdinContext: string;
613
613
  };
614
- "gd.gen-ai.message.label.tool": {
615
- text: string;
616
- crowdinContext: string;
617
- };
618
614
  "gd.gen-ai.message.reasoning.tool-call": {
619
615
  text: string;
620
616
  crowdinContext: string;
621
617
  };
622
- "gd.gen-ai.message.reasoning.tool-call.plain": {
623
- text: string;
624
- crowdinContext: string;
625
- };
626
618
  "gd.gen-ai.message.reasoned.tool-call": {
627
619
  text: string;
628
620
  crowdinContext: string;
@@ -631,18 +623,10 @@ export declare const en_US: {
631
623
  text: string;
632
624
  crowdinContext: string;
633
625
  };
634
- "gd.gen-ai.message.reasoning.tool-result.plain": {
635
- text: string;
636
- crowdinContext: string;
637
- };
638
626
  "gd.gen-ai.message.reasoned.tool-result": {
639
627
  text: string;
640
628
  crowdinContext: string;
641
629
  };
642
- "gd.gen-ai.message.reasoning.waiting_for_server": {
643
- text: string;
644
- crowdinContext: string;
645
- };
646
630
  "gd.gen-ai.skip-messages-history": {
647
631
  text: string;
648
632
  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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqsBjB,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqrBjB,CAAC"}
@@ -613,18 +613,10 @@ export const en_US = {
613
613
  "text": "Bot:",
614
614
  "crowdinContext": "Label identifying messages sent by the AI assistant in the chat conversation"
615
615
  },
616
- "gd.gen-ai.message.label.tool": {
617
- "text": "Tool:",
618
- "crowdinContext": "Label identifying messages sent by the AI assistant tool in the chat conversation"
619
- },
620
616
  "gd.gen-ai.message.reasoning.tool-call": {
621
617
  "text": "<b>Calling tool</b>: {name}",
622
618
  "crowdinContext": "Contextual label identifying the AI assistant tool call in the chat conversation"
623
619
  },
624
- "gd.gen-ai.message.reasoning.tool-call.plain": {
625
- "text": "Calling tool: \"{name}\"",
626
- "crowdinContext": "Contextual label identifying the AI assistant tool call in the chat conversation"
627
- },
628
620
  "gd.gen-ai.message.reasoned.tool-call": {
629
621
  "text": "<b>Called tool</b>: {name}",
630
622
  "crowdinContext": "Contextual label identifying the AI assistant tool call in the chat conversation"
@@ -633,18 +625,10 @@ export const en_US = {
633
625
  "text": "<b>Collecting data from tool</b>",
634
626
  "crowdinContext": "Contextual label identifying the AI assistant tool result in the chat conversation"
635
627
  },
636
- "gd.gen-ai.message.reasoning.tool-result.plain": {
637
- "text": "Collecting data from tool",
638
- "crowdinContext": "Contextual label identifying the AI assistant tool result in the chat conversation"
639
- },
640
628
  "gd.gen-ai.message.reasoned.tool-result": {
641
629
  "text": "<b>Collected data from tool</b>",
642
630
  "crowdinContext": "Contextual label identifying the AI assistant tool result in the chat conversation"
643
631
  },
644
- "gd.gen-ai.message.reasoning.waiting_for_server": {
645
- "text": "Waiting for response from server...",
646
- "crowdinContext": "Contextual label identifying that the AI assistant tool is waiting for a response from the server"
647
- },
648
632
  "gd.gen-ai.skip-messages-history": {
649
633
  "text": "Skip to AI assistant input",
650
634
  "crowdinContext": "Accessibility link to skip past the message history and go directly to the input field"
@@ -369,7 +369,7 @@ export declare type GenAIAssistantProps = Omit<GenAiStoreProps, "children"> & {
369
369
  * When provided, references to the metadata objects will be rendered as clickable links.
370
370
  * Otherwise, the metadata objects will be rendered as plain text (using object title).
371
371
  */
372
- onLinkClick?: (linkClickEvent: LinkHandlerEvent) => void;
372
+ onLinkClick?: (linkClickEvent: LinkHandlerEvent) => string | undefined;
373
373
  /**
374
374
  * When true, allows the chat to render links that open in a new tab or window. This
375
375
  * is handy only when embedding the chat in same environment where GD platform is running because
@@ -473,6 +473,14 @@ export declare type GenAiStoreProps = {
473
473
  * User settings to use for the chat UI.
474
474
  */
475
475
  settings?: IUserWorkspaceSettings;
476
+ /**
477
+ * Callback to handle link clicks.
478
+ */
479
+ onLinkClick?: (linkClickEvent: LinkHandlerEvent) => string | undefined;
480
+ /**
481
+ * Whether to allow native links to be opened in a new tab.
482
+ */
483
+ allowNativeLinks?: boolean;
476
484
  /**
477
485
  * Event handlers to subscribe to chat events.
478
486
  */
@@ -123,7 +123,9 @@ export declare const loadThreadAction: import("@reduxjs/toolkit").ActionCreatorW
123
123
  verbose: boolean;
124
124
  }, "messages/setVerboseAction">, setGlobalErrorAction: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
125
125
  error: Error;
126
- }, "messages/setGlobalErrorAction">, cancelAsyncAction: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"messages/cancelAsyncAction">, setUserFeedback: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
126
+ }, "messages/setGlobalErrorAction">, cancelAsyncAction: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"messages/cancelAsyncAction">, clearConversationLoadingAction: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
127
+ conversationLocalId?: string | undefined;
128
+ }, "messages/clearConversationLoadingAction">, setUserFeedback: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
127
129
  assistantMessageId: string;
128
130
  feedback: GenAIChatInteractionUserFeedback;
129
131
  userTextFeedback?: string | undefined;
@@ -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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"}
@@ -563,6 +563,23 @@ const messagesSlice = createSlice({
563
563
  state.globalError = errorToObject(error);
564
564
  },
565
565
  cancelAsyncAction: (state) => {
566
+ // Aborting the in-flight thread load. A conversation switch can move
567
+ // currentConversation between load-start (loadThreadAction) and this cancel
568
+ // (the useThreadLoading cleanup runs after the new conversation is already
569
+ // current), so keying the clear only to the live current conversation would
570
+ // orphan the "loading" flag on the conversation that was actually loading -
571
+ // its skeleton then spins forever when it is reopened (LX-2577). Clear the
572
+ // load flag wherever it sits; there is only ever one load in flight.
573
+ if (state.messageAsyncProcess === "loading" || state.messageAsyncProcess === "restoring") {
574
+ delete state.messageAsyncProcess;
575
+ }
576
+ for (const data of Object.values(state.conversationsData)) {
577
+ if (data.asyncProcess === "loading" || data.asyncProcess === "restoring") {
578
+ delete data.asyncProcess;
579
+ }
580
+ }
581
+ // Preserve the original behaviour for the current conversation's non-load
582
+ // async states (e.g. "evaluating"/"clearing").
566
583
  if (state.currentConversation) {
567
584
  const data = getConversationData(state.conversationsData, state.currentConversation.localId);
568
585
  delete data?.asyncProcess;
@@ -571,6 +588,25 @@ const messagesSlice = createSlice({
571
588
  delete state.messageAsyncProcess;
572
589
  }
573
590
  },
591
+ /**
592
+ * Clear the "loading"/"restoring" flag for a specific conversation.
593
+ *
594
+ * Used when a thread load is superseded by a newer one (takeLatest cancels the
595
+ * running onThreadLoad saga without dispatching cancelAsyncAction). The clear must
596
+ * target the conversation that was actually loading - identified by its localId -
597
+ * rather than whichever conversation is current now, which may already have changed.
598
+ */
599
+ clearConversationLoadingAction: (state, { payload: { conversationLocalId } }) => {
600
+ if (conversationLocalId) {
601
+ const data = state.conversationsData[conversationLocalId];
602
+ if (data?.asyncProcess === "loading" || data?.asyncProcess === "restoring") {
603
+ delete data.asyncProcess;
604
+ }
605
+ }
606
+ else if (state.messageAsyncProcess === "loading" || state.messageAsyncProcess === "restoring") {
607
+ delete state.messageAsyncProcess;
608
+ }
609
+ },
574
610
  setUserFeedback: (state, { payload, }) => {
575
611
  const conversationId = getConversationLocalId(state.currentConversation);
576
612
  const assistantMessage = getAssistantMessageStrict(state, payload.assistantMessageId, conversationId);
@@ -818,7 +854,7 @@ const messagesSlice = createSlice({
818
854
  });
819
855
  const errorToObject = (error) => Object.fromEntries(Object.getOwnPropertyNames(error).map((key) => [key, error[key]]));
820
856
  export const messagesSliceReducer = messagesSlice.reducer;
821
- export const { loadThreadAction, loadThreadErrorAction, loadThreadSuccessAction, loadConversationsSuccessAction, loadConversationSuccessAction, restoreCachedMessagesAction, clearThreadErrorAction, clearThreadSuccessAction, clearConversationSuccessAction, evaluateConversationTitleAction, evaluateMessageAction, evaluateMessageErrorAction, evaluateMessageStreamingAction, evaluateMessageUpdateAction, evaluateMessageCompleteAction, setMessagesAction, setVerboseAction, setGlobalErrorAction, cancelAsyncAction, setUserFeedback, setUserFeedbackError, clearUserFeedbackError, saveVisualizationAction, savedVisualizationAction, saveVisualizationErrorAction, saveVisualizationSuccessAction, saveVisualisationRenderStatusAction, saveVisualisationRenderStatusSuccessAction, visualizationErrorAction, setSelectedAgentAction, applyPendingAgentSwitchAction, revertAgentSwitchAction, setAgentsAction, pinConversationAction, pinConversationSuccessAction, pinConversationFailureAction, renameConversationAction, renameConversationSuccessAction, renameConversationFailureAction, deleteConversationAction, deleteConversationStartAction, deleteConversationSuccessAction, deleteConversationFailureAction,
857
+ export const { loadThreadAction, loadThreadErrorAction, loadThreadSuccessAction, loadConversationsSuccessAction, loadConversationSuccessAction, restoreCachedMessagesAction, clearThreadErrorAction, clearThreadSuccessAction, clearConversationSuccessAction, evaluateConversationTitleAction, evaluateMessageAction, evaluateMessageErrorAction, evaluateMessageStreamingAction, evaluateMessageUpdateAction, evaluateMessageCompleteAction, setMessagesAction, setVerboseAction, setGlobalErrorAction, cancelAsyncAction, clearConversationLoadingAction, setUserFeedback, setUserFeedbackError, clearUserFeedbackError, saveVisualizationAction, savedVisualizationAction, saveVisualizationErrorAction, saveVisualizationSuccessAction, saveVisualisationRenderStatusAction, saveVisualisationRenderStatusSuccessAction, visualizationErrorAction, setSelectedAgentAction, applyPendingAgentSwitchAction, revertAgentSwitchAction, setAgentsAction, pinConversationAction, pinConversationSuccessAction, pinConversationFailureAction, renameConversationAction, renameConversationSuccessAction, renameConversationFailureAction, deleteConversationAction, deleteConversationStartAction, deleteConversationSuccessAction, deleteConversationFailureAction,
822
858
  /**
823
859
  * @public
824
860
  */
@@ -1,5 +1,6 @@
1
1
  import { type IUserWorkspaceSettings } from "@gooddata/sdk-backend-spi";
2
2
  import { type CatalogItem, type GenAIObjectType, type IColorPalette } from "@gooddata/sdk-model";
3
+ import type { LinkHandlerEvent } from "../components/ConfigContext.js";
3
4
  /**
4
5
  * A dispatcher for chat events.
5
6
  * @internal
@@ -11,8 +12,15 @@ export declare class OptionsDispatcher {
11
12
  private includeTags;
12
13
  private excludeTags;
13
14
  private catalogItems;
15
+ private onLinkClick;
16
+ private allowNativeLinks;
14
17
  setColorPalette(colorPalette: IColorPalette | undefined): void;
15
18
  getColorPalette(): IColorPalette | undefined;
19
+ setOnLinkClick(onLinkClick?: (linkClickEvent: LinkHandlerEvent) => string | undefined, allowNativeLinks?: boolean): void;
20
+ getOnLinkClick(): {
21
+ onLinkClick?: (linkClickEvent: LinkHandlerEvent) => string | undefined;
22
+ allowNativeLinks?: boolean;
23
+ };
16
24
  setSettings(settings: IUserWorkspaceSettings | undefined): void;
17
25
  getSettings(): IUserWorkspaceSettings | undefined;
18
26
  setObjectTypes(objectTypes: GenAIObjectType[] | undefined): void;
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/store/options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEjG;;;GAGG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,QAAQ,CAAiD;IACjE,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAwC;IAErD,eAAe,CAAC,YAAY,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CAEpE;IAEM,eAAe,IAAI,aAAa,GAAG,SAAS,CAElD;IAEM,WAAW,CAAC,QAAQ,EAAE,sBAAsB,GAAG,SAAS,GAAG,IAAI,CAErE;IAEM,WAAW,IAAI,sBAAsB,GAAG,SAAS,CAEvD;IAEM,cAAc,CAAC,WAAW,EAAE,eAAe,EAAE,GAAG,SAAS,GAAG,IAAI,CAEtE;IAEM,cAAc,IAAI,eAAe,EAAE,GAAG,SAAS,CAErD;IAEM,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAGzF;IAEM,OAAO,IAAI;QAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;KAAE,CAKzF;IAEM,eAAe,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,SAAS,GAAG,IAAI,CAEpE;IAEM,eAAe,IAAI,WAAW,EAAE,GAAG,SAAS,CAElD;CACJ"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/store/options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEjG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAEvE;;;GAGG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,QAAQ,CAAiD;IACjE,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,WAAW,CAAqF;IACxG,OAAO,CAAC,gBAAgB,CAAkC;IAEnD,eAAe,CAAC,YAAY,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CAEpE;IAEM,eAAe,IAAI,aAAa,GAAG,SAAS,CAElD;IAEM,cAAc,CACjB,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,EACtE,gBAAgB,CAAC,EAAE,OAAO,GAC3B,IAAI,CAGN;IAEM,cAAc,IAAI;QACrB,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,CAAC;QACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAKA;IAEM,WAAW,CAAC,QAAQ,EAAE,sBAAsB,GAAG,SAAS,GAAG,IAAI,CAErE;IAEM,WAAW,IAAI,sBAAsB,GAAG,SAAS,CAEvD;IAEM,cAAc,CAAC,WAAW,EAAE,eAAe,EAAE,GAAG,SAAS,GAAG,IAAI,CAEtE;IAEM,cAAc,IAAI,eAAe,EAAE,GAAG,SAAS,CAErD;IAEM,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAGzF;IAEM,OAAO,IAAI;QAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;KAAE,CAKzF;IAEM,eAAe,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,SAAS,GAAG,IAAI,CAEpE;IAEM,eAAe,IAAI,WAAW,EAAE,GAAG,SAAS,CAElD;CACJ"}
@@ -10,12 +10,24 @@ export class OptionsDispatcher {
10
10
  includeTags = undefined;
11
11
  excludeTags = undefined;
12
12
  catalogItems = undefined;
13
+ onLinkClick = undefined;
14
+ allowNativeLinks = undefined;
13
15
  setColorPalette(colorPalette) {
14
16
  this.colorPalette = colorPalette;
15
17
  }
16
18
  getColorPalette() {
17
19
  return this.colorPalette;
18
20
  }
21
+ setOnLinkClick(onLinkClick, allowNativeLinks) {
22
+ this.onLinkClick = onLinkClick;
23
+ this.allowNativeLinks = allowNativeLinks;
24
+ }
25
+ getOnLinkClick() {
26
+ return {
27
+ onLinkClick: this.onLinkClick,
28
+ allowNativeLinks: this.allowNativeLinks,
29
+ };
30
+ }
19
31
  setSettings(settings) {
20
32
  this.settings = settings;
21
33
  }
@@ -1,10 +1,10 @@
1
1
  import { type IAnalyticalBackend, type IChatThreadHistory, type IUserWorkspaceSettings } from "@gooddata/sdk-backend-spi";
2
- import { type Message } from "../../model.js";
2
+ import { type IChatConversationLocal, type Message } from "../../model.js";
3
3
  /**
4
4
  * Load thread history and put it to the store.
5
5
  * @internal
6
6
  */
7
- export declare function onThreadLoad(): Generator<Generator<import("redux-saga/effects").CallEffect<void>, void, unknown> | Generator<import("redux-saga/effects").GetContextEffect | import("redux-saga/effects").PutEffect<{
7
+ export declare function onThreadLoad(): Generator<import("redux-saga/effects").CancelledEffect | Generator<import("redux-saga/effects").CallEffect<void>, void, unknown> | Generator<import("redux-saga/effects").GetContextEffect | import("redux-saga/effects").PutEffect<{
8
8
  payload: {
9
9
  messages: Message[];
10
10
  threadId: string;
@@ -23,7 +23,12 @@ export declare function onThreadLoad(): Generator<Generator<import("redux-saga/e
23
23
  error: Error;
24
24
  };
25
25
  type: "messages/loadThreadErrorAction";
26
- }> | import("redux-saga/effects").SelectEffect, void, IUserWorkspaceSettings | undefined>;
26
+ }> | import("redux-saga/effects").PutEffect<{
27
+ payload: {
28
+ conversationLocalId?: string | undefined;
29
+ };
30
+ type: "messages/clearConversationLoadingAction";
31
+ }> | import("redux-saga/effects").SelectEffect, void, (IChatConversationLocal | undefined) & ((IUserWorkspaceSettings & false) | (IUserWorkspaceSettings & true))>;
27
32
  /**
28
33
  * Merge backend-loaded messages with cached messages.
29
34
  * For each assistant message from the backend, if its content is missing semanticSearch
@@ -1 +1 @@
1
- {"version":3,"file":"onThreadLoad.d.ts","sourceRoot":"","sources":["../../../src/store/sideEffects/onThreadLoad.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,kBAAkB,EAKvB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC9B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAKH,KAAK,OAAO,EAIf,MAAM,gBAAgB,CAAC;AAsBxB;;;GAGG;AACH,wBAAiB,YAAY;;;;;;;;;;;;;;;;;;;0FAW5B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,eAAe,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CA+B/F"}
1
+ {"version":3,"file":"onThreadLoad.d.ts","sourceRoot":"","sources":["../../../src/store/sideEffects/onThreadLoad.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,kBAAkB,EAKvB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC9B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAGH,KAAK,sBAAsB,EAE3B,KAAK,OAAO,EAIf,MAAM,gBAAgB,CAAC;AAuBxB;;;GAGG;AACH,wBAAiB,YAAY;;;;;;;;;;;;;;;;;;;;;;;;mKAoC5B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,eAAe,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CA+B/F"}
@@ -4,7 +4,7 @@ import { isAssistantMessage, isSemanticSearchContents, makeConversationItem, } f
4
4
  import { settingsSelector } from "../chatWindow/chatWindowSelectors.js";
5
5
  import { loadMessages } from "../localStorage.js";
6
6
  import { conversationMessagesByIdSelector, conversationSelector, conversationsLoadedSelector, conversationsSelector, } from "../messages/messagesSelectors.js";
7
- import { cancelAsyncAction, loadConversationSuccessAction, loadConversationsSuccessAction, loadThreadErrorAction, loadThreadSuccessAction, restoreCachedMessagesAction, } from "../messages/messagesSlice.js";
7
+ import { cancelAsyncAction, clearConversationLoadingAction, loadConversationSuccessAction, loadConversationsSuccessAction, loadThreadErrorAction, loadThreadSuccessAction, restoreCachedMessagesAction, } from "../messages/messagesSlice.js";
8
8
  import { createEmptyConversation } from "../utils.js";
9
9
  import { interactionsToMessages } from "./converters/interactionsToMessages.js";
10
10
  import { convertToLocalContent } from "./converters/toLocalContent.js";
@@ -13,6 +13,13 @@ import { convertToLocalContent } from "./converters/toLocalContent.js";
13
13
  * @internal
14
14
  */
15
15
  export function* onThreadLoad() {
16
+ // Remember which conversation this load marked as "loading" (loadThreadAction keyed the
17
+ // flag to the conversation that was current when this saga was dispatched). If a newer
18
+ // load supersedes us, takeLatest cancels this saga without dispatching cancelAsyncAction,
19
+ // so we must clear that conversation's flag ourselves - otherwise its skeleton spins
20
+ // forever when reopened (LX-2577).
21
+ const loadingConversation = yield select(conversationSelector);
22
+ const loadingConversationLocalId = loadingConversation?.localId;
16
23
  try {
17
24
  const settings = yield select(settingsSelector);
18
25
  if (settings?.enableAiAgenticConversations) {
@@ -25,6 +32,22 @@ export function* onThreadLoad() {
25
32
  catch (e) {
26
33
  yield put(loadThreadErrorAction({ error: e }));
27
34
  }
35
+ finally {
36
+ const wasCancelled = yield cancelled();
37
+ if (wasCancelled) {
38
+ // Only clear when the load was genuinely orphaned, i.e. the conversation we were
39
+ // loading is no longer the current one (the user switched away mid-load). When a
40
+ // newer load supersedes us on the SAME conversation - e.g. a split layout mounts
41
+ // both GenAIConversations and GenAIAssistant and each useThreadLoading dispatches
42
+ // loadThreadAction - the replacement saga has already re-set the "loading" flag and
43
+ // is still fetching, so clearing it here would prematurely hide the skeleton and
44
+ // re-enable the input.
45
+ const currentConversation = yield select(conversationSelector);
46
+ if (currentConversation?.localId !== loadingConversationLocalId) {
47
+ yield put(clearConversationLoadingAction({ conversationLocalId: loadingConversationLocalId }));
48
+ }
49
+ }
50
+ }
28
51
  }
29
52
  /**
30
53
  * Merge backend-loaded messages with cached messages.
@@ -1,12 +1,13 @@
1
1
  import { type PayloadAction } from "@reduxjs/toolkit";
2
2
  import { type IAnalyticalBackend, type IUserWorkspaceSettings } from "@gooddata/sdk-backend-spi";
3
3
  import { type Message } from "../../model.js";
4
+ import { type OptionsDispatcher } from "../options.js";
4
5
  export declare function onVisualizationSuccessSave({ payload }: PayloadAction<{
5
6
  visualizationId: string;
6
7
  assistantMessageId: string;
7
8
  savedVisualizationId: string;
8
9
  explore: boolean;
9
- }>): Generator<import("redux-saga/effects").CallEffect<void> | import("redux-saga/effects").GetContextEffect | import("redux-saga/effects").SelectEffect, void, IAnalyticalBackend & string & import("@gooddata/sdk-backend-spi").IChatConversation & {
10
+ }>): Generator<import("redux-saga/effects").CallEffect<void> | import("redux-saga/effects").GetContextEffect | import("redux-saga/effects").SelectEffect, void, IAnalyticalBackend & string & OptionsDispatcher & import("@gooddata/sdk-backend-spi").IChatConversation & {
10
11
  localId: string;
11
12
  generatingTitle?: boolean | undefined;
12
13
  inProgress?: boolean | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"onVisualizationSuccessSave.d.ts","sourceRoot":"","sources":["../../../src/store/sideEffects/onVisualizationSuccessSave.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGjG,OAAO,EAA+B,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAK3E,wBAAiB,0BAA0B,CAAC,EACxC,OAAO,EACV,EAAE,aAAa,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;;;;wCAyCD"}
1
+ {"version":3,"file":"onVisualizationSuccessSave.d.ts","sourceRoot":"","sources":["../../../src/store/sideEffects/onVisualizationSuccessSave.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAItD,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGjG,OAAO,EAA+B,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAI3E,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,wBAAiB,0BAA0B,CAAC,EACxC,OAAO,EACV,EAAE,aAAa,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;;;;wCA0ED"}
@@ -1,4 +1,5 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
+ import noop from "lodash-es/noop.js";
2
3
  import { call, getContext, select } from "redux-saga/effects";
3
4
  import { getVisualizationHref } from "../../utils.js";
4
5
  import { settingsSelector } from "../chatWindow/chatWindowSelectors.js";
@@ -7,12 +8,26 @@ export function* onVisualizationSuccessSave({ payload, }) {
7
8
  // Retrieve backend from context
8
9
  const backend = yield getContext("backend");
9
10
  const workspace = yield getContext("workspace");
11
+ const options = yield getContext("optionsDispatcher");
10
12
  const conversation = yield select(conversationSelector);
11
13
  const settings = yield select(settingsSelector);
12
14
  const useHostedAnalyticalDesigner = Boolean(settings?.enableShellApplication_analyticalDesigner);
15
+ const { onLinkClick, allowNativeLinks } = options.getOnLinkClick();
13
16
  if (conversation) {
14
17
  if (payload.explore) {
15
- window.location.href = getVisualizationHref(workspace, payload.savedVisualizationId, useHostedAnalyticalDesigner);
18
+ if (allowNativeLinks) {
19
+ window.location.href = getVisualizationHref(workspace, payload.savedVisualizationId, useHostedAnalyticalDesigner);
20
+ }
21
+ else {
22
+ onLinkClick?.({
23
+ id: payload.savedVisualizationId,
24
+ type: "visualization",
25
+ workspaceId: workspace,
26
+ newTab: true,
27
+ preventDefault: noop,
28
+ itemUrl: getVisualizationHref(workspace, payload.savedVisualizationId, useHostedAnalyticalDesigner),
29
+ });
30
+ }
16
31
  }
17
32
  //NOTE: In new conversations, save call is already done before
18
33
  }
@@ -20,7 +35,19 @@ export function* onVisualizationSuccessSave({ payload, }) {
20
35
  const messages = yield select(messagesSelector);
21
36
  const message = messages.find((message) => message.localId === payload.assistantMessageId);
22
37
  if (payload.explore) {
23
- window.location.href = getVisualizationHref(workspace, payload.savedVisualizationId, useHostedAnalyticalDesigner);
38
+ if (allowNativeLinks) {
39
+ window.location.href = getVisualizationHref(workspace, payload.savedVisualizationId, useHostedAnalyticalDesigner);
40
+ }
41
+ else {
42
+ onLinkClick?.({
43
+ id: payload.savedVisualizationId,
44
+ type: "visualization",
45
+ workspaceId: workspace,
46
+ newTab: true,
47
+ preventDefault: noop,
48
+ itemUrl: getVisualizationHref(workspace, payload.savedVisualizationId, useHostedAnalyticalDesigner),
49
+ });
50
+ }
24
51
  }
25
52
  if (!message?.id) {
26
53
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-gen-ai",
3
- "version": "11.43.0-alpha.3",
3
+ "version": "11.43.0-alpha.4",
4
4
  "description": "GoodData GenAI SDK",
5
5
  "license": "MIT",
6
6
  "author": "GoodData Corporation",
@@ -56,18 +56,18 @@
56
56
  "reselect": "5.1.1",
57
57
  "tslib": "2.8.1",
58
58
  "uuid": "11.1.1",
59
- "@gooddata/api-client-tiger": "11.43.0-alpha.3",
60
- "@gooddata/sdk-backend-spi": "11.43.0-alpha.3",
61
- "@gooddata/sdk-ui-charts": "11.43.0-alpha.3",
62
- "@gooddata/sdk-model": "11.43.0-alpha.3",
63
- "@gooddata/sdk-ui-dashboard": "11.43.0-alpha.3",
64
- "@gooddata/sdk-ui": "11.43.0-alpha.3",
65
- "@gooddata/sdk-ui-kit": "11.43.0-alpha.3",
66
- "@gooddata/sdk-ui-filters": "11.43.0-alpha.3",
67
- "@gooddata/sdk-ui-pivot": "11.43.0-alpha.3",
68
- "@gooddata/sdk-ui-semantic-search": "11.43.0-alpha.3",
69
- "@gooddata/util": "11.43.0-alpha.3",
70
- "@gooddata/sdk-ui-theme-provider": "11.43.0-alpha.3"
59
+ "@gooddata/api-client-tiger": "11.43.0-alpha.4",
60
+ "@gooddata/sdk-backend-spi": "11.43.0-alpha.4",
61
+ "@gooddata/sdk-model": "11.43.0-alpha.4",
62
+ "@gooddata/sdk-ui": "11.43.0-alpha.4",
63
+ "@gooddata/sdk-ui-charts": "11.43.0-alpha.4",
64
+ "@gooddata/sdk-ui-dashboard": "11.43.0-alpha.4",
65
+ "@gooddata/sdk-ui-filters": "11.43.0-alpha.4",
66
+ "@gooddata/sdk-ui-kit": "11.43.0-alpha.4",
67
+ "@gooddata/sdk-ui-semantic-search": "11.43.0-alpha.4",
68
+ "@gooddata/sdk-ui-pivot": "11.43.0-alpha.4",
69
+ "@gooddata/sdk-ui-theme-provider": "11.43.0-alpha.4",
70
+ "@gooddata/util": "11.43.0-alpha.4"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@microsoft/api-documenter": "^7.17.0",
@@ -110,13 +110,13 @@
110
110
  "typescript": "5.9.3",
111
111
  "vitest": "4.1.8",
112
112
  "vitest-dom": "0.1.1",
113
- "@gooddata/eslint-config": "11.43.0-alpha.3",
114
- "@gooddata/i18n-toolkit": "11.43.0-alpha.3",
115
- "@gooddata/oxlint-config": "11.43.0-alpha.3",
116
- "@gooddata/sdk-backend-mockingbird": "11.43.0-alpha.3",
117
- "@gooddata/reference-workspace": "11.43.0-alpha.3",
118
- "@gooddata/sdk-ui-theme-provider": "11.43.0-alpha.3",
119
- "@gooddata/stylelint-config": "11.43.0-alpha.3"
113
+ "@gooddata/eslint-config": "11.43.0-alpha.4",
114
+ "@gooddata/i18n-toolkit": "11.43.0-alpha.4",
115
+ "@gooddata/oxlint-config": "11.43.0-alpha.4",
116
+ "@gooddata/reference-workspace": "11.43.0-alpha.4",
117
+ "@gooddata/sdk-backend-mockingbird": "11.43.0-alpha.4",
118
+ "@gooddata/sdk-ui-theme-provider": "11.43.0-alpha.4",
119
+ "@gooddata/stylelint-config": "11.43.0-alpha.4"
120
120
  },
121
121
  "peerDependencies": {
122
122
  "react": "^18.0.0 || ^19.0.0",
@@ -13852,6 +13852,24 @@ body.gd-kda-dialog-opened .highcharts-tooltip-container {
13852
13852
  .gd-gen-ai-chat__messages__conversation-group--content .gd-gen-ai-chat__messages__conversation--isLast .gd-gen-ai-chat__icon .gd-gen-ai-chat__icon__special {
13853
13853
  animation: pulsate-opacity 1s infinite ease-in-out;
13854
13854
  }
13855
+ .gd-gen-ai-chat__messages__conversation-group--content--loading {
13856
+ position: relative;
13857
+ padding-left: 15px;
13858
+ }
13859
+ .gd-gen-ai-chat__messages__conversation-group--content--loading::before {
13860
+ content: "";
13861
+ position: absolute;
13862
+ left: 5px;
13863
+ top: 0;
13864
+ bottom: 16px;
13865
+ width: 1px;
13866
+ background-color: var(--gd-palette-complementary-6, #94a1ad);
13867
+ opacity: 0.3;
13868
+ }
13869
+ .gd-gen-ai-chat__messages__conversation-group--content--loading--spinner svg {
13870
+ width: 16px;
13871
+ height: 16px;
13872
+ }
13855
13873
 
13856
13874
  .gd-gen-ai-chat__messages__conversation {
13857
13875
  display: flex;