diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx index cc85c5bf8c1a1..a26eaf015ebb8 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx @@ -383,7 +383,7 @@ export function ChatBody({ const { conversationCalloutDismissed, tourCalloutDismissed } = useElasticLlmCalloutsStatus(false); const showElasticLlmCalloutInChat = - elasticManagedLlm && + !!elasticManagedLlm && connectors.selectedConnector === elasticManagedLlm.id && !conversationCalloutDismissed && tourCalloutDismissed; diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_elastic_managed_llm_connector.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_elastic_managed_llm_connector.ts index 00c5330934c91..eb6985ea1258c 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_elastic_managed_llm_connector.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_elastic_managed_llm_connector.ts @@ -13,13 +13,13 @@ export const getElasticManagedLlmConnector = ( connectors: UseGenAIConnectorsResult['connectors'] | undefined ) => { if (!Array.isArray(connectors) || connectors.length === 0) { - return false; + return undefined; } - return connectors.filter( + return connectors.find( (connector) => connector.actionTypeId === INFERENCE_CONNECTOR_ACTION_TYPE_ID && connector.isPreconfigured && connector.config?.provider === 'elastic' - )[0]; + ); }; diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/generate_pattern_button.tsx b/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/generate_pattern_button.tsx index 8ff1ac1f2e036..82ea62f15eae8 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/generate_pattern_button.tsx +++ b/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/generate_pattern_button.tsx @@ -21,6 +21,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useBoolean } from '@kbn/react-hooks'; +import { FormattedMessage } from '@kbn/i18n-react'; import { AIFeatures } from './use_ai_features'; import { useKibana } from '../../../../../hooks/use_kibana'; @@ -140,17 +141,47 @@ export const GeneratePatternButton = ({ )} - {aiFeatures.isManagedAIConnector && !aiFeatures.hasAcknowledgedAdditionalCharges && ( - aiFeatures.acknowledgeAdditionalCharges(true)}> - {i18n.translate( - 'xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.managedConnectorTooltip', - { - defaultMessage: - 'Generating patterns is powered by a preconfigured LLM. Additional charges apply', - } - )} - - )} ); }; + +export interface AdditionalChargesCalloutProps { + aiFeatures: AIFeatures; +} + +export const AdditionalChargesCallout = ({ aiFeatures }: AdditionalChargesCalloutProps) => { + const { + core: { docLinks }, + } = useKibana(); + + return ( + aiFeatures.acknowledgeAdditionalCharges(true)}> + ( + + {chunks} + + ), + learnMoreLink: (...chunks: React.ReactNode[]) => ( + + {chunks} + + ), + }} + /> + + ); +}; diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/grok_patterns_editor.tsx b/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/grok_patterns_editor.tsx index 48245ba438935..9b10a81528d1a 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/grok_patterns_editor.tsx +++ b/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/grok_patterns_editor.tsx @@ -27,6 +27,7 @@ import { EuiIcon, EuiButtonIcon, EuiFlexItem, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { DraftGrokExpression, GrokCollection } from '@kbn/grok-ui'; @@ -36,7 +37,7 @@ import useObservable from 'react-use/lib/useObservable'; import { useStreamsEnrichmentSelector } from '../../state_management/stream_enrichment_state_machine'; import { SortableList } from '../../sortable_list'; import { GrokPatternSuggestion } from './grok_pattern_suggestion'; -import { GeneratePatternButton } from './generate_pattern_button'; +import { GeneratePatternButton, AdditionalChargesCallout } from './generate_pattern_button'; import { useGrokPatternSuggestion } from './use_grok_pattern_suggestion'; import { useSimulatorSelector } from '../../state_management/stream_enrichment_state_machine'; import { selectPreviewDocuments } from '../../state_management/simulation_state_machine/selectors'; @@ -145,39 +146,49 @@ export const GrokPatternsEditor = () => { onDismiss={() => refreshSuggestions(null)} /> ) : ( - - {aiFeatures && ( + <> + + {aiFeatures && ( + + + refreshSuggestions({ + connectorId, + streamName: stream.name, + samples: previewDocuments, + fieldName: fieldValue, + }) + } + isLoading={suggestionsState.loading} + isDisabled={!isValidField} + /> + + )} - - refreshSuggestions({ - connectorId, - streamName: stream.name, - samples: previewDocuments, - fieldName: fieldValue, - }) - } - isLoading={suggestionsState.loading} - isDisabled={!isValidField} - /> + + {i18n.translate( + 'xpack.streams.streamDetailView.managementTab.enrichment.processor.grokEditor.addPattern', + { defaultMessage: 'Add pattern' } + )} + - )} - - - {i18n.translate( - 'xpack.streams.streamDetailView.managementTab.enrichment.processor.grokEditor.addPattern', - { defaultMessage: 'Add pattern' } - )} - - - + + {aiFeatures && + aiFeatures.isManagedAIConnector && + !aiFeatures.hasAcknowledgedAdditionalCharges && ( + <> + + + + )} + )} ); diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/use_ai_features.tsx b/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/use_ai_features.tsx index 56e49e044e8e8..66f2415a0cd64 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/use_ai_features.tsx +++ b/x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_enrichment/processors/grok/use_ai_features.tsx @@ -7,11 +7,13 @@ import useObservable from 'react-use/lib/useObservable'; import { isEmpty } from 'lodash'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; +import { + ElasticLlmCalloutKey, + useElasticLlmCalloutDismissed, + getElasticManagedLlmConnector, +} from '@kbn/observability-ai-assistant-plugin/public'; import { useKibana } from '../../../../../hooks/use_kibana'; -const INTERNAL_INFERENCE_CONNECTORS = ['Elastic-Managed-LLM']; - export function useAIFeatures() { const { dependencies: { @@ -21,10 +23,10 @@ export function useAIFeatures() { } = useKibana(); const genAiConnectors = observabilityAIAssistant.useGenAIConnectors(); const license = useObservable(licensing.license$); - const [hasAcknowledgedAdditionalCharges, acknowledgeAdditionalCharges] = useLocalStorage( - 'streams:additionalChargesAcknowledged', - false + const [tourCalloutDismissed, setTourCalloutDismissed] = useElasticLlmCalloutDismissed( + ElasticLlmCalloutKey.TOUR_CALLOUT ); + const elasticManagedLlmConnector = getElasticManagedLlmConnector(genAiConnectors.connectors); if (genAiConnectors.loading) { return undefined; @@ -35,8 +37,8 @@ export function useAIFeatures() { const couldBeEnabled = Boolean( license?.hasAtLeast('enterprise') && core.application.capabilities.actions?.save ); - const isManagedAIConnector = genAiConnectors.selectedConnector - ? INTERNAL_INFERENCE_CONNECTORS.includes(genAiConnectors.selectedConnector) + const isManagedAIConnector = elasticManagedLlmConnector + ? elasticManagedLlmConnector.id === genAiConnectors.selectedConnector : false; return { @@ -44,8 +46,8 @@ export function useAIFeatures() { couldBeEnabled, genAiConnectors, isManagedAIConnector, - hasAcknowledgedAdditionalCharges, - acknowledgeAdditionalCharges, + hasAcknowledgedAdditionalCharges: tourCalloutDismissed, + acknowledgeAdditionalCharges: setTourCalloutDismissed, }; }