diff --git a/x-pack/platform/packages/shared/ai-assistant-default-llm-setting/src/components/default_ai_connector.tsx b/x-pack/platform/packages/shared/ai-assistant-default-llm-setting/src/components/default_ai_connector.tsx index 0c54697b68896..3bc640dd0745a 100644 --- a/x-pack/platform/packages/shared/ai-assistant-default-llm-setting/src/components/default_ai_connector.tsx +++ b/x-pack/platform/packages/shared/ai-assistant-default-llm-setting/src/components/default_ai_connector.tsx @@ -313,7 +313,10 @@ export const DefaultAIConnector: React.FC = ({ connectors, settings }) => onChange={onChangeDefaultLlm} isDisabled={fields[GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR]?.isReadOnly} isLoading={connectors.loading} - isInvalid={selectedOptions.length === 0 && !connectors.loading} + isInvalid={ + (selectedOptions.length === 0 && !connectors.loading) || + (defaultLlmOnlyValue && selectedOptions[0]?.value === NO_DEFAULT_CONNECTOR) + } /> diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/api/chat_complete/use_chat_complete.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/api/chat_complete/use_chat_complete.ts index 550ccda6e15aa..ea9e45b0591c4 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/api/chat_complete/use_chat_complete.ts +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/api/chat_complete/use_chat_complete.ts @@ -26,10 +26,10 @@ interface UseChatComplete { // useChatComplete uses the same api as useSendMessage (post_actions_connector_execute) but without requiring conversationId/apiConfig // it is meant to be used for one-off messages that don't require a conversation export const useChatComplete = ({ connectorId }: { connectorId: string }): UseChatComplete => { - const { alertsIndexPattern, http, traceOptions } = useAssistantContext(); + const { alertsIndexPattern, http, traceOptions, settings } = useAssistantContext(); const [isLoading, setIsLoading] = useState(false); const abortController = useRef(new AbortController()); - const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true }); + const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true, settings }); const actionTypeId = useMemo( () => connectors?.find(({ id }) => id === connectorId)?.actionTypeId ?? '.gen-ai', [connectors, connectorId] diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx index c00e40606223e..4bc8b918fc612 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx @@ -11,8 +11,8 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; import { FormattedMessage } from '@kbn/i18n-react'; import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; -import { PromptResponse } from '@kbn/elastic-assistant-common'; -import { Conversation } from '../../../..'; +import type { PromptResponse } from '@kbn/elastic-assistant-common'; +import { useAssistantContext, type Conversation } from '../../../..'; import * as i18n from './translations'; import * as i18nModel from '../../../connectorland/models/model_selector/translations'; @@ -49,8 +49,10 @@ export const ConversationSettingsEditor: React.FC { + const { settings } = useAssistantContext(); const { data: connectors, isSuccess: areConnectorsFetched } = useLoadConnectors({ http, + settings, }); const [conversationUpdates, setConversationUpdates] = useState(selectedConversation); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.test.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.test.ts index 186a3f82691db..7339f29bdefb7 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.test.ts +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.test.ts @@ -6,7 +6,9 @@ */ import { getDefaultConnector, getOptionalRequestParams } from './helpers'; -import { AIConnector } from '../connectorland/connector_selector'; +import type { AIConnector } from '../connectorland/connector_selector'; +import type { SettingsStart } from '@kbn/core-ui-settings-browser'; +import { GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR } from '@kbn/management-settings-ids'; describe('helpers', () => { describe('getDefaultConnector', () => { @@ -25,41 +27,97 @@ describe('helpers', () => { apiUrl: 'https://api.openai.com/v1/chat/completions', }, }; + + const connector2: AIConnector = { + ...defaultConnector, + id: 'c7f91dc0-2197-11ee-aded-897192c5d633', + name: 'OpenAI', + config: { + apiProvider: 'OpenAI 2', + apiUrl: 'https://api.openai.com/v1/chat/completions', + }, + }; + + const clientGet = jest.fn(); + + const settings = { + client: { + get: clientGet, + }, + } as unknown as SettingsStart; + + beforeEach(() => { + jest.clearAllMocks(); + clientGet.mockImplementation((key: string) => { + return undefined; + }); + }); + it('should return undefined if connectors array is undefined', () => { const connectors = undefined; - const result = getDefaultConnector(connectors); + const result = getDefaultConnector(connectors, settings); expect(result).toBeUndefined(); }); it('should return undefined if connectors array is empty', () => { const connectors: AIConnector[] = []; - const result = getDefaultConnector(connectors); + const result = getDefaultConnector(connectors, settings); expect(result).toBeUndefined(); }); - it('should return the connector id if there is only one connector', () => { + it('should return the first connector if there is only one connector available', () => { const connectors: AIConnector[] = [defaultConnector]; - const result = getDefaultConnector(connectors); + const result = getDefaultConnector(connectors, settings); expect(result).toBe(connectors[0]); }); - it('should return the connector id if there are multiple connectors', () => { - const connectors: AIConnector[] = [ - defaultConnector, - { - ...defaultConnector, - id: 'c7f91dc0-2197-11ee-aded-897192c5d633', - name: 'OpenAI', - config: { - apiProvider: 'OpenAI 2', - apiUrl: 'https://api.openai.com/v1/chat/completions', - }, - }, - ]; - const result = getDefaultConnector(connectors); + it('should return the default connector if there are multiple connectors and default connector is defined', () => { + clientGet.mockImplementation((key: string) => { + if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) { + return defaultConnector.id; + } + return undefined; + }); + const connectors: AIConnector[] = [defaultConnector, connector2]; + const result = getDefaultConnector(connectors, settings); + expect(result).toBe(defaultConnector); + }); + + it('should return the default connector if there are multiple connectors and default connector is defined but they are in a different order', () => { + clientGet.mockImplementation((key: string) => { + if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) { + return defaultConnector.id; + } + return undefined; + }); + const connectors: AIConnector[] = [connector2, defaultConnector]; + const result = getDefaultConnector(connectors, settings); + expect(result).toBe(defaultConnector); + }); + + it('should return the first connector if there are multiple connectors and no default connector is defined', () => { + clientGet.mockImplementation(() => { + return undefined; + }); + + const connectors: AIConnector[] = [connector2, defaultConnector]; + const result = getDefaultConnector(connectors, settings); + expect(result).toBe(connectors[0]); + }); + + it('should return the first connector if there are multiple connectors and a default connector is defined but it does not exist', () => { + clientGet.mockImplementation((key: string) => { + if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) { + return 'randomConnectorIdThatDoesNotExist'; + } + return undefined; + }); + + const connectors: AIConnector[] = [connector2, defaultConnector]; + const result = getDefaultConnector(connectors, settings); expect(result).toBe(connectors[0]); }); }); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.ts index 2768d3fb7e035..e11c19c96dce8 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.ts +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/helpers.ts @@ -5,8 +5,10 @@ * 2.0. */ -import { AIConnector } from '../connectorland/connector_selector'; -import { FetchConnectorExecuteResponse } from './api'; +import type { SettingsStart } from '@kbn/core-ui-settings-browser'; +import { GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR } from '@kbn/management-settings-ids'; +import type { AIConnector } from '../connectorland/connector_selector'; +import type { FetchConnectorExecuteResponse } from './api'; import type { ClientMessage } from '../assistant_context/types'; export const getMessageFromRawResponse = ( @@ -40,13 +42,30 @@ export const getMessageFromRawResponse = ( * @param connectors */ export const getDefaultConnector = ( - connectors: AIConnector[] | undefined + connectors: AIConnector[] | undefined, + settings: SettingsStart ): AIConnector | undefined => { + const defaultAiConnectorId = settings.client.get( + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR, + undefined + ); + const validConnectors = connectors?.filter((connector) => !connector.isMissingSecrets); + const defaultConnector = validConnectors?.find( + (connector) => connector.id === defaultAiConnectorId + ); + + if (defaultConnector) { + // If the user has set a default connector setting, and that connector exists, use it + return defaultConnector; + } + if (validConnectors?.length) { + // In case the default connector is not set or is invalid, return the first valid connector return validConnectors[0]; } + // If no valid connectors are available, return undefined return undefined; }; diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/index.tsx index e144ef4466d7f..38341b71ba127 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/index.tsx @@ -100,6 +100,7 @@ const AssistantComponent: React.FC = ({ showAnonymizedValues, setContentReferencesVisible, setShowAnonymizedValues, + settings, } = useAssistantContext(); const [selectedPromptContexts, setSelectedPromptContexts] = useState< @@ -132,8 +133,12 @@ const AssistantComponent: React.FC = ({ // Connector details const { data: connectors, isFetchedAfterMount: isFetchedConnectors } = useLoadConnectors({ http, + settings, }); - const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]); + const defaultConnector = useMemo( + () => getDefaultConnector(connectors, settings), + [connectors, settings] + ); const spaceId = useAssistantSpaceId(); const { getLastConversation, setLastConversation } = useAssistantLastConversation({ spaceId }); const lastConversationFromLocalStorage = useMemo( diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx index beab8d3e1b32a..43f431a636fd1 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx @@ -68,6 +68,7 @@ export const AssistantSettings: React.FC = React.memo( selectedSettingsTab, setSelectedSettingsTab, toasts, + settings, } = useAssistantContext(); useEffect(() => { @@ -80,6 +81,7 @@ export const AssistantSettings: React.FC = React.memo( const { data: connectors } = useLoadConnectors({ http, + settings, }); const { conversationsSettingsBulkActions, diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx index e0cc0ac8a6419..a528c4eba8042 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx @@ -24,8 +24,12 @@ import { QUICK_PROMPTS_TAB, SYSTEM_PROMPTS_TAB, } from './const'; -import { DataViewsContract } from '@kbn/data-views-plugin/public'; import { SettingsStart } from '@kbn/core-ui-settings-browser'; +import type { DataViewsContract } from '@kbn/data-views-plugin/public'; +import { + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR, + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY, +} from '@kbn/management-settings-ids'; const mockSetSelectedSettingsTab = jest.fn(); @@ -40,6 +44,19 @@ const mockContext = { isAssistantManagementEnabled: true, hasConnectorsAllPrivilege: true, }, + settings: { + client: { + get: jest.fn((key) => { + if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) { + return 'c5f91dc0-2197-11ee-aded-897192c5d6f5'; + } + if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY) { + return false; + } + return undefined; + }), + }, + }, selectedSettingsTab: null, setSelectedSettingsTab: mockSetSelectedSettingsTab, navigateToApp: jest.fn(), diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx index 978c398a50115..ef5088a9ba1ff 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx @@ -9,7 +9,6 @@ import React, { useEffect, useMemo } from 'react'; import { EuiAvatar, EuiPageTemplate, EuiTitle, useEuiShadow, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import { DataViewsContract } from '@kbn/data-views-plugin/public'; -import { SettingsStart } from '@kbn/core-ui-settings-browser'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; import { useLoadConnectors } from '../../connectorland/use_load_connectors'; @@ -35,7 +34,6 @@ import { ManagementSettingsTabs } from './types'; interface Props { dataViews: DataViewsContract; - settings: SettingsStart; onTabChange?: (tabId: string) => void; currentTab: ManagementSettingsTabs; } @@ -45,7 +43,7 @@ interface Props { * anonymization, knowledge base, and evaluation via the `isModelEvaluationEnabled` feature flag. */ export const AssistantSettingsManagement: React.FC = React.memo( - ({ dataViews, onTabChange, currentTab: selectedSettingsTab, settings }) => { + ({ dataViews, onTabChange, currentTab: selectedSettingsTab }) => { const { assistantFeatures: { assistantModelEvaluation: modelEvaluatorEnabled }, http, @@ -53,6 +51,7 @@ export const AssistantSettingsManagement: React.FC = React.memo( setSelectedSettingsTab, navigateToApp, assistantAvailability: { isAssistantManagementEnabled }, + settings, } = useAssistantContext(); useEffect(() => { @@ -65,8 +64,12 @@ export const AssistantSettingsManagement: React.FC = React.memo( const { data: connectors } = useLoadConnectors({ http, + settings, }); - const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]); + const defaultConnector = useMemo( + () => getDefaultConnector(connectors, settings), + [connectors, settings] + ); const { euiTheme } = useEuiTheme(); const headerIconShadow = useEuiShadow('s'); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/evaluation_settings/evaluation_settings.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/evaluation_settings/evaluation_settings.tsx index 657dd81d4b330..c6c45edb18130 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/evaluation_settings/evaluation_settings.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/evaluation_settings/evaluation_settings.tsx @@ -50,8 +50,9 @@ const AS_PLAIN_TEXT: EuiComboBoxSingleSelectionShape = { asPlainText: true }; * Evaluation Settings -- development-only feature for evaluating models */ export const EvaluationSettings: React.FC = React.memo(() => { - const { actionTypeRegistry, http, setTraceOptions, toasts, traceOptions } = useAssistantContext(); - const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true }); + const { actionTypeRegistry, http, setTraceOptions, toasts, traceOptions, settings } = + useAssistantContext(); + const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true, settings }); const { mutate: performEvaluation, isLoading: isPerformingEvaluation } = usePerformEvaluation({ http, toasts, diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.test.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.test.tsx index 59111f257ecf5..0456a3cbc5b36 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.test.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.test.tsx @@ -23,8 +23,12 @@ import { QUICK_PROMPTS_TAB, SYSTEM_PROMPTS_TAB, } from './const'; -import { DataViewsContract } from '@kbn/data-views-plugin/public'; import { SettingsStart } from '@kbn/core-ui-settings-browser'; +import type { DataViewsContract } from '@kbn/data-views-plugin/public'; +import { + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR, + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY, +} from '@kbn/management-settings-ids'; const mockContext = { basePromptContexts: MOCK_QUICK_PROMPTS, @@ -35,6 +39,19 @@ const mockContext = { assistantAvailability: { isAssistantEnabled: true, }, + settings: { + client: { + get: jest.fn((key) => { + if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) { + return 'c5f91dc0-2197-11ee-aded-897192c5d6f5'; + } + if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY) { + return false; + } + return undefined; + }), + }, + }, }; const mockDataViews = { diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.tsx index b95d6917ac90b..ce2600299b0ac 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/search_ai_lake_configurations_settings_management.tsx @@ -15,7 +15,6 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; import { DataViewsContract } from '@kbn/data-views-plugin/public'; -import { SettingsStart } from '@kbn/core-ui-settings-browser'; import { AIForSOCConnectorSettingsManagement } from '../../connectorland/ai_for_soc_connector_settings_management'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; @@ -43,7 +42,6 @@ interface Props { dataViews: DataViewsContract; onTabChange?: (tabId: string) => void; currentTab: ManagementSettingsTabs; - settings: SettingsStart; } /** @@ -51,12 +49,13 @@ interface Props { * anonymization, knowledge base, and evaluation via the `isModelEvaluationEnabled` feature flag. */ export const SearchAILakeConfigurationsSettingsManagement: React.FC = React.memo( - ({ dataViews, onTabChange, currentTab, settings }) => { + ({ dataViews, onTabChange, currentTab }) => { const { assistantFeatures: { assistantModelEvaluation: modelEvaluatorEnabled }, http, selectedSettingsTab, setSelectedSettingsTab, + settings, } = useAssistantContext(); useEffect(() => { @@ -68,8 +67,12 @@ export const SearchAILakeConfigurationsSettingsManagement: React.FC = Rea const { data: connectors } = useLoadConnectors({ http, + settings, }); - const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]); + const defaultConnector = useMemo( + () => getDefaultConnector(connectors, settings), + [connectors, settings] + ); const { euiTheme } = useEuiTheme(); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/index.tsx index fed795afe2b6a..79fa75ffead89 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/index.tsx @@ -22,6 +22,7 @@ import { } from '@kbn/core/public'; import type { ProductDocBasePluginStart } from '@kbn/product-doc-base-plugin/public'; import { useQuery } from '@tanstack/react-query'; +import type { SettingsStart } from '@kbn/core-ui-settings-browser'; import { updatePromptContexts } from './helpers'; import type { PromptContext, @@ -87,6 +88,7 @@ export interface AssistantProviderProps { nameSpace?: string; navigateToApp: ApplicationStart['navigateToApp']; title?: string; + settings: SettingsStart; toasts?: IToasts; currentAppId: string; productDocBase: ProductDocBasePluginStart; @@ -128,6 +130,7 @@ export interface UseAssistantContext { selectedSettingsTab: ModalSettingsTabs | null; contentReferencesVisible: boolean; showAnonymizedValues: boolean; + settings: SettingsStart; setShowAnonymizedValues: React.Dispatch>; setContentReferencesVisible: React.Dispatch>; setAssistantStreamingEnabled: React.Dispatch>; @@ -178,6 +181,7 @@ export const useAssistantContextValue = (props: AssistantProviderProps): UseAssi getUrlForApp, http, inferenceEnabled = false, + settings, navigateToApp, nameSpace = DEFAULT_ASSISTANT_NAMESPACE, productDocBase, @@ -317,6 +321,7 @@ export const useAssistantContextValue = (props: AssistantProviderProps): UseAssi getComments, getUrlForApp, http, + settings, inferenceEnabled, knowledgeBase: { ...DEFAULT_KNOWLEDGE_BASE_SETTINGS, @@ -330,6 +335,7 @@ export const useAssistantContextValue = (props: AssistantProviderProps): UseAssi selectedSettingsTab, // can be undefined from localStorage, if not defined, default to true assistantStreamingEnabled: localStorageStreaming ?? true, + setAssistantStreamingEnabled: setLocalStorageStreaming, setKnowledgeBase: setLocalStorageKnowledgeBase, contentReferencesVisible: contentReferencesVisible ?? true, @@ -364,6 +370,7 @@ export const useAssistantContextValue = (props: AssistantProviderProps): UseAssi basePromptContexts, currentUserAvatar, docLinks, + settings, getComments, getUrlForApp, http, diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx index c308fbb2a80cb..8d49a0cedbd31 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx @@ -21,6 +21,7 @@ import { ActionConnector, ActionType } from '@kbn/triggers-actions-ui-plugin/pub import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/openai/constants'; import { some } from 'lodash'; import type { AttackDiscoveryStats } from '@kbn/elastic-assistant-common'; +import { GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR } from '@kbn/management-settings-ids'; import { AttackDiscoveryStatusIndicator } from './attack_discovery_status_indicator'; import { useLoadConnectors } from '../use_load_connectors'; import * as i18n from '../translations'; @@ -57,7 +58,7 @@ export const ConnectorSelector: React.FC = React.memo( stats = null, }) => { const { euiTheme } = useEuiTheme(); - const { actionTypeRegistry, http, assistantAvailability, inferenceEnabled } = + const { actionTypeRegistry, http, assistantAvailability, inferenceEnabled, settings } = useAssistantContext(); // Connector Modal State const [isConnectorModalVisible, setIsConnectorModalVisible] = useState(false); @@ -68,6 +69,7 @@ export const ConnectorSelector: React.FC = React.memo( const { data: aiConnectors, refetch: refetchConnectors } = useLoadConnectors({ http, inferenceEnabled, + settings, }); const localIsDisabled = isDisabled || !assistantAvailability.hasConnectorsReadPrivilege; @@ -185,6 +187,11 @@ export const ConnectorSelector: React.FC = React.memo( [cleanupAndCloseModal, onConnectorSelectionChange, refetchConnectors] ); + const defaultAIConnectorId = settings.client.get( + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR, + undefined + ); + return ( <> {!connectorExists && !connectorOptions.length ? ( @@ -213,7 +220,7 @@ export const ConnectorSelector: React.FC = React.memo( isOpen={modalForceOpen} onChange={onChange} options={allConnectorOptions} - valueOfSelected={selectedConnectorId} + valueOfSelected={selectedConnectorId ?? defaultAIConnectorId} placeholder={i18n.INLINE_CONNECTOR_PLACEHOLDER} popoverProps={{ panelMinWidth: 400, anchorPosition: 'downRight' }} /> diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx index 3e186f267bab6..5d6a69249ab22 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx @@ -35,9 +35,9 @@ export const ConnectorSetup = ({ ); const { setApiConfig } = useConversation(); // Access all conversations so we can add connector to all on initial setup - const { actionTypeRegistry, http, inferenceEnabled } = useAssistantContext(); + const { actionTypeRegistry, http, inferenceEnabled, settings } = useAssistantContext(); - const { refetch: refetchConnectors } = useLoadConnectors({ http, inferenceEnabled }); + const { refetch: refetchConnectors } = useLoadConnectors({ http, inferenceEnabled, settings }); const { data: actionTypes } = useLoadActionTypes({ http }); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx index e1c7fa93116c5..3dc937aeaa6fa 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx @@ -9,6 +9,10 @@ import { waitFor, renderHook } from '@testing-library/react'; import { useLoadConnectors, Props } from '.'; import { mockConnectors } from '../../mock/connectors'; import { TestProviders } from '../../mock/test_providers/test_providers'; +import { + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR, + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY, +} from '@kbn/management-settings-ids'; const mockConnectorsAndExtras = [ ...mockConnectors, @@ -52,7 +56,19 @@ const http = { const toasts = { addError: jest.fn(), }; -const defaultProps = { http, toasts } as unknown as Props; +const settings = { + client: { + get: jest.fn().mockImplementation((settingKey) => { + if (settingKey === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) { + return undefined; + } + if (settingKey === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY) { + return false; + } + }), + }, +}; +const defaultProps = { http, toasts, settings } as unknown as Props; describe('useLoadConnectors', () => { beforeEach(() => { diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx index 078a5c483d3e4..f0d19a4fd9b08 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx @@ -9,11 +9,15 @@ import type { UseQueryResult } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query'; import type { ServerError } from '@kbn/cases-plugin/public/types'; import { loadAllActions as loadConnectors } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; -import type { IHttpFetchError } from '@kbn/core-http-browser'; -import { HttpSetup } from '@kbn/core-http-browser'; -import { IToasts } from '@kbn/core-notifications-browser'; -import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/openai/constants'; -import { AIConnector } from '../connector_selector'; +import type { IHttpFetchError, HttpSetup } from '@kbn/core-http-browser'; +import type { IToasts } from '@kbn/core-notifications-browser'; +import type { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/openai/constants'; +import type { SettingsStart } from '@kbn/core-ui-settings-browser'; +import { + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR, + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY, +} from '@kbn/management-settings-ids'; +import type { AIConnector } from '../connector_selector'; import * as i18n from '../translations'; /** @@ -26,6 +30,7 @@ export interface Props { http: HttpSetup; toasts?: IToasts; inferenceEnabled?: boolean; + settings: SettingsStart; } const actionTypes = ['.bedrock', '.gen-ai', '.gemini']; @@ -34,6 +39,7 @@ export const useLoadConnectors = ({ http, toasts, inferenceEnabled = false, + settings, }: Props): UseQueryResult => { useEffect(() => { if (inferenceEnabled && !actionTypes.includes('.inference')) { @@ -41,13 +47,20 @@ export const useLoadConnectors = ({ } }, [inferenceEnabled]); + const defaultAiConnectorId = settings.client.get(GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR); + const defaultAiConnectorOnly = settings.client.get( + GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY, + false + ); + return useQuery( QUERY_KEY, async () => { const connectors = await loadConnectors({ http }); - return connectors.reduce((acc: AIConnector[], connector) => { + + const allAiConnectors = connectors.flatMap((connector) => { if (!connector.isMissingSecrets && actionTypes.includes(connector.actionTypeId)) { - acc.push({ + const aiConnector: AIConnector = { ...connector, apiProvider: !connector.isPreconfigured && @@ -55,10 +68,23 @@ export const useLoadConnectors = ({ connector?.config?.apiProvider ? (connector?.config?.apiProvider as OpenAiProviderType) : undefined, - }); + }; + return [aiConnector]; } - return acc; - }, []); + return []; + }); + + const availableConnectors = allAiConnectors.filter((connector) => { + if (defaultAiConnectorOnly) { + return connector.id === defaultAiConnectorId; + } + return true; + }); + + if (availableConnectors.length === 0) { + return allAiConnectors; + } + return availableConnectors; }, { retry: false, diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx index 78e711f9cee7d..6c610e4f4aaed 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx @@ -17,12 +17,10 @@ import { UserProfileService } from '@kbn/core/public'; import { chromeServiceMock } from '@kbn/core-chrome-browser-mocks'; import { of } from 'rxjs'; import { docLinksServiceMock } from '@kbn/core/public/mocks'; -import { - AssistantProvider, - AssistantProviderProps, - useAssistantContextValue, -} from '../../assistant_context'; -import { AssistantAvailability } from '../../assistant_context/types'; +import type { SettingsStart } from '@kbn/core-ui-settings-browser'; +import type { AssistantProviderProps } from '../../assistant_context'; +import { AssistantProvider, useAssistantContextValue } from '../../assistant_context'; +import type { AssistantAvailability } from '../../assistant_context/types'; import { AssistantSpaceIdProvider } from '../../assistant/use_space_aware_context'; interface Props { @@ -99,7 +97,12 @@ export const TestProvidersComponent: React.FC = ({ }, userProfileService: jest.fn() as unknown as UserProfileService, chrome, - }; + settings: { + client: { + get: jest.fn(), + }, + } as unknown as SettingsStart, + } as AssistantProviderProps; return ( diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/tour/elastic_llm/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/tour/elastic_llm/index.tsx index 80be8ed1e6dcb..a666c08e86ebf 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/tour/elastic_llm/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/tour/elastic_llm/index.tsx @@ -41,7 +41,7 @@ const ElasticLLMCostAwarenessTourComponent: React.FC = ({ zIndex, wrapper = true, // Whether to wrap the children in a div with padding }) => { - const { http, inferenceEnabled } = useAssistantContext(); + const { http, inferenceEnabled, settings } = useAssistantContext(); const { euiTheme } = useEuiTheme(); const tourStorageKey = useTourStorageKey(storageKey); const [tourState, setTourState] = useLocalStorage( @@ -72,6 +72,7 @@ const ElasticLLMCostAwarenessTourComponent: React.FC = ({ const { data: aiConnectors } = useLoadConnectors({ http, inferenceEnabled, + settings, }); const isElasticLLMConnectorSelected = useMemo( () => diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/tsconfig.json b/x-pack/platform/packages/shared/kbn-elastic-assistant/tsconfig.json index 842a80ea28192..5634292627865 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/tsconfig.json +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/tsconfig.json @@ -51,6 +51,7 @@ "@kbn/management-settings-field-definition", "@kbn/management-settings-ids", "@kbn/ai-assistant-default-llm-setting", + "@kbn/management-settings-ids", "@kbn/core-ui-settings-browser", ] } diff --git a/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/connector_step/connector_step.tsx b/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/connector_step/connector_step.tsx index e281061f09bd2..bd211f85c94aa 100644 --- a/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/connector_step/connector_step.tsx +++ b/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/connector_step/connector_step.tsx @@ -94,7 +94,7 @@ interface ConnectorStepProps { export const ConnectorStep = React.memo(({ connector }) => { const { euiTheme } = useEuiTheme(); - const { http, notifications, triggersActionsUi } = useKibana().services; + const { http, notifications, triggersActionsUi, settings } = useKibana().services; const { setConnector, completeStep } = useActions(); const [connectors, setConnectors] = useState(); @@ -110,7 +110,7 @@ export const ConnectorStep = React.memo(({ connector }) => { isLoading, data: aiConnectors, refetch: refetchConnectors, - } = useLoadConnectors({ http, toasts: notifications.toasts, inferenceEnabled }); + } = useLoadConnectors({ http, toasts: notifications.toasts, inferenceEnabled, settings }); useEffect(() => { if (aiConnectors != null) { diff --git a/x-pack/solutions/security/packages/ecs-data-quality-dashboard/impl/data_quality_panel/mock/test_providers/test_providers.tsx b/x-pack/solutions/security/packages/ecs-data-quality-dashboard/impl/data_quality_panel/mock/test_providers/test_providers.tsx index ff720dc0ad4e6..5cf700a4b06ac 100644 --- a/x-pack/solutions/security/packages/ecs-data-quality-dashboard/impl/data_quality_panel/mock/test_providers/test_providers.tsx +++ b/x-pack/solutions/security/packages/ecs-data-quality-dashboard/impl/data_quality_panel/mock/test_providers/test_providers.tsx @@ -20,11 +20,11 @@ import { of } from 'rxjs'; import { I18nProvider } from '@kbn/i18n-react'; import { EuiThemeProvider } from '@elastic/eui'; -import { - AssistantProviderProps, - useAssistantContextValue, -} from '@kbn/elastic-assistant/impl/assistant_context'; -import { DataQualityProvider, DataQualityProviderProps } from '../../data_quality_context'; +import type { AssistantProviderProps } from '@kbn/elastic-assistant/impl/assistant_context'; +import { useAssistantContextValue } from '@kbn/elastic-assistant/impl/assistant_context'; +import type { SettingsStart } from '@kbn/core-ui-settings-browser'; +import type { DataQualityProviderProps } from '../../data_quality_context'; +import { DataQualityProvider } from '../../data_quality_context'; import { ResultsRollupContext } from '../../contexts/results_rollup_context'; import { IndicesCheckContext } from '../../contexts/indices_check_context'; import { UseIndicesCheckReturnValue } from '../../hooks/use_indices_check/types'; @@ -98,6 +98,11 @@ const TestExternalProvidersComponent: React.FC = ({ userProfileService: jest.fn() as unknown as UserProfileService, getUrlForApp: jest.fn(), chrome, + settings: { + client: { + get: jest.fn(), + }, + } as unknown as SettingsStart, }; return ( diff --git a/x-pack/solutions/security/packages/ecs-data-quality-dashboard/tsconfig.json b/x-pack/solutions/security/packages/ecs-data-quality-dashboard/tsconfig.json index 8334bc4449955..c9574559abb45 100644 --- a/x-pack/solutions/security/packages/ecs-data-quality-dashboard/tsconfig.json +++ b/x-pack/solutions/security/packages/ecs-data-quality-dashboard/tsconfig.json @@ -24,6 +24,7 @@ "@kbn/core-notifications-browser-mocks", "@kbn/core-chrome-browser-mocks", "@kbn/ai-assistant-icon", - "@kbn/react-kibana-context-render" + "@kbn/react-kibana-context-render", + "@kbn/core-ui-settings-browser" ] } diff --git a/x-pack/solutions/security/plugins/elastic_assistant/public/src/context/assistant_context/assistant_provider.tsx b/x-pack/solutions/security/plugins/elastic_assistant/public/src/context/assistant_context/assistant_provider.tsx index dabff2d8e0d63..1b85de036c9f4 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/public/src/context/assistant_context/assistant_provider.tsx +++ b/x-pack/solutions/security/plugins/elastic_assistant/public/src/context/assistant_context/assistant_provider.tsx @@ -41,6 +41,7 @@ export function AssistantProvider({ children }: { children: React.ReactElement } chrome, productDocBase, elasticAssistantSharedState, + settings, } = useKibana().services; const inferenceEnabled = useInferenceEnabled(); @@ -106,6 +107,7 @@ export function AssistantProvider({ children }: { children: React.ReactElement } userProfileService: userProfile, chrome, getUrlForApp, + settings, }); useEffect(() => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/stack_management/management_settings.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/stack_management/management_settings.tsx index da5a75e4c6dbd..9c583d1b188ad 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/stack_management/management_settings.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/stack_management/management_settings.tsx @@ -24,7 +24,6 @@ export const ManagementSettings = React.memo(() => { data: { dataViews }, chrome: { docTitle, setBreadcrumbs }, serverless, - settings, docLinks, featureFlags, notifications, @@ -111,7 +110,6 @@ export const ManagementSettings = React.memo(() => { featureFlags={featureFlags} > { const { - services: { uiSettings }, + services: { uiSettings, settings }, } = useKibana(); const { attackDiscoveryAlertsEnabled } = useKibanaFeatureFlags(); @@ -64,6 +64,7 @@ const AttackDiscoveryPageComponent: React.FC = () => { const { data: aiConnectors } = useLoadConnectors({ http, inferenceEnabled, + settings, }); // for showing / hiding anonymized data: diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx index b1b9bf6d57608..438f8cc6d3500 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx @@ -58,9 +58,10 @@ export const CreateFlyout: React.FC = React.memo(({ onClose }) => { services: { uiSettings }, } = useKibana(); - const { alertsIndexPattern, http } = useAssistantContext(); + const { alertsIndexPattern, http, settings } = useAssistantContext(); const { data: aiConnectors, isLoading: isLoadingConnectors } = useLoadConnectors({ http, + settings, }); const { sourcererDataView } = useSourcererDataView(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx index 417971318d171..f8111c3b5f856 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx @@ -73,9 +73,10 @@ export const DetailsFlyout: React.FC = React.memo(({ scheduleId, onClose } = useKibana(); const { euiTheme } = useEuiTheme(); - const { alertsIndexPattern, http } = useAssistantContext(); + const { alertsIndexPattern, http, settings } = useAssistantContext(); const { data: aiConnectors, isLoading: isLoadingConnectors } = useLoadConnectors({ http, + settings, }); const { data: { schedule } = { schedule: undefined }, isLoading: isLoadingSchedule } = useGetAttackDiscoverySchedule({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/use_attack_discovery/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/use_attack_discovery/index.tsx index d542d26bc5b7c..5f6ee9adb56db 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/use_attack_discovery/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/use_attack_discovery/index.tsx @@ -74,9 +74,12 @@ export const useAttackDiscovery = ({ const { http, notifications: { toasts }, + settings, } = useKibana().services; + const { data: aiConnectors } = useLoadConnectors({ http, + settings, }); // generation can take a long time, so we calculate an approximate future time: diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx index 33e3312f52e51..c34773c1e3213 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx @@ -15,6 +15,7 @@ import { chromeServiceMock } from '@kbn/core-chrome-browser-mocks'; import { of } from 'rxjs'; import { useAssistantContextValue } from '@kbn/elastic-assistant/impl/assistant_context'; import { docLinksServiceMock } from '@kbn/core/public/mocks'; +import type { SettingsStart } from '@kbn/core-ui-settings-browser'; interface Props { assistantAvailability?: AssistantAvailability; @@ -69,6 +70,11 @@ export const MockAssistantProviderComponent: React.FC = ({ userProfileService: mockUserProfileService, chrome, getUrlForApp: jest.fn(), + settings: { + client: { + get: jest.fn(), + }, + } as unknown as SettingsStart, }); return {children}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/configurations/tabs/ai_settings.tsx b/x-pack/solutions/security/plugins/security_solution/public/configurations/tabs/ai_settings.tsx index 0822ff12d7b1f..4972c55aa49cb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/configurations/tabs/ai_settings.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/configurations/tabs/ai_settings.tsx @@ -23,7 +23,6 @@ export const AISettings: React.FC = () => { const { application, data: { dataViews }, - settings, docLinks, notifications: { toasts }, featureFlags, @@ -66,7 +65,6 @@ export const AISettings: React.FC = () => { dataViews={dataViews} onTabChange={onTabChange} currentTab={currentTab} - settings={settings} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx index 989ecbd48ef4c..acd79ae7f207c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx @@ -44,9 +44,10 @@ export const WorkflowInsightsScanSection = ({ const CONNECTOR_ID_LOCAL_STORAGE_KEY = 'connectorId'; const spaceId = useSpaceId(); - const { http } = useKibana().services; + const { http, settings } = useKibana().services; const { data: aiConnectors } = useLoadConnectors({ http, + settings, }); const { canWriteWorkflowInsights } = useUserPrivileges().endpointPrivileges; const { inferenceEnabled } = useAssistantContext(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/assistant_card.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/assistant_card.tsx index 7591cfa52a672..663b3dd1c1c62 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/assistant_card.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/assistant_card.tsx @@ -46,14 +46,19 @@ export const AssistantCard: OnboardingCardComponent = ({ const [selectedConnectorId, setSelectedConnectorId] = useStoredAssistantConnectorId(spaceId); - const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]); - - const { setApiConfig } = useConversation(); - const { http, assistantAvailability: { isAssistantEnabled }, + settings, } = useAssistantContext(); + + const defaultConnector = useMemo( + () => getDefaultConnector(connectors, settings), + [connectors, settings] + ); + + const { setApiConfig } = useConversation(); + const { getLastConversation, setLastConversation } = useAssistantLastConversation({ spaceId }); const { allSystemPrompts,