- {showElasticLlmCalloutInChat ? (
-
-
-
- ) : null}
+
+ {showKnowledgeBaseReIndexingCallout ? : null}
+ {showElasticLlmCalloutInChat ? : null}
+
{items.map((item, index) => {
return Array.isArray(item) ? (
({
+ useKibana: () => ({
+ services: {
+ triggersActionsUi: {
+ getAddConnectorFlyout: jest.fn(() => null),
+ },
+ observabilityAIAssistant: {
+ service: {
+ getScreenContexts: jest.fn(() => []),
+ },
+ useGenAIConnectors: jest.fn(() => mockConnectors),
+ },
+ },
+ }),
+}));
+
+const createMockKnowledgeBase = (
+ partial: Partial = {}
+): UseKnowledgeBaseResult => ({
+ isInstalling: false,
+ isPolling: false,
+ install: jest.fn(),
+ warmupModel: jest.fn(),
+ isWarmingUpModel: false,
+ status: {
+ value: {
+ enabled: true,
+ errorMessage: undefined,
+ kbState: KnowledgeBaseState.NOT_INSTALLED,
+ concreteWriteIndex: undefined,
+ currentInferenceId: undefined,
+ isReIndexing: false,
+ },
+ loading: false,
+ error: undefined,
+ refresh: jest.fn(),
+ },
+ ...partial,
+});
+
+describe('WelcomeMessage', () => {
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('renders a warning callout while knowledge base is re-indexing', async () => {
+ const knowledgeBase = createMockKnowledgeBase({
+ status: {
+ value: {
+ kbState: KnowledgeBaseState.READY,
+ enabled: true,
+ concreteWriteIndex: 'my-index',
+ currentInferenceId: 'inference_id',
+ isReIndexing: true,
+ },
+ loading: false,
+ error: undefined,
+ refresh: jest.fn(),
+ },
+ });
+
+ const { rerender } = render(
+
+ );
+
+ // Callout is shown during re-indexing
+ expect(screen.queryByText(/Re-indexing in progress/i)).toBeInTheDocument();
+ expect(
+ screen.queryByText(/Knowledge base is currently being re-indexed./i)
+ ).toBeInTheDocument();
+
+ // Knowledge base finished re-indexing
+ const updatedKnowledgeBase = createMockKnowledgeBase({
+ status: {
+ value: {
+ kbState: KnowledgeBaseState.READY,
+ enabled: true,
+ concreteWriteIndex: 'my-index',
+ currentInferenceId: 'inference_id',
+ isReIndexing: false,
+ },
+ loading: false,
+ error: undefined,
+ refresh: jest.fn(),
+ },
+ });
+
+ await act(async () => {
+ rerender(
+
+ );
+ });
+
+ // Callout is no longer shown
+ expect(screen.queryByText(/Re-indexing in progress/i)).not.toBeInTheDocument();
+ expect(
+ screen.queryByText(/Knowledge base is currently being re-indexed./i)
+ ).not.toBeInTheDocument();
+ });
+});
diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx
index 29d024d8d0ffd..0b9d5d31f2d36 100644
--- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx
+++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx
@@ -20,6 +20,7 @@ import { WelcomeMessageKnowledgeBase } from '../knowledge_base/welcome_message_k
import { StarterPrompts } from './starter_prompts';
import { useKibana } from '../hooks/use_kibana';
import { ElasticLlmConversationCallout } from './elastic_llm_conversation_callout';
+import { KnowledgeBaseReindexingCallout } from '../knowledge_base/knowledge_base_reindexing_callout';
const fullHeightClassName = css`
height: 100%;
@@ -34,11 +35,13 @@ export function WelcomeMessage({
connectors,
knowledgeBase,
showElasticLlmCalloutInChat,
+ showKnowledgeBaseReIndexingCallout,
onSelectPrompt,
}: {
connectors: UseGenAIConnectorsResult;
knowledgeBase: UseKnowledgeBaseResult;
showElasticLlmCalloutInChat: boolean;
+ showKnowledgeBaseReIndexingCallout: boolean;
onSelectPrompt: (prompt: string) => void;
}) {
const breakpoint = useCurrentEuiBreakpoint();
@@ -78,6 +81,7 @@ export function WelcomeMessage({
gutterSize="none"
className={fullHeightClassName}
>
+ {showKnowledgeBaseReIndexingCallout ? : null}
{showElasticLlmCalloutInChat ? : null}
diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/knowledge_base/knowledge_base_reindexing_callout.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/knowledge_base/knowledge_base_reindexing_callout.tsx
new file mode 100644
index 0000000000000..111a08e1d3b2e
--- /dev/null
+++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/knowledge_base/knowledge_base_reindexing_callout.tsx
@@ -0,0 +1,37 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { css } from '@emotion/css';
+import { EuiCallOut, useEuiTheme } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+export const KnowledgeBaseReindexingCallout = () => {
+ const { euiTheme } = useEuiTheme();
+
+ const knowledgeBaseReindexingCalloutName = css`
+ margin-bottom: ${euiTheme.size.s};
+ width: 100%;
+ `;
+
+ return (
+
+ {i18n.translate('xpack.aiAssistant.knowledgeBase.reindexingCalloutBody', {
+ defaultMessage:
+ 'Knowledge base is currently being re-indexed. If you have entries, some may be unavailable until the operation completes.',
+ })}
+
+ );
+};
diff --git a/x-pack/platform/plugins/private/observability_ai_assistant_management/public/helpers/test_helper.tsx b/x-pack/platform/plugins/private/observability_ai_assistant_management/public/helpers/test_helper.tsx
index e520cc4052b59..133ad49e5c6b2 100644
--- a/x-pack/platform/plugins/private/observability_ai_assistant_management/public/helpers/test_helper.tsx
+++ b/x-pack/platform/plugins/private/observability_ai_assistant_management/public/helpers/test_helper.tsx
@@ -8,7 +8,7 @@
import React from 'react';
import { createMemoryHistory } from 'history';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { render as testLibRender } from '@testing-library/react';
+import { RenderResult, render as testLibRender } from '@testing-library/react';
import { coreMock } from '@kbn/core/public/mocks';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import { observabilityAIAssistantPluginMock } from '@kbn/observability-ai-assistant-plugin/public/mock';
@@ -41,7 +41,7 @@ const queryClient = new QueryClient({
export const render = (
component: React.ReactNode,
mocks?: { coreStart?: DeepPartial; appContextValue?: AppContextValue }
-) => {
+): RenderResult => {
const history = createMemoryHistory();
const startDeps = {
@@ -76,7 +76,7 @@ export const render = (
},
};
- return testLibRender(
+ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
// @ts-ignore
@@ -87,7 +87,7 @@ export const render = (
history={history}
router={aIAssistantManagementObservabilityRouter as any}
>
- {component}
+ {children}
@@ -95,4 +95,13 @@ export const render = (
);
+
+ const renderResult = testLibRender(component, { wrapper: TestWrapper });
+
+ return {
+ ...renderResult,
+ rerender: (newComponent: React.ReactNode) => {
+ renderResult.rerender(newComponent);
+ },
+ };
};
diff --git a/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.test.tsx b/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.test.tsx
index f282ddfe51962..c06bed775bd60 100644
--- a/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.test.tsx
+++ b/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.test.tsx
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { fireEvent } from '@testing-library/react';
+import { act, fireEvent } from '@testing-library/react';
import { KnowledgeBaseState } from '@kbn/observability-ai-assistant-plugin/public';
import { useGenAIConnectors, useKnowledgeBase } from '@kbn/ai-assistant/src/hooks';
import { render } from '../../helpers/test_helper';
@@ -104,6 +104,47 @@ describe('KnowledgeBaseTab', () => {
});
});
+ describe('when the knowledge base is re-indexing', () => {
+ beforeEach(() => {
+ useKnowledgeBaseMock.mockReturnValue({
+ status: {
+ value: {
+ kbState: KnowledgeBaseState.READY,
+ enabled: true,
+ isReIndexing: true,
+ },
+ },
+ isInstalling: false,
+ install: jest.fn(),
+ });
+ });
+
+ it('should show a warning callout while re-indexing is in progress', async () => {
+ const { getByTestId, queryByTestId, rerender } = render();
+ expect(getByTestId('knowledgeBaseReindexingCallOut')).toBeInTheDocument();
+
+ // Re-indexing completed
+ useKnowledgeBaseMock.mockReturnValue({
+ status: {
+ value: {
+ kbState: KnowledgeBaseState.READY,
+ enabled: true,
+ isReIndexing: false,
+ },
+ },
+ isInstalling: false,
+ install: jest.fn(),
+ });
+
+ await act(async () => {
+ rerender();
+ });
+
+ // Callout is no longer shown
+ expect(queryByTestId('knowledgeBaseReindexingCallOut')).not.toBeInTheDocument();
+ });
+ });
+
describe('when the knowledge base is installed and ready', () => {
beforeEach(() => {
useKnowledgeBaseMock.mockReturnValue({
diff --git a/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.tsx b/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.tsx
index d20c0bfacdfcd..5e9e17d0e8cd4 100644
--- a/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.tsx
+++ b/x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/knowledge_base_tab.tsx
@@ -39,6 +39,7 @@ import { useKnowledgeBase } from '@kbn/ai-assistant/src/hooks';
import { KnowledgeBaseInstallationStatusPanel } from '@kbn/ai-assistant/src/knowledge_base/knowledge_base_installation_status_panel';
import { SettingUpKnowledgeBase } from '@kbn/ai-assistant/src/knowledge_base/setting_up_knowledge_base';
import { InspectKnowledgeBasePopover } from '@kbn/ai-assistant/src/knowledge_base/inspect_knowlegde_base_popover';
+import { KnowledgeBaseReindexingCallout } from '@kbn/ai-assistant/src/knowledge_base/knowledge_base_reindexing_callout';
import { useGetKnowledgeBaseEntries } from '../../hooks/use_get_knowledge_base_entries';
import { categorizeEntries, KnowledgeBaseEntryCategory } from '../../helpers/categorize_entries';
import { KnowledgeBaseEditManualEntryFlyout } from './knowledge_base_edit_manual_entry_flyout';
@@ -256,6 +257,8 @@ export function KnowledgeBaseTab() {
return (
<>
+ {knowledgeBase.status.value?.isReIndexing && }
+