From f80b1529539c415f2326e35b133c1ee95f270923 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Wed, 26 Jun 2024 18:00:53 -0700 Subject: [PATCH 01/22] [Security AI Assistant] Persist prompts --- .../prompts/bulk_crud_prompts_route.gen.ts | 24 +++- .../bulk_crud_prompts_route.schema.yaml | 41 ++++-- .../api/prompts/bulk_update_prompts.test.ts | 133 ++++++++++++++++++ .../api/prompts/bulk_update_prompts.ts | 54 +++++++ .../api/prompts/use_fetch_prompts.test.tsx | 60 ++++++++ .../api/prompts/use_fetch_prompts.ts | 74 ++++++++++ .../impl/assistant/assistant_header/index.tsx | 4 + .../assistant/chat_send/use_chat_send.tsx | 5 +- .../conversation_selector/index.tsx | 13 +- .../conversation_settings.tsx | 7 +- .../impl/assistant/index.tsx | 51 ++++--- .../impl/assistant/prompt/helpers.ts | 6 +- .../impl/assistant/prompt_editor/helpers.tsx | 6 +- .../impl/assistant/prompt_editor/index.tsx | 15 +- .../prompt_editor/system_prompt/helpers.tsx | 30 +--- .../prompt_editor/system_prompt/index.tsx | 10 +- .../select_system_prompt/index.test.tsx | 2 +- .../select_system_prompt/index.tsx | 18 ++- .../system_prompt_selector.tsx | 8 +- .../system_prompt_settings.tsx | 126 +++++++++++++++-- .../quick_prompt_selector.tsx | 16 +-- .../quick_prompt_settings.tsx | 52 ++++--- .../assistant/quick_prompts/quick_prompts.tsx | 30 ++-- .../assistant/settings/assistant_settings.tsx | 23 +-- .../assistant_settings_management.tsx | 25 ++-- .../use_settings_updater.test.tsx | 28 ++-- .../use_settings_updater.tsx | 95 ++++++++----- .../impl/assistant/types.ts | 12 -- .../assistant/use_conversation/helpers.ts | 6 +- .../impl/assistant_context/index.tsx | 46 +----- .../impl/mock/system_prompt/index.ts | 11 +- .../packages/kbn-elastic-assistant/index.ts | 3 - .../prompts/field_maps_configuration.ts | 14 +- .../prompts/helpers.ts | 34 +++-- .../prompts/types.ts | 11 +- .../server/routes/prompts/find_route.ts | 2 +- .../public/assistant/provider.tsx | 4 - 37 files changed, 803 insertions(+), 296 deletions(-) create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.ts create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen.ts index d0bd99e063d0c..2d7a4d762eecc 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen.ts @@ -34,6 +34,14 @@ export const PromptDetailsInError = z.object({ name: z.string().optional(), }); +/** + * Prompt type + */ +export type PromptType = z.infer; +export const PromptType = z.enum(['system', 'quick']); +export type PromptTypeEnum = typeof PromptType.enum; +export const PromptTypeEnum = PromptType.enum; + export type NormalizedPromptError = z.infer; export const NormalizedPromptError = z.object({ message: z.string(), @@ -47,11 +55,13 @@ export const PromptResponse = z.object({ id: NonEmptyString, timestamp: NonEmptyString.optional(), name: z.string(), - promptType: z.string(), + promptType: PromptType, content: z.string(), + categories: z.array(z.string()).optional(), + color: z.string().optional(), isNewConversationDefault: z.boolean().optional(), isDefault: z.boolean().optional(), - isShared: z.boolean().optional(), + consumer: z.string().optional(), updatedAt: z.string().optional(), updatedBy: z.string().optional(), createdAt: z.string().optional(), @@ -107,20 +117,24 @@ export const BulkActionBase = z.object({ export type PromptCreateProps = z.infer; export const PromptCreateProps = z.object({ name: z.string(), - promptType: z.string(), + promptType: PromptType, content: z.string(), + color: z.string().optional(), + categories: z.array(z.string()).optional(), isNewConversationDefault: z.boolean().optional(), isDefault: z.boolean().optional(), - isShared: z.boolean().optional(), + consumer: z.string().optional(), }); export type PromptUpdateProps = z.infer; export const PromptUpdateProps = z.object({ id: z.string(), content: z.string().optional(), + color: z.string().optional(), + categories: z.array(z.string()).optional(), isNewConversationDefault: z.boolean().optional(), isDefault: z.boolean().optional(), - isShared: z.boolean().optional(), + consumer: z.string().optional(), }); export type PerformBulkActionRequestBody = z.infer; diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.schema.yaml index ede0136ba710a..5be6bde140b85 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.schema.yaml @@ -78,6 +78,13 @@ components: required: - id + PromptType: + type: string + description: Prompt type + enum: + - system + - quick + NormalizedPromptError: type: object properties: @@ -111,15 +118,21 @@ components: name: type: string promptType: - type: string + $ref: '#/components/schemas/PromptType' content: type: string + categories: + type: array + items: + type: string + color: + type: string isNewConversationDefault: type: boolean isDefault: type: boolean - isShared: - type: boolean + consumer: + type: string updatedAt: type: string updatedBy: @@ -231,15 +244,21 @@ components: name: type: string promptType: - type: string + $ref: '#/components/schemas/PromptType' content: type: string + color: + type: string + categories: + type: array + items: + type: string isNewConversationDefault: type: boolean isDefault: type: boolean - isShared: - type: boolean + consumer: + type: string PromptUpdateProps: type: object @@ -250,9 +269,15 @@ components: type: string content: type: string + color: + type: string + categories: + type: array + items: + type: string isNewConversationDefault: type: boolean isDefault: type: boolean - isShared: - type: boolean + consumer: + type: string diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts new file mode 100644 index 0000000000000..8a676d35465e4 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts @@ -0,0 +1,133 @@ +/* + * 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 { + API_VERSIONS, + ELASTIC_AI_ASSISTANT_PROMPTS_URL_BULK_ACTION, +} from '@kbn/elastic-assistant-common'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; +import { IToasts } from '@kbn/core-notifications-browser'; +import { bulkUpdatePrompts } from './bulk_update_prompts'; + +const prompt1 = { + id: 'field1', + field: 'Prompt field 1', + allowed: true, +}; +const prompt2 = { + ...prompt1, + id: 'field2', + field: 'field 2', +}; +const toasts = { + addError: jest.fn(), +}; +describe('bulkUpdatePrompts', () => { + let httpMock: ReturnType; + + beforeEach(() => { + httpMock = httpServiceMock.createSetupContract(); + + jest.clearAllMocks(); + }); + it('should send a POST request with the correct parameters and receive a successful response', async () => { + const promptsActions = { + create: [], + update: [], + delete: { ids: [] }, + }; + + await bulkUpdatePrompts(httpMock, promptsActions); + + expect(httpMock.fetch).toHaveBeenCalledWith(ELASTIC_AI_ASSISTANT_PROMPTS_URL_BULK_ACTION, { + method: 'POST', + version: API_VERSIONS.internal.v1, + body: JSON.stringify({ + create: [], + update: [], + delete: { ids: [] }, + }), + }); + }); + + it('should transform the prompts dictionary to an array of fields to create', async () => { + const promptsActions = { + create: [prompt1, prompt2], + update: [], + delete: { ids: [] }, + }; + + await bulkUpdatePrompts(httpMock, promptsActions); + + expect(httpMock.fetch).toHaveBeenCalledWith(ELASTIC_AI_ASSISTANT_PROMPTS_URL_BULK_ACTION, { + method: 'POST', + version: API_VERSIONS.internal.v1, + body: JSON.stringify({ + create: [prompt1, prompt2], + update: [], + delete: { ids: [] }, + }), + }); + }); + + it('should transform the prompts dictionary to an array of fields to update', async () => { + const promptsActions = { + update: [prompt1, prompt2], + delete: { ids: [] }, + }; + + await bulkUpdatePrompts(httpMock, promptsActions); + + expect(httpMock.fetch).toHaveBeenCalledWith(ELASTIC_AI_ASSISTANT_PROMPTS_URL_BULK_ACTION, { + method: 'POST', + version: API_VERSIONS.internal.v1, + body: JSON.stringify({ + update: [prompt1, prompt2], + delete: { ids: [] }, + }), + }); + }); + + it('should throw an error with the correct message when receiving an unsuccessful response', async () => { + httpMock.fetch.mockResolvedValue({ + success: false, + attributes: { + errors: [ + { + statusCode: 400, + message: 'Error updating prompt', + prompts: [{ id: prompt1.id, name: prompt1.field }], + }, + ], + }, + }); + const promptsActions = { + create: [], + update: [prompt1], + delete: { ids: [] }, + }; + await bulkUpdatePrompts(httpMock, promptsActions, toasts as unknown as IToasts); + expect(toasts.addError.mock.calls[0][0]).toEqual( + new Error('Error message: Error updating prompt for Prompt 1') + ); + }); + + it('should handle cases where result.attributes.errors is undefined', async () => { + httpMock.fetch.mockResolvedValue({ + success: false, + attributes: {}, + }); + const promptsActions = { + create: [], + update: [], + delete: { ids: [] }, + }; + + await bulkUpdatePrompts(httpMock, promptsActions, toasts as unknown as IToasts); + expect(toasts.addError.mock.calls[0][0]).toEqual(new Error('')); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.ts new file mode 100644 index 0000000000000..2d7b053d7acbd --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.ts @@ -0,0 +1,54 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { HttpSetup, IToasts } from '@kbn/core/public'; +import { + ELASTIC_AI_ASSISTANT_PROMPTS_URL_BULK_ACTION, + API_VERSIONS, +} from '@kbn/elastic-assistant-common'; +import { + PerformBulkActionRequestBody, + PerformBulkActionResponse, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; + +export const bulkUpdatePrompts = async ( + http: HttpSetup, + prompts: PerformBulkActionRequestBody, + toasts?: IToasts +) => { + try { + const result = await http.fetch( + ELASTIC_AI_ASSISTANT_PROMPTS_URL_BULK_ACTION, + { + method: 'POST', + version: API_VERSIONS.internal.v1, + body: JSON.stringify(prompts), + } + ); + + if (!result.success) { + const serverError = result.attributes.errors + ?.map( + (e) => + `${e.status_code ? `Error code: ${e.status_code}. ` : ''}Error message: ${ + e.message + } for prompt ${e.prompts.map((c) => c.name).join(',')}` + ) + .join(',\n'); + throw new Error(serverError); + } + return result; + } catch (error) { + toasts?.addError(error.body && error.body.message ? new Error(error.body.message) : error, { + title: i18n.translate('xpack.elasticAssistant.prompts.bulkActionspromptsError', { + defaultMessage: 'Error updating prompts {error}', + values: { error }, + }), + }); + } +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx new file mode 100644 index 0000000000000..78c45a3329dfa --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx @@ -0,0 +1,60 @@ +/* + * 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 { act, renderHook } from '@testing-library/react-hooks'; + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import type { ReactNode } from 'react'; +import React from 'react'; +import { useFetchPrompts } from './use_fetch_prompts'; +import { HttpSetup } from '@kbn/core-http-browser'; +import { useAssistantContext } from '../../../assistant_context'; +import { API_VERSIONS, defaultAssistantFeatures } from '@kbn/elastic-assistant-common'; + +const http = { + fetch: jest.fn().mockResolvedValue(defaultAssistantFeatures), +} as unknown as HttpSetup; + +jest.mock('../../../assistant_context'); + +const createWrapper = () => { + const queryClient = new QueryClient(); + // eslint-disable-next-line react/display-name + return ({ children }: { children: ReactNode }) => ( + {children} + ); +}; + +describe('useFetchPrompts', () => { + (useAssistantContext as jest.Mock).mockReturnValue({ + http, + assistantAvailability: { + isAssistantEnabled: true, + }, + }); + it(`should make http request to fetch prompts`, async () => { + renderHook(() => useFetchPrompts(), { + wrapper: createWrapper(), + }); + + await act(async () => { + const { waitForNextUpdate } = renderHook(() => useFetchPrompts()); + await waitForNextUpdate(); + expect(http.fetch).toHaveBeenCalledWith('/internal/elastic_assistant/prompts/_find', { + method: 'GET', + query: { + page: 1, + per_page: 1000, + }, + version: API_VERSIONS.internal.v1, + signal: undefined, + }); + + expect(http.fetch).toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts new file mode 100644 index 0000000000000..74b646a8c8223 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts @@ -0,0 +1,74 @@ +/* + * 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 { FindPromptsResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/find_prompts_route.gen'; +import { useQuery } from '@tanstack/react-query'; +import { API_VERSIONS, ELASTIC_AI_ASSISTANT_PROMPTS_URL_FIND } from '@kbn/elastic-assistant-common'; +import { useAssistantContext } from '../../../assistant_context'; + +export interface UseFetchPromptsParams { + signal?: AbortSignal | undefined; + consumer?: string; +} + +/** + * API call for fetching prompts for current spaceId + * + * @param {Object} options - The options object. + * @param {HttpSetup} options.http - HttpSetup + * @param {AbortSignal} [options.signal] - AbortSignal + * + * @returns {useQuery} hook for getting the status of the prompts + */ + +export const useFetchPrompts = (payload?: UseFetchPromptsParams) => { + const { + assistantAvailability: { isAssistantEnabled }, + http, + } = useAssistantContext(); + + const QUERY = { + page: 1, + per_page: 1000, // Continue use in-memory paging till the new design will be ready + filter: `consumer:${payload?.consumer ?? '*'}`, + }; + + const CACHING_KEYS = [ + ELASTIC_AI_ASSISTANT_PROMPTS_URL_FIND, + QUERY.page, + QUERY.per_page, + QUERY.filter, + API_VERSIONS.internal.v1, + ]; + + return useQuery( + CACHING_KEYS, + async () => + http.fetch(ELASTIC_AI_ASSISTANT_PROMPTS_URL_FIND, { + method: 'GET', + version: API_VERSIONS.internal.v1, + query: QUERY, + signal: payload?.signal, + }), + { + initialData: { + data: [], + page: 1, + perPage: 5, + total: 0, + }, + placeholderData: { + data: [], + page: 1, + perPage: 5, + total: 0, + }, + keepPreviousData: true, + enabled: isAssistantEnabled, + } + ); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx index bb2e72e2936d3..5694ee3fac50f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx @@ -17,6 +17,7 @@ import { import { css } from '@emotion/react'; import { DocLinksStart } from '@kbn/core-doc-links-browser'; import { isEmpty } from 'lodash'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { AIConnector } from '../../connectorland/connector_selector'; import { Conversation } from '../../..'; import { AssistantTitle } from '../assistant_title'; @@ -39,6 +40,7 @@ interface OwnProps { title: string; conversations: Record; refetchConversationsState: () => Promise; + allPrompts: PromptResponse[]; } type Props = OwnProps; @@ -62,6 +64,7 @@ export const AssistantHeader: React.FC = ({ title, conversations, refetchConversationsState, + allPrompts, }) => { const showAnonymizedValuesChecked = useMemo( () => @@ -120,6 +123,7 @@ export const AssistantHeader: React.FC = ({ isDisabled={isDisabled} conversations={conversations} onConversationDeleted={onConversationDeleted} + allPrompts={allPrompts} /> <> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx index 020822821d163..c0f40c83d29cd 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx @@ -9,17 +9,18 @@ import React, { useCallback } from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; import { i18n } from '@kbn/i18n'; import { Replacements } from '@kbn/elastic-assistant-common'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import type { ClientMessage } from '../../assistant_context/types'; import { SelectedPromptContext } from '../prompt_context/types'; import { useSendMessage } from '../use_send_message'; import { useConversation } from '../use_conversation'; import { getCombinedMessage } from '../prompt/helpers'; -import { Conversation, Prompt, useAssistantContext } from '../../..'; +import { Conversation, useAssistantContext } from '../../..'; import { getMessageFromRawResponse } from '../helpers'; import { getDefaultSystemPrompt } from '../use_conversation/helpers'; export interface UseChatSendProps { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; currentConversation?: Conversation; editingSystemPromptId: string | undefined; http: HttpSetup; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.tsx index c55540b55b6c0..fd9cddc39dbbe 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.tsx @@ -18,10 +18,13 @@ import { import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { css } from '@emotion/react'; +import { + PromptResponse, + PromptTypeEnum, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { getGenAiConfig } from '../../../connectorland/helpers'; import { AIConnector } from '../../../connectorland/connector_selector'; import { Conversation } from '../../../..'; -import { useAssistantContext } from '../../../assistant_context'; import * as i18n from './translations'; import { DEFAULT_CONVERSATION_TITLE } from '../../use_conversation/translations'; import { useConversation } from '../../use_conversation'; @@ -35,6 +38,7 @@ interface Props { shouldDisableKeyboardShortcut?: () => boolean; isDisabled?: boolean; conversations: Record; + allPrompts: PromptResponse[]; } const getPreviousConversationId = (conversationIds: string[], selectedConversationId: string) => { @@ -64,10 +68,13 @@ export const ConversationSelector: React.FC = React.memo( shouldDisableKeyboardShortcut = () => false, isDisabled = false, conversations, + allPrompts, }) => { - const { allSystemPrompts } = useAssistantContext(); - const { createConversation } = useConversation(); + const allSystemPrompts = useMemo( + () => allPrompts.filter((p) => p.promptType === PromptTypeEnum.system), + [allPrompts] + ); const conversationIds = useMemo(() => Object.keys(conversations), [conversations]); const conversationOptions = useMemo(() => { return Object.values(conversations).map((conversation) => ({ diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx index 179ff7524bd88..f5bdfebe3fdf8 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx @@ -21,7 +21,8 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; import { noop } from 'lodash/fp'; import { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public'; -import { Conversation, Prompt } from '../../../..'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { Conversation } from '../../../..'; import * as i18n from './translations'; import * as i18nModel from '../../../connectorland/models/model_selector/translations'; @@ -36,7 +37,7 @@ import { ConversationsBulkActions } from '../../api'; export interface ConversationSettingsProps { actionTypeRegistry: ActionTypeRegistryContract; - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; defaultConnector?: AIConnector; @@ -390,7 +391,7 @@ export const ConversationSettings: React.FC = React.m helpText={i18n.SETTINGS_PROMPT_HELP_TEXT_TITLE} > = ({ setLastConversationId, getLastConversationId, title, - allSystemPrompts, baseConversations, } = useAssistantContext(); @@ -182,6 +182,13 @@ const AssistantComponent: React.FC = ({ isFetched: isFetchedAnonymizationFields, } = useFetchAnonymizationFields(); + const { + data: allPrompts, + isLoading: isLoadingPrompts, + isError: isErrorPrompts, + isFetched: isFetchedPrompts, + } = useFetchPrompts(); + // Connector details const { data: connectors, isFetchedAfterMount: areConnectorsFetched } = useLoadConnectors({ http, @@ -397,8 +404,12 @@ const AssistantComponent: React.FC = ({ // End Scrolling const selectedSystemPrompt = useMemo( - () => getDefaultSystemPrompt({ allSystemPrompts, conversation: currentConversation }), - [allSystemPrompts, currentConversation] + () => + getDefaultSystemPrompt({ + allSystemPrompts: allPrompts.data, + conversation: currentConversation, + }), + [allPrompts, currentConversation] ); const [editingSystemPromptId, setEditingSystemPromptId] = useState( @@ -409,22 +420,23 @@ const AssistantComponent: React.FC = ({ async ({ cId, cTitle }: { cId: string; cTitle: string }) => { const updatedConv = await refetchResults(); + let selectedConversation; if (cId === '') { setCurrentConversationId(cTitle); - setEditingSystemPromptId( - getDefaultSystemPrompt({ allSystemPrompts, conversation: updatedConv?.data?.[cTitle] }) - ?.id - ); + selectedConversation = updatedConv?.data?.[cTitle]; setCurrentConversationId(cTitle); } else { - const refetchedConversation = await refetchCurrentConversation({ cId }); - setEditingSystemPromptId( - getDefaultSystemPrompt({ allSystemPrompts, conversation: refetchedConversation })?.id - ); + selectedConversation = await refetchCurrentConversation({ cId }); setCurrentConversationId(cId); } + setEditingSystemPromptId( + getDefaultSystemPrompt({ + allSystemPrompts: allPrompts.data, + conversation: selectedConversation, + })?.id + ); }, - [allSystemPrompts, refetchCurrentConversation, refetchResults] + [allPrompts, refetchCurrentConversation, refetchResults] ); const { comments: connectorComments, prompt: connectorPrompt } = useConnectorSetup({ @@ -555,7 +567,7 @@ const AssistantComponent: React.FC = ({ handleRegenerateResponse, isLoading: isLoadingChatSend, } = useChatSend({ - allSystemPrompts, + allSystemPrompts: allPrompts.data, currentConversation, setPromptTextPreview, setUserPrompt, @@ -634,18 +646,18 @@ const AssistantComponent: React.FC = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} setSelectedPromptContexts={setSelectedPromptContexts} isFlyoutMode={isFlyoutMode} + allSystemPrompts={allPrompts.data} /> )} ), [ + getComments, abortStream, - refetchCurrentConversation, currentConversation, - editingSystemPromptId, - getComments, showAnonymizedValues, + refetchCurrentConversation, handleRegenerateResponse, isEnabledKnowledgeBase, isEnabledRAGAlerts, @@ -653,12 +665,14 @@ const AssistantComponent: React.FC = ({ currentUserAvatar, isFlyoutMode, selectedPromptContextsCount, + editingSystemPromptId, isNewConversation, isSettingsModalVisible, promptContexts, promptTextPreview, handleOnSystemPromptSelectionChange, selectedPromptContexts, + allPrompts.data, ] ); @@ -862,6 +876,7 @@ const AssistantComponent: React.FC = ({ isSettingsModalVisible={isSettingsModalVisible} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode + allSystemPrompts={allPrompts.data} /> @@ -885,6 +900,7 @@ const AssistantComponent: React.FC = ({ ); }, [ + allPrompts.data, comments, connectorPrompt, currentConversation, @@ -1082,6 +1098,7 @@ const AssistantComponent: React.FC = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} trackPrompt={trackPrompt} isFlyoutMode={isFlyoutMode} + allPrompts={allPrompts.data} /> )} @@ -1117,6 +1134,7 @@ const AssistantComponent: React.FC = ({ conversations={conversations} onConversationDeleted={handleOnConversationDeleted} refetchConversationsState={refetchConversationsState} + allPrompts={allPrompts.data} /> )} @@ -1195,6 +1213,7 @@ const AssistantComponent: React.FC = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} trackPrompt={trackPrompt} isFlyoutMode={isFlyoutMode} + allPrompts={allPrompts.data} /> )} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts index bd00058b4bbd3..f23c7f4de8f59 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts @@ -6,10 +6,10 @@ */ import { Replacements, transformRawData } from '@kbn/elastic-assistant-common'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import type { ClientMessage } from '../../assistant_context/types'; import { getAnonymizedValue as defaultGetAnonymizedValue } from '../get_anonymized_value'; import type { SelectedPromptContext } from '../prompt_context/types'; -import type { Prompt } from '../types'; import { SYSTEM_PROMPT_CONTEXT_NON_I18N } from '../../content/prompts/system/translations'; export const getSystemMessages = ({ @@ -17,7 +17,7 @@ export const getSystemMessages = ({ selectedSystemPrompt, }: { isNewChat: boolean; - selectedSystemPrompt: Prompt | undefined; + selectedSystemPrompt: PromptResponse | undefined; }): ClientMessage[] => { if (!isNewChat || selectedSystemPrompt == null) { return []; @@ -53,7 +53,7 @@ export function getCombinedMessage({ isNewChat: boolean; promptText: string; selectedPromptContexts: Record; - selectedSystemPrompt: Prompt | undefined; + selectedSystemPrompt: PromptResponse | undefined; }): ClientMessageWithReplacements { let replacements: Replacements = currentReplacements ?? {}; const onNewReplacements = (newReplacements: Replacements) => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx index 7b3e91147635f..4a21c147332bd 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx @@ -5,12 +5,12 @@ * 2.0. */ -import type { Prompt } from '../types'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; export const getPromptById = ({ prompts, id, }: { - prompts: Prompt[]; + prompts: PromptResponse[]; id: string; -}): Prompt | undefined => prompts.find((p) => p.id === id); +}): PromptResponse | undefined => prompts.find((p) => p.id === id); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx index b2f5c1a3a2e33..b1242c93e0dfb 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx @@ -10,6 +10,7 @@ import React, { useMemo } from 'react'; // eslint-disable-next-line @kbn/eslint/module_migration import styled from 'styled-components'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation } from '../../..'; import type { PromptContext, SelectedPromptContext } from '../prompt_context/types'; import { SystemPrompt } from './system_prompt'; @@ -31,6 +32,7 @@ export interface Props { React.SetStateAction> >; isFlyoutMode: boolean; + allSystemPrompts: PromptResponse[]; } const PreviewText = styled(EuiText)` @@ -49,12 +51,14 @@ const PromptEditorComponent: React.FC = ({ setIsSettingsModalVisible, setSelectedPromptContexts, isFlyoutMode, + allSystemPrompts, }) => { const commentBody = useMemo( () => ( <> {isNewConversation && ( = ({ ), [ + isNewConversation, + allSystemPrompts, conversation, editingSystemPromptId, - isNewConversation, - isSettingsModalVisible, onSystemPromptSelectionChange, + isSettingsModalVisible, + setIsSettingsModalVisible, + isFlyoutMode, promptContexts, - promptTextPreview, selectedPromptContexts, - setIsSettingsModalVisible, setSelectedPromptContexts, - isFlyoutMode, + promptTextPreview, ] ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx index a52ed303d4a63..33850b6725d9a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx @@ -11,9 +11,8 @@ import React from 'react'; // eslint-disable-next-line @kbn/eslint/module_migration import styled from 'styled-components'; -import { css } from '@emotion/react'; import { isEmpty } from 'lodash/fp'; -import type { Prompt } from '../../types'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { EMPTY_PROMPT } from './translations'; const Strong = styled.strong` @@ -24,27 +23,9 @@ export const getOptionFromPrompt = ({ content, id, name, - showTitles = false, - isFlyoutMode, -}: Prompt & { showTitles?: boolean }): EuiSuperSelectOption => ({ +}: PromptResponse & { showTitles?: boolean }): EuiSuperSelectOption => ({ value: id, - inputDisplay: isFlyoutMode ? ( - name - ) : ( - - {showTitles ? name : content} - - ), + inputDisplay: name, dropdownDisplay: ( <> {name} @@ -60,13 +41,12 @@ export const getOptionFromPrompt = ({ }); interface GetOptionsProps { - prompts: Prompt[] | undefined; + prompts: PromptResponse[] | undefined; showTitles?: boolean; isFlyoutMode: boolean; } export const getOptions = ({ prompts, showTitles = false, - isFlyoutMode = false, }: GetOptionsProps): Array> => - prompts?.map((p) => getOptionFromPrompt({ ...p, showTitles, isFlyoutMode })) ?? []; + prompts?.map((p) => getOptionFromPrompt({ ...p, showTitles })) ?? []; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx index d6a507b6deeed..90b276def6315 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx @@ -10,7 +10,7 @@ import React, { useCallback, useMemo } from 'react'; import { css } from '@emotion/react'; import { isEmpty } from 'lodash/fp'; -import { useAssistantContext } from '../../../assistant_context'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation } from '../../../..'; import * as i18n from './translations'; import { SelectSystemPrompt } from './select_system_prompt'; @@ -22,6 +22,7 @@ interface Props { onSystemPromptSelectionChange: (systemPromptId: string | undefined) => void; setIsSettingsModalVisible: React.Dispatch>; isFlyoutMode: boolean; + allSystemPrompts: PromptResponse[]; } const SystemPromptComponent: React.FC = ({ @@ -31,9 +32,8 @@ const SystemPromptComponent: React.FC = ({ onSystemPromptSelectionChange, setIsSettingsModalVisible, isFlyoutMode, + allSystemPrompts, }) => { - const { allSystemPrompts } = useAssistantContext(); - const selectedPrompt = useMemo(() => { if (editingSystemPromptId !== undefined) { return ( @@ -58,7 +58,7 @@ const SystemPromptComponent: React.FC = ({ if (isFlyoutMode) { return ( = ({
{selectedPrompt == null || isEditing ? ( void; isClearable?: boolean; isEditing?: boolean; @@ -49,7 +52,7 @@ export interface Props { const ADD_NEW_SYSTEM_PROMPT = 'ADD_NEW_SYSTEM_PROMPT'; const SelectSystemPromptComponent: React.FC = ({ - allSystemPrompts, + allPrompts, compressed = false, conversation, selectedPrompt, @@ -68,6 +71,11 @@ const SelectSystemPromptComponent: React.FC = ({ const { setSelectedSettingsTab } = useAssistantContext(); const { setApiConfig } = useConversation(); + const allSystemPrompts = useMemo( + () => allPrompts.filter((p) => p.promptType === PromptTypeEnum.system), + [allPrompts] + ); + const [isOpenLocal, setIsOpenLocal] = useState(isOpen); const [valueOfSelected, setValueOfSelected] = useState( selectedPrompt?.id ?? allSystemPrompts?.[0]?.id @@ -76,7 +84,7 @@ const SelectSystemPromptComponent: React.FC = ({ // Write the selected system prompt to the conversation config const setSelectedSystemPrompt = useCallback( - (prompt: Prompt | undefined) => { + (prompt: PromptResponse | undefined) => { if (conversation && conversation.apiConfig) { setApiConfig({ conversation, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx index 1ec1c4b721065..ce127bc5e6319 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx @@ -18,8 +18,8 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { TEST_IDS } from '../../../../constants'; -import { Prompt } from '../../../../../..'; import * as i18n from './translations'; import { SYSTEM_PROMPT_DEFAULT_NEW_CONVERSATION } from '../translations'; @@ -27,10 +27,10 @@ export const SYSTEM_PROMPT_SELECTOR_CLASSNAME = 'systemPromptSelector'; interface Props { onSystemPromptDeleted: (systemPromptTitle: string) => void; - onSystemPromptSelectionChange: (systemPrompt?: Prompt | string) => void; - systemPrompts: Prompt[]; + onSystemPromptSelectionChange: (systemPrompt?: PromptResponse | string) => void; + systemPrompts: PromptResponse[]; autoFocus?: boolean; - selectedSystemPrompt?: Prompt; + selectedSystemPrompt?: PromptResponse; } export type SystemPromptSelectorOption = EuiComboBoxOptionOption<{ diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx index 88f00de57f444..721747e54434d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx @@ -23,8 +23,12 @@ import { keyBy } from 'lodash/fp'; import { css } from '@emotion/react'; import { ApiConfig } from '@kbn/elastic-assistant-common'; +import { + PerformBulkActionRequestBody, + PromptResponse, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { AIConnector } from '../../../../connectorland/connector_selector'; -import { Conversation, Prompt } from '../../../../..'; +import { Conversation } from '../../../../..'; import * as i18n from './translations'; import { ConversationMultiSelector } from './conversation_multi_selector/conversation_multi_selector'; import { SystemPromptSelector } from './system_prompt_selector/system_prompt_selector'; @@ -34,14 +38,16 @@ import { ConversationsBulkActions } from '../../../api'; interface Props { conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; - onSelectedSystemPromptChange: (systemPrompt?: Prompt) => void; - selectedSystemPrompt: Prompt | undefined; - setUpdatedSystemPromptSettings: React.Dispatch>; + onSelectedSystemPromptChange: (systemPrompt?: PromptResponse) => void; + selectedSystemPrompt: PromptResponse | undefined; + setPromptsBulkActions: React.Dispatch>; + setUpdatedSystemPromptSettings: React.Dispatch>; setConversationSettings: React.Dispatch>>; - systemPromptSettings: Prompt[]; + systemPromptSettings: PromptResponse[]; setConversationsSettingsBulkActions: React.Dispatch< React.SetStateAction >; + promptsBulkActions: PerformBulkActionRequestBody; defaultConnector?: AIConnector; } @@ -58,7 +64,9 @@ export const SystemPromptSettings: React.FC = React.memo( systemPromptSettings, conversationsSettingsBulkActions, setConversationsSettingsBulkActions, + promptsBulkActions, defaultConnector, + setPromptsBulkActions, }) => { // Prompt const promptContent = useMemo( @@ -69,11 +77,11 @@ export const SystemPromptSettings: React.FC = React.memo( const handlePromptContentChange = useCallback( (e: React.ChangeEvent) => { if (selectedSystemPrompt != null) { - setUpdatedSystemPromptSettings((prev): Prompt[] => { + setUpdatedSystemPromptSettings((prev): PromptResponse[] => { const alreadyExists = prev.some((sp) => sp.id === selectedSystemPrompt.id); if (alreadyExists) { - return prev.map((sp): Prompt => { + return prev.map((sp): PromptResponse => { if (sp.id === selectedSystemPrompt.id) { return { ...sp, @@ -86,9 +94,47 @@ export const SystemPromptSettings: React.FC = React.memo( return prev; }); + + const existingPrompt = systemPromptSettings.find( + (sp) => sp.id === selectedSystemPrompt.id + ); + if (existingPrompt) { + setPromptsBulkActions({ + ...promptsBulkActions, + ...(selectedSystemPrompt.name !== selectedSystemPrompt.id + ? { + update: [ + ...(promptsBulkActions.update ?? []).filter( + (p) => p.id !== selectedSystemPrompt.id + ), + { + ...selectedSystemPrompt, + content: e.target.value, + }, + ], + } + : { + create: [ + ...(promptsBulkActions.create ?? []).filter( + (p) => p.name !== selectedSystemPrompt.name + ), + { + ...selectedSystemPrompt, + content: e.target.value, + }, + ], + }), + }); + } } }, - [selectedSystemPrompt, setUpdatedSystemPromptSettings] + [ + promptsBulkActions, + selectedSystemPrompt, + setPromptsBulkActions, + setUpdatedSystemPromptSettings, + systemPromptSettings, + ] ); // Conversations this system prompt should be a default for @@ -238,21 +284,53 @@ export const SystemPromptSettings: React.FC = React.memo( }; }); }); + setPromptsBulkActions({ + ...promptsBulkActions, + ...(selectedSystemPrompt.name !== selectedSystemPrompt.id + ? { + update: [ + ...(promptsBulkActions.update ?? []).filter( + (p) => p.id !== selectedSystemPrompt.id + ), + { + ...selectedSystemPrompt, + isNewConversationDefault: isChecked, + }, + ], + } + : { + create: [ + ...(promptsBulkActions.create ?? []).filter( + (p) => p.name !== selectedSystemPrompt.name + ), + { + ...selectedSystemPrompt, + isNewConversationDefault: isChecked, + }, + ], + }), + }); } }, - [selectedSystemPrompt, setUpdatedSystemPromptSettings] + [ + promptsBulkActions, + selectedSystemPrompt, + setUpdatedSystemPromptSettings, + setPromptsBulkActions, + ] ); // When top level system prompt selection changes const onSystemPromptSelectionChange = useCallback( - (systemPrompt?: Prompt | string) => { + (systemPrompt?: PromptResponse | string) => { const isNew = typeof systemPrompt === 'string'; - const newSelectedSystemPrompt: Prompt | undefined = isNew + const newSelectedSystemPrompt: PromptResponse | undefined = isNew ? { - id: systemPrompt ?? '', + id: systemPrompt, content: '', name: systemPrompt ?? '', promptType: 'system', + consumer: 'security', } : systemPrompt; @@ -266,18 +344,38 @@ export const SystemPromptSettings: React.FC = React.memo( return prev; }); + setPromptsBulkActions({ + ...promptsBulkActions, + create: [ + ...(promptsBulkActions.create ?? []), + { + ...newSelectedSystemPrompt, + }, + ], + }); } onSelectedSystemPromptChange(newSelectedSystemPrompt); }, - [onSelectedSystemPromptChange, setUpdatedSystemPromptSettings] + [ + onSelectedSystemPromptChange, + promptsBulkActions, + setPromptsBulkActions, + setUpdatedSystemPromptSettings, + ] ); const onSystemPromptDeleted = useCallback( (id: string) => { setUpdatedSystemPromptSettings((prev) => prev.filter((sp) => sp.id !== id)); + setPromptsBulkActions({ + ...promptsBulkActions, + delete: { + ids: [...(promptsBulkActions.delete?.ids ?? []), id], + }, + }); }, - [setUpdatedSystemPromptSettings] + [promptsBulkActions, setPromptsBulkActions, setUpdatedSystemPromptSettings] ); return ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx index 5aaff2bbc8fc9..118fabda468c9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx @@ -18,15 +18,15 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import * as i18n from './translations'; -import { QuickPrompt } from '../types'; interface Props { isDisabled?: boolean; onQuickPromptDeleted: (quickPromptTitle: string) => void; - onQuickPromptSelectionChange: (quickPrompt?: QuickPrompt | string) => void; - quickPrompts: QuickPrompt[]; - selectedQuickPrompt?: QuickPrompt; + onQuickPromptSelectionChange: (quickPrompt?: PromptResponse | string) => void; + quickPrompts: PromptResponse[]; + selectedQuickPrompt?: PromptResponse; } export type QuickPromptSelectorOption = EuiComboBoxOptionOption<{ isDefault: boolean }>; @@ -48,8 +48,8 @@ export const QuickPromptSelector: React.FC = React.memo( value: { isDefault: qp.isDefault ?? false, }, - label: qp.title, - 'data-test-subj': qp.title, + label: qp.name, + 'data-test-subj': qp.name, color: qp.color, })) ); @@ -60,7 +60,7 @@ export const QuickPromptSelector: React.FC = React.memo( value: { isDefault: true, }, - label: selectedQuickPrompt.title, + label: selectedQuickPrompt.name, color: selectedQuickPrompt.color, }, ] @@ -72,7 +72,7 @@ export const QuickPromptSelector: React.FC = React.memo( const newQuickPrompt = quickPromptSelectorOption.length === 0 ? undefined - : quickPrompts.find((qp) => qp.title === quickPromptSelectorOption[0]?.label) ?? + : quickPrompts.find((qp) => qp.name === quickPromptSelectorOption[0]?.label) ?? quickPromptSelectorOption[0]?.label; onQuickPromptSelectionChange(newQuickPrompt); }, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx index 38bbb0e6899be..12c1256f2538b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx @@ -18,20 +18,22 @@ import { import { EuiSetColorMethod } from '@elastic/eui/src/services/color_picker/color_picker'; import { css } from '@emotion/react'; -import { PromptContextTemplate } from '../../../..'; +import { + PromptResponse, + PromptTypeEnum, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptContextTemplate, useAssistantContext } from '../../../..'; import * as i18n from './translations'; -import { QuickPrompt } from '../types'; import { QuickPromptSelector } from '../quick_prompt_selector/quick_prompt_selector'; import { PromptContextSelector } from '../prompt_context_selector/prompt_context_selector'; -import { useAssistantContext } from '../../../assistant_context'; const DEFAULT_COLOR = '#D36086'; interface Props { - onSelectedQuickPromptChange: (quickPrompt?: QuickPrompt) => void; - quickPromptSettings: QuickPrompt[]; - selectedQuickPrompt: QuickPrompt | undefined; - setUpdatedQuickPromptSettings: React.Dispatch>; + onSelectedQuickPromptChange: (quickPrompt?: PromptResponse) => void; + quickPromptSettings: PromptResponse[]; + selectedQuickPrompt: PromptResponse | undefined; + setUpdatedQuickPromptSettings: React.Dispatch>; } /** @@ -45,19 +47,21 @@ export const QuickPromptSettings: React.FC = React.memo( setUpdatedQuickPromptSettings, }) => { const { basePromptContexts } = useAssistantContext(); - // Prompt - const prompt = useMemo(() => selectedQuickPrompt?.prompt ?? '', [selectedQuickPrompt?.prompt]); + const prompt = useMemo( + () => selectedQuickPrompt?.content ?? '', + [selectedQuickPrompt?.content] + ); const handlePromptChange = useCallback( (e: React.ChangeEvent) => { if (selectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === selectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); if (alreadyExists) { return prev.map((qp) => { - if (qp.title === selectedQuickPrompt.title) { + if (qp.name === selectedQuickPrompt.name) { return { ...qp, prompt: e.target.value, @@ -84,11 +88,11 @@ export const QuickPromptSettings: React.FC = React.memo( (color, { hex, isValid }) => { if (selectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === selectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); if (alreadyExists) { return prev.map((qp) => { - if (qp.title === selectedQuickPrompt.title) { + if (qp.name === selectedQuickPrompt.name) { return { ...qp, color, @@ -107,7 +111,7 @@ export const QuickPromptSettings: React.FC = React.memo( // Prompt Contexts const selectedPromptContexts = useMemo( () => - basePromptContexts.filter((bpc) => + basePromptContexts?.filter((bpc) => selectedQuickPrompt?.categories?.some((cat) => bpc?.category === cat) ) ?? [], [basePromptContexts, selectedQuickPrompt?.categories] @@ -117,11 +121,11 @@ export const QuickPromptSettings: React.FC = React.memo( (pc: PromptContextTemplate[]) => { if (selectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === selectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); if (alreadyExists) { return prev.map((qp) => { - if (qp.title === selectedQuickPrompt.title) { + if (qp.name === selectedQuickPrompt.name) { return { ...qp, categories: pc.map((p) => p.category), @@ -139,20 +143,22 @@ export const QuickPromptSettings: React.FC = React.memo( // When top level quick prompt selection changes const onQuickPromptSelectionChange = useCallback( - (quickPrompt?: QuickPrompt | string) => { + (quickPrompt?: PromptResponse | string) => { const isNew = typeof quickPrompt === 'string'; - const newSelectedQuickPrompt: QuickPrompt | undefined = isNew + const newSelectedQuickPrompt: PromptResponse | undefined = isNew ? { - title: quickPrompt ?? '', - prompt: '', + name: quickPrompt ?? '', + content: '', + id: '', color: DEFAULT_COLOR, categories: [], + promptType: PromptTypeEnum.quick, } : quickPrompt; if (newSelectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === newSelectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === newSelectedQuickPrompt.name); if (!alreadyExists) { return [...prev, newSelectedQuickPrompt]; @@ -168,8 +174,8 @@ export const QuickPromptSettings: React.FC = React.memo( ); const onQuickPromptDeleted = useCallback( - (title: string) => { - setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.title !== title)); + (name: string) => { + setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.name !== name)); }, [setUpdatedQuickPromptSettings] ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx index 63e57424fa49b..601541748d5ad 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx @@ -17,6 +17,10 @@ import { import { useMeasure } from 'react-use'; import { css } from '@emotion/react'; +import { + PromptResponse, + PromptTypeEnum, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { QuickPrompt } from '../../..'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; @@ -30,6 +34,7 @@ interface QuickPromptsProps { setIsSettingsModalVisible: React.Dispatch>; trackPrompt: (prompt: string) => void; isFlyoutMode: boolean; + allPrompts: PromptResponse[]; } /** @@ -38,11 +43,10 @@ interface QuickPromptsProps { * and localstorage for storing new and edited prompts. */ export const QuickPrompts: React.FC = React.memo( - ({ setInput, setIsSettingsModalVisible, trackPrompt, isFlyoutMode }) => { + ({ setInput, setIsSettingsModalVisible, trackPrompt, isFlyoutMode, allPrompts }) => { const [quickPromptsContainerRef, { width }] = useMeasure(); - const { allQuickPrompts, knowledgeBase, promptContexts, setSelectedSettingsTab } = - useAssistantContext(); + const { knowledgeBase, promptContexts, setSelectedSettingsTab } = useAssistantContext(); const contextFilteredQuickPrompts = useMemo(() => { const registeredPromptContextTitles = Object.values(promptContexts).map((pc) => pc.category); @@ -50,17 +54,21 @@ export const QuickPrompts: React.FC = React.memo( if (knowledgeBase.isEnabledKnowledgeBase) { registeredPromptContextTitles.push(KNOWLEDGE_BASE_CATEGORY); } - return allQuickPrompts.filter((quickPrompt) => { + return allPrompts.filter((prompt) => { + // only quick prompts + if (prompt.promptType !== PromptTypeEnum.quick) { + return false; + } // Return quick prompt as match if it has no categories, otherwise ensure category exists in registered prompt contexts - if (quickPrompt.categories == null || quickPrompt.categories.length === 0) { + if (!prompt.categories || prompt.categories.length === 0) { return true; } else { - return quickPrompt.categories.some((category) => { + return prompt.categories?.some((category) => { return registeredPromptContextTitles.includes(category); }); } }); - }, [allQuickPrompts, knowledgeBase.isEnabledKnowledgeBase, promptContexts]); + }, [allPrompts, knowledgeBase.isEnabledKnowledgeBase, promptContexts]); // Overflow state const [isOverflowPopoverOpen, setIsOverflowPopoverOpen] = useState(false); @@ -137,9 +145,9 @@ export const QuickPrompts: React.FC = React.memo( onClickAddQuickPrompt(badge)} - onClickAriaLabel={badge.title} + onClickAriaLabel={badge.name} > - {badge.title} + {badge.name} ))} @@ -172,9 +180,9 @@ export const QuickPrompts: React.FC = React.memo( onClickOverflowQuickPrompt(badge)} - onClickAriaLabel={badge.title} + onClickAriaLabel={badge.name} > - {badge.title} + {badge.name} ))} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx index f83e6c0d72ee6..d05511d7a68db 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx @@ -23,8 +23,9 @@ import { // eslint-disable-next-line @kbn/eslint/module_migration import styled from 'styled-components'; import { css } from '@emotion/react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { AIConnector } from '../../connectorland/connector_selector'; -import { Conversation, Prompt, QuickPrompt } from '../../..'; +import { Conversation } from '../../..'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; import { TEST_IDS } from '../constants'; @@ -38,6 +39,7 @@ import { SystemPromptSettings, } from '.'; import { useFetchAnonymizationFields } from '../api/anonymization_fields/use_fetch_anonymization_fields'; +import { useFetchPrompts } from '../api/prompts/use_fetch_prompts'; const StyledEuiModal = styled(EuiModal)` width: 800px; @@ -95,6 +97,7 @@ export const AssistantSettings: React.FC = React.memo( const { data: anonymizationFields, refetch: refetchAnonymizationFieldsResults } = useFetchAnonymizationFields(); + const { data: allPrompts } = useFetchPrompts(); const { conversationSettings, @@ -106,7 +109,7 @@ export const AssistantSettings: React.FC = React.memo( setUpdatedAssistantStreamingEnabled, setUpdatedKnowledgeBaseSettings, setUpdatedQuickPromptSettings, - setUpdatedSystemPromptSettings, + promptsBulkActions, saveSettings, conversationsSettingsBulkActions, updatedAnonymizationData, @@ -114,7 +117,9 @@ export const AssistantSettings: React.FC = React.memo( anonymizationFieldsBulkActions, setAnonymizationFieldsBulkActions, setUpdatedAnonymizationData, - } = useSettingsUpdater(conversations, anonymizationFields); + setPromptsBulkActions, + setUpdatedSystemPromptSettings, + } = useSettingsUpdater(conversations, anonymizationFields, allPrompts); // Local state for saving previously selected items so tab switching is friendlier // Conversation Selection State @@ -131,21 +136,21 @@ export const AssistantSettings: React.FC = React.memo( ); // Quick Prompt Selection State - const [selectedQuickPrompt, setSelectedQuickPrompt] = useState(); - const onHandleSelectedQuickPromptChange = useCallback((quickPrompt?: QuickPrompt) => { + const [selectedQuickPrompt, setSelectedQuickPrompt] = useState(); + const onHandleSelectedQuickPromptChange = useCallback((quickPrompt?: PromptResponse) => { setSelectedQuickPrompt(quickPrompt); }, []); useEffect(() => { if (selectedQuickPrompt != null) { setSelectedQuickPrompt( - quickPromptSettings.find((q) => q.title === selectedQuickPrompt.title) + quickPromptSettings.find((q) => q.name === selectedQuickPrompt.name) ); } }, [quickPromptSettings, selectedQuickPrompt]); // System Prompt Selection State - const [selectedSystemPrompt, setSelectedSystemPrompt] = useState(); - const onHandleSelectedSystemPromptChange = useCallback((systemPrompt?: Prompt) => { + const [selectedSystemPrompt, setSelectedSystemPrompt] = useState(); + const onHandleSelectedSystemPromptChange = useCallback((systemPrompt?: PromptResponse) => { setSelectedSystemPrompt(systemPrompt); }, []); useEffect(() => { @@ -347,6 +352,8 @@ export const AssistantSettings: React.FC = React.memo( setConversationsSettingsBulkActions={setConversationsSettingsBulkActions} conversationsSettingsBulkActions={conversationsSettingsBulkActions} setUpdatedSystemPromptSettings={setUpdatedSystemPromptSettings} + setPromptsBulkActions={setPromptsBulkActions} + promptsBulkActions={promptsBulkActions} /> )} {selectedSettingsTab === ANONYMIZATION_TAB && ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx index 79a050b11bb27..40b2eb7139878 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx @@ -16,7 +16,8 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; -import { Conversation, Prompt, QuickPrompt } from '../../..'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { Conversation } from '../../..'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; import { useSettingsUpdater } from './use_settings_updater/use_settings_updater'; @@ -31,6 +32,7 @@ import { import { useLoadConnectors } from '../../connectorland/use_load_connectors'; import { getDefaultConnector } from '../helpers'; import { useFetchAnonymizationFields } from '../api/anonymization_fields/use_fetch_anonymization_fields'; +import { useFetchPrompts } from '../api/prompts/use_fetch_prompts'; export const CONVERSATIONS_TAB = 'CONVERSATION_TAB' as const; export const QUICK_PROMPTS_TAB = 'QUICK_PROMPTS_TAB' as const; @@ -75,6 +77,8 @@ export const AssistantSettingsManagement: React.FC = React.memo( const { data: anonymizationFields } = useFetchAnonymizationFields(); + const { data: allPrompts } = useFetchPrompts(); + // Connector details const { data: connectors } = useLoadConnectors({ http, @@ -93,7 +97,7 @@ export const AssistantSettingsManagement: React.FC = React.memo( setUpdatedAssistantStreamingEnabled, setUpdatedKnowledgeBaseSettings, setUpdatedQuickPromptSettings, - setUpdatedSystemPromptSettings, + setPromptsBulkActions, saveSettings, conversationsSettingsBulkActions, updatedAnonymizationData, @@ -101,10 +105,13 @@ export const AssistantSettingsManagement: React.FC = React.memo( anonymizationFieldsBulkActions, setAnonymizationFieldsBulkActions, setUpdatedAnonymizationData, + setUpdatedSystemPromptSettings, + promptsBulkActions, resetSettings, } = useSettingsUpdater( conversations, - anonymizationFields ?? { page: 0, perPage: 0, total: 0, data: [] } + anonymizationFields ?? { page: 0, perPage: 0, total: 0, data: [] }, + allPrompts ); // Local state for saving previously selected items so tab switching is friendlier @@ -126,21 +133,21 @@ export const AssistantSettingsManagement: React.FC = React.memo( }, [conversationSettings, selectedConversation]); // Quick Prompt Selection State - const [selectedQuickPrompt, setSelectedQuickPrompt] = useState(); - const onHandleSelectedQuickPromptChange = useCallback((quickPrompt?: QuickPrompt) => { + const [selectedQuickPrompt, setSelectedQuickPrompt] = useState(); + const onHandleSelectedQuickPromptChange = useCallback((quickPrompt?: PromptResponse) => { setSelectedQuickPrompt(quickPrompt); }, []); useEffect(() => { if (selectedQuickPrompt != null) { setSelectedQuickPrompt( - quickPromptSettings.find((q) => q.title === selectedQuickPrompt.title) + quickPromptSettings.find((q) => q.name === selectedQuickPrompt.name) ); } }, [quickPromptSettings, selectedQuickPrompt]); // System Prompt Selection State - const [selectedSystemPrompt, setSelectedSystemPrompt] = useState(); - const onHandleSelectedSystemPromptChange = useCallback((systemPrompt?: Prompt) => { + const [selectedSystemPrompt, setSelectedSystemPrompt] = useState(); + const onHandleSelectedSystemPromptChange = useCallback((systemPrompt?: PromptResponse) => { setSelectedSystemPrompt(systemPrompt); }, []); useEffect(() => { @@ -284,6 +291,8 @@ export const AssistantSettingsManagement: React.FC = React.memo( )} conversationsSettingsBulkActions={conversationsSettingsBulkActions} setUpdatedSystemPromptSettings={handleChange(setUpdatedSystemPromptSettings)} + promptsBulkActions={promptsBulkActions} + setPromptsBulkActions={handleChange(setPromptsBulkActions)} /> )} {selectedSettingsTab === ANONYMIZATION_TAB && ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx index 08e9fb434b051..c1de62c50c2e0 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx @@ -9,13 +9,13 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { DEFAULT_LATEST_ALERTS } from '../../../assistant_context/constants'; import { alertConvo, customConvo, welcomeConvo } from '../../../mock/conversation'; import { useSettingsUpdater } from './use_settings_updater'; -import { Prompt } from '../../../..'; import { defaultSystemPrompt, mockSuperheroSystemPrompt, mockSystemPrompt, } from '../../../mock/system_prompt'; import { HttpSetup } from '@kbn/core/public'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; const mockConversations = { [alertConvo.title]: alertConvo, @@ -26,8 +26,8 @@ const mockHttp = { fetch: jest.fn(), } as unknown as HttpSetup; -const mockSystemPrompts: Prompt[] = [mockSystemPrompt]; -const mockQuickPrompts: Prompt[] = [defaultSystemPrompt]; +const mockSystemPrompts: PromptResponse[] = [mockSystemPrompt]; +const mockQuickPrompts: PromptResponse[] = [defaultSystemPrompt]; const anonymizationFields = { total: 2, @@ -66,7 +66,7 @@ const mockValues = { const updatedValues = { conversations: { [customConvo.title]: customConvo }, - allSystemPrompts: [mockSuperheroSystemPrompt], + allSystemPrompts: { update: [mockSuperheroSystemPrompt] }, allQuickPrompts: [{ title: 'Prompt 2', prompt: 'Prompt 2', color: 'red' }], updatedAnonymizationData: { total: 2, @@ -100,7 +100,7 @@ describe('useSettingsUpdater', () => { it('should set all state variables to their initial values when resetSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, anonymizationFields) + useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) ); await waitForNextUpdate(); const { @@ -111,12 +111,12 @@ describe('useSettingsUpdater', () => { setUpdatedKnowledgeBaseSettings, setUpdatedAssistantStreamingEnabled, resetSettings, + setPromptsBulkActions, } = result.current; setConversationSettings(updatedValues.conversations); setConversationsSettingsBulkActions({}); - setUpdatedQuickPromptSettings(updatedValues.allQuickPrompts); - setUpdatedSystemPromptSettings(updatedValues.allSystemPrompts); + setPromptsBulkActions(updatedValues.allSystemPrompts); setUpdatedAnonymizationData(updatedValues.updatedAnonymizationData); setUpdatedKnowledgeBaseSettings(updatedValues.knowledgeBase); setUpdatedAssistantStreamingEnabled(updatedValues.assistantStreamingEnabled); @@ -148,23 +148,21 @@ describe('useSettingsUpdater', () => { it('should update all state variables to their updated values when saveSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, anonymizationFields) + useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) ); await waitForNextUpdate(); const { setConversationSettings, setConversationsSettingsBulkActions, - setUpdatedQuickPromptSettings, - setUpdatedSystemPromptSettings, setAnonymizationFieldsBulkActions, setUpdatedKnowledgeBaseSettings, + setPromptsBulkActions, } = result.current; setConversationSettings(updatedValues.conversations); setConversationsSettingsBulkActions({ delete: { ids: ['1'] } }); setAnonymizationFieldsBulkActions({ delete: { ids: ['1'] } }); - setUpdatedQuickPromptSettings(updatedValues.allQuickPrompts); - setUpdatedSystemPromptSettings(updatedValues.allSystemPrompts); + setPromptsBulkActions(updatedValues.allSystemPrompts); setUpdatedAnonymizationData(updatedValues.updatedAnonymizationData); setUpdatedKnowledgeBaseSettings(updatedValues.knowledgeBase); @@ -189,7 +187,7 @@ describe('useSettingsUpdater', () => { it('should track which toggles have been updated when saveSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, anonymizationFields) + useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; @@ -206,7 +204,7 @@ describe('useSettingsUpdater', () => { it('should track only toggles that updated', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, anonymizationFields) + useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; @@ -224,7 +222,7 @@ describe('useSettingsUpdater', () => { it('if no toggles update, do not track anything', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, anonymizationFields) + useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx index 1e1c3b0b026d6..5385b93cd36ce 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx @@ -8,7 +8,13 @@ import React, { useCallback, useEffect, useState } from 'react'; import { FindAnonymizationFieldsResponse } from '@kbn/elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.gen'; import { PerformBulkActionRequestBody } from '@kbn/elastic-assistant-common/impl/schemas/anonymization_fields/bulk_crud_anonymization_fields_route.gen'; -import { Conversation, Prompt, QuickPrompt } from '../../../..'; +import { + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, + PromptResponse, + PromptTypeEnum, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { FindPromptsResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/find_prompts_route.gen'; +import { Conversation } from '../../../..'; import { useAssistantContext } from '../../../assistant_context'; import type { KnowledgeBaseConfig } from '../../types'; import { @@ -16,6 +22,7 @@ import { bulkUpdateConversations, } from '../../api/conversations/bulk_update_actions_conversations'; import { bulkUpdateAnonymizationFields } from '../../api/anonymization_fields/bulk_update_anonymization_fields'; +import { bulkUpdatePrompts } from '../../api/prompts/bulk_update_prompts'; interface UseSettingsUpdater { assistantStreamingEnabled: boolean; @@ -23,9 +30,9 @@ interface UseSettingsUpdater { conversationsSettingsBulkActions: ConversationsBulkActions; updatedAnonymizationData: FindAnonymizationFieldsResponse; knowledgeBase: KnowledgeBaseConfig; - quickPromptSettings: QuickPrompt[]; + quickPromptSettings: PromptResponse[]; resetSettings: () => void; - systemPromptSettings: Prompt[]; + systemPromptSettings: PromptResponse[]; setUpdatedAnonymizationData: React.Dispatch< React.SetStateAction >; @@ -37,25 +44,24 @@ interface UseSettingsUpdater { setAnonymizationFieldsBulkActions: React.Dispatch< React.SetStateAction >; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; setUpdatedKnowledgeBaseSettings: React.Dispatch>; - setUpdatedQuickPromptSettings: React.Dispatch>; - setUpdatedSystemPromptSettings: React.Dispatch>; + setUpdatedQuickPromptSettings: React.Dispatch>; + setUpdatedSystemPromptSettings: React.Dispatch>; setUpdatedAssistantStreamingEnabled: React.Dispatch>; saveSettings: () => Promise; } export const useSettingsUpdater = ( conversations: Record, - anonymizationFields: FindAnonymizationFieldsResponse + anonymizationFields: FindAnonymizationFieldsResponse, + allSystemPrompts: FindPromptsResponse ): UseSettingsUpdater => { // Initial state from assistant context const { - allQuickPrompts, - allSystemPrompts, assistantTelemetry, knowledgeBase, - setAllQuickPrompts, - setAllSystemPrompts, assistantStreamingEnabled, setAssistantStreamingEnabled, setKnowledgeBase, @@ -72,14 +78,20 @@ export const useSettingsUpdater = ( const [conversationsSettingsBulkActions, setConversationsSettingsBulkActions] = useState({}); // Quick Prompts - const [updatedQuickPromptSettings, setUpdatedQuickPromptSettings] = - useState(allQuickPrompts); + const [updatedQuickPromptSettings, setUpdatedQuickPromptSettings] = useState( + allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.quick) + ); // System Prompts - const [updatedSystemPromptSettings, setUpdatedSystemPromptSettings] = - useState(allSystemPrompts); + const [updatedSystemPromptSettings, setUpdatedSystemPromptSettings] = useState( + allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.system) + ); // Anonymization const [anonymizationFieldsBulkActions, setAnonymizationFieldsBulkActions] = useState({}); + // Prompts + const [promptsBulkActions, setPromptsBulkActions] = useState( + {} + ); const [updatedAnonymizationData, setUpdatedAnonymizationData] = useState(anonymizationFields); const [updatedAssistantStreamingEnabled, setUpdatedAssistantStreamingEnabled] = @@ -94,13 +106,14 @@ export const useSettingsUpdater = ( const resetSettings = useCallback((): void => { setConversationSettings(conversations); setConversationsSettingsBulkActions({}); - setUpdatedQuickPromptSettings(allQuickPrompts); + setUpdatedQuickPromptSettings( + allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.quick) + ); setUpdatedKnowledgeBaseSettings(knowledgeBase); setUpdatedAssistantStreamingEnabled(assistantStreamingEnabled); - setUpdatedSystemPromptSettings(allSystemPrompts); + setUpdatedSystemPromptSettings(allSystemPrompts.data); setUpdatedAnonymizationData(anonymizationFields); }, [ - allQuickPrompts, allSystemPrompts, anonymizationFields, assistantStreamingEnabled, @@ -108,17 +121,22 @@ export const useSettingsUpdater = ( knowledgeBase, ]); + const hasBulkConversations = + conversationsSettingsBulkActions.create || + conversationsSettingsBulkActions.update || + conversationsSettingsBulkActions.delete; + + const hasBulkAnonymizationFields = + anonymizationFieldsBulkActions.create || + anonymizationFieldsBulkActions.update || + anonymizationFieldsBulkActions.delete; + + const hasBulkPrompts = + promptsBulkActions.create || promptsBulkActions.update || promptsBulkActions.delete; /** * Save all pending settings */ const saveSettings = useCallback(async (): Promise => { - setAllQuickPrompts(updatedQuickPromptSettings); - setAllSystemPrompts(updatedSystemPromptSettings); - - const hasBulkConversations = - conversationsSettingsBulkActions.create || - conversationsSettingsBulkActions.update || - conversationsSettingsBulkActions.delete; const bulkResult = hasBulkConversations ? await bulkUpdateConversations(http, conversationsSettingsBulkActions, toasts) : undefined; @@ -144,31 +162,36 @@ export const useSettingsUpdater = ( } setAssistantStreamingEnabled(updatedAssistantStreamingEnabled); setKnowledgeBase(updatedKnowledgeBaseSettings); - const hasBulkAnonymizationFields = - anonymizationFieldsBulkActions.create || - anonymizationFieldsBulkActions.update || - anonymizationFieldsBulkActions.delete; + const bulkAnonymizationFieldsResult = hasBulkAnonymizationFields ? await bulkUpdateAnonymizationFields(http, anonymizationFieldsBulkActions, toasts) : undefined; - return (bulkResult?.success ?? true) && (bulkAnonymizationFieldsResult?.success ?? true); + const bulkPromptsResult = hasBulkPrompts + ? await bulkUpdatePrompts(http, promptsBulkActions, toasts) + : undefined; + + return ( + (bulkResult?.success ?? true) && + (bulkAnonymizationFieldsResult?.success ?? true) && + (bulkPromptsResult?.success ?? true) + ); }, [ - setAllQuickPrompts, - updatedQuickPromptSettings, - setAllSystemPrompts, - updatedSystemPromptSettings, - conversationsSettingsBulkActions, + hasBulkConversations, http, + conversationsSettingsBulkActions, toasts, knowledgeBase.isEnabledKnowledgeBase, knowledgeBase.isEnabledRAGAlerts, - updatedAssistantStreamingEnabled, updatedKnowledgeBaseSettings, assistantStreamingEnabled, + updatedAssistantStreamingEnabled, setAssistantStreamingEnabled, setKnowledgeBase, + hasBulkAnonymizationFields, anonymizationFieldsBulkActions, + hasBulkPrompts, + promptsBulkActions, assistantTelemetry, ]); @@ -207,5 +230,7 @@ export const useSettingsUpdater = ( setUpdatedSystemPromptSettings, setConversationSettings, setConversationsSettingsBulkActions, + promptsBulkActions, + setPromptsBulkActions, }; }; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts index 8b80b87584d35..587be76910c3e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts @@ -5,18 +5,6 @@ * 2.0. */ -export type PromptType = 'system' | 'user'; - -export interface Prompt { - id: string; - content: string; - name: string; - promptType: PromptType; - isDefault?: boolean; // TODO: Should be renamed to isImmutable as this flag is used to prevent users from deleting prompts - isNewConversationDefault?: boolean; - isFlyoutMode?: boolean; -} - export interface KnowledgeBaseConfig { isEnabledRAGAlerts: boolean; isEnabledKnowledgeBase: boolean; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts index de766085e1aee..a2d8fbb3d7019 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts @@ -6,7 +6,7 @@ */ import React from 'react'; -import { Prompt } from '../types'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation } from '../../assistant_context/types'; export interface CodeBlockDetails { @@ -78,9 +78,9 @@ export const getDefaultSystemPrompt = ({ allSystemPrompts, conversation, }: { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; conversation: Conversation | undefined; -}): Prompt | undefined => { +}): PromptResponse | undefined => { const conversationSystemPrompt = allSystemPrompts.find( (prompt) => prompt.id === conversation?.apiConfig?.defaultSystemPromptId ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx index 6a74dab81ac47..3646b73c0612d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx @@ -24,17 +24,13 @@ import type { Conversation } from './types'; import { DEFAULT_ASSISTANT_TITLE } from '../assistant/translations'; import { CodeBlockDetails } from '../assistant/use_conversation/helpers'; import { PromptContextTemplate } from '../assistant/prompt_context/types'; -import { QuickPrompt } from '../assistant/quick_prompts/types'; -import { KnowledgeBaseConfig, Prompt, TraceOptions } from '../assistant/types'; -import { BASE_SYSTEM_PROMPTS } from '../content/prompts/system'; +import { KnowledgeBaseConfig, TraceOptions } from '../assistant/types'; import { DEFAULT_ASSISTANT_NAMESPACE, DEFAULT_KNOWLEDGE_BASE_SETTINGS, KNOWLEDGE_BASE_LOCAL_STORAGE_KEY, LAST_CONVERSATION_ID_LOCAL_STORAGE_KEY, - QUICK_PROMPT_LOCAL_STORAGE_KEY, STREAMING_LOCAL_STORAGE_KEY, - SYSTEM_PROMPT_LOCAL_STORAGE_KEY, TRACE_OPTIONS_SESSION_STORAGE_KEY, } from './constants'; import { CONVERSATIONS_TAB, SettingsTabs } from '../assistant/settings/assistant_settings'; @@ -64,8 +60,6 @@ export interface AssistantProviderProps { ) => CodeBlockDetails[][]; basePath: string; basePromptContexts?: PromptContextTemplate[]; - baseQuickPrompts?: QuickPrompt[]; - baseSystemPrompts?: Prompt[]; docLinks: Omit; children: React.ReactNode; getComments: (commentArgs: { @@ -104,13 +98,8 @@ export interface UseAssistantContext { currentConversation: Conversation, showAnonymizedValues: boolean ) => CodeBlockDetails[][]; - allQuickPrompts: QuickPrompt[]; - allSystemPrompts: Prompt[]; docLinks: Omit; basePath: string; - basePromptContexts: PromptContextTemplate[]; - baseQuickPrompts: QuickPrompt[]; - baseSystemPrompts: Prompt[]; baseConversations: Record; getComments: (commentArgs: { abortStream: () => void; @@ -131,8 +120,6 @@ export interface UseAssistantContext { nameSpace: string; registerPromptContext: RegisterPromptContext; selectedSettingsTab: SettingsTabs; - setAllQuickPrompts: React.Dispatch>; - setAllSystemPrompts: React.Dispatch>; setAssistantStreamingEnabled: React.Dispatch>; setKnowledgeBase: React.Dispatch>; setLastConversationId: React.Dispatch>; @@ -147,6 +134,7 @@ export interface UseAssistantContext { title: string; toasts: IToasts | undefined; traceOptions: TraceOptions; + basePromptContexts: PromptContextTemplate[]; unRegisterPromptContext: UnRegisterPromptContext; } @@ -161,8 +149,6 @@ export const AssistantProvider: React.FC = ({ docLinks, basePath, basePromptContexts = [], - baseQuickPrompts = [], - baseSystemPrompts = BASE_SYSTEM_PROMPTS, children, getComments, http, @@ -185,22 +171,6 @@ export const AssistantProvider: React.FC = ({ defaultTraceOptions ); - /** - * Local storage for all quick prompts, prefixed by assistant nameSpace - */ - const [localStorageQuickPrompts, setLocalStorageQuickPrompts] = useLocalStorage( - `${nameSpace}.${QUICK_PROMPT_LOCAL_STORAGE_KEY}`, - baseQuickPrompts - ); - - /** - * Local storage for all system prompts, prefixed by assistant nameSpace - */ - const [localStorageSystemPrompts, setLocalStorageSystemPrompts] = useLocalStorage( - `${nameSpace}.${SYSTEM_PROMPT_LOCAL_STORAGE_KEY}`, - baseSystemPrompts - ); - const [localStorageLastConversationId, setLocalStorageLastConversationId] = useLocalStorage(`${nameSpace}.${LAST_CONVERSATION_ID_LOCAL_STORAGE_KEY}`); @@ -286,12 +256,8 @@ export const AssistantProvider: React.FC = ({ assistantFeatures: assistantFeatures ?? defaultAssistantFeatures, assistantTelemetry, augmentMessageCodeBlocks, - allQuickPrompts: localStorageQuickPrompts ?? [], - allSystemPrompts: localStorageSystemPrompts ?? [], basePath, basePromptContexts, - baseQuickPrompts, - baseSystemPrompts, docLinks, getComments, http, @@ -303,8 +269,6 @@ export const AssistantProvider: React.FC = ({ // can be undefined from localStorage, if not defined, default to true assistantStreamingEnabled: localStorageStreaming ?? true, setAssistantStreamingEnabled: setLocalStorageStreaming, - setAllQuickPrompts: setLocalStorageQuickPrompts, - setAllSystemPrompts: setLocalStorageSystemPrompts, setKnowledgeBase: setLocalStorageKnowledgeBase, setSelectedSettingsTab, setShowAssistantOverlay, @@ -325,12 +289,8 @@ export const AssistantProvider: React.FC = ({ assistantFeatures, assistantTelemetry, augmentMessageCodeBlocks, - localStorageQuickPrompts, - localStorageSystemPrompts, basePath, basePromptContexts, - baseQuickPrompts, - baseSystemPrompts, docLinks, getComments, http, @@ -341,8 +301,6 @@ export const AssistantProvider: React.FC = ({ selectedSettingsTab, localStorageStreaming, setLocalStorageStreaming, - setLocalStorageQuickPrompts, - setLocalStorageSystemPrompts, setLocalStorageKnowledgeBase, setSessionStorageTraceOptions, showAssistantOverlay, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts b/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts index de23052d15564..9516d95289813 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts @@ -5,17 +5,16 @@ * 2.0. */ -import { Prompt } from '../../assistant/types'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; -export const mockSystemPrompt: Prompt = { +export const mockSystemPrompt: PromptResponse = { id: 'mock-system-prompt-1', content: 'You are a helpful, expert assistant who answers questions about Elastic Security.', name: 'Mock system prompt', promptType: 'system', - isFlyoutMode: false, }; -export const mockSuperheroSystemPrompt: Prompt = { +export const mockSuperheroSystemPrompt: PromptResponse = { id: 'mock-superhero-system-prompt-1', content: `You are a helpful, expert assistant who answers questions about Elastic Security. You have the personality of a mutant superhero who says "bub" a lot.`, @@ -23,7 +22,7 @@ You have the personality of a mutant superhero who says "bub" a lot.`, promptType: 'system', }; -export const defaultSystemPrompt: Prompt = { +export const defaultSystemPrompt: PromptResponse = { id: 'default-system-prompt', content: 'You are a helpful, expert assistant who answers questions about Elastic Security. Do not answer questions unrelated to Elastic Security.\nIf you answer a question related to KQL or EQL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query.\nUse the following context to answer questions:', @@ -33,7 +32,7 @@ export const defaultSystemPrompt: Prompt = { isNewConversationDefault: true, }; -export const mockSystemPrompts: Prompt[] = [ +export const mockSystemPrompts: PromptResponse[] = [ mockSystemPrompt, mockSuperheroSystemPrompt, defaultSystemPrompt, diff --git a/x-pack/packages/kbn-elastic-assistant/index.ts b/x-pack/packages/kbn-elastic-assistant/index.ts index df0ba1e8db0f9..748e0ba33ebd1 100644 --- a/x-pack/packages/kbn-elastic-assistant/index.ts +++ b/x-pack/packages/kbn-elastic-assistant/index.ts @@ -114,9 +114,6 @@ export type { ClientMessage, } from './impl/assistant_context/types'; -/** Interface for defining system/user prompts */ -export type { Prompt } from './impl/assistant/types'; - /** * This interface is used to pass context to the assistant, * for the purpose of building prompts. Examples of context include: diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/field_maps_configuration.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/field_maps_configuration.ts index 50df573d01872..ecf72372194c8 100644 --- a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/field_maps_configuration.ts +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/field_maps_configuration.ts @@ -23,11 +23,21 @@ export const assistantPromptsFieldMap: FieldMap = { array: false, required: false, }, - is_shared: { - type: 'boolean', + consumer: { + type: 'text', + array: false, + required: false, + }, + color: { + type: 'text', array: false, required: false, }, + categories: { + type: 'text', + array: true, + required: false, + }, is_new_conversation_default: { type: 'boolean', array: false, diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts index 84e683121ae75..2ac275363fdbf 100644 --- a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts @@ -9,6 +9,7 @@ import { estypes } from '@elastic/elasticsearch'; import { PromptCreateProps, PromptResponse, + PromptType, PromptUpdateProps, } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { AuthenticatedUser } from '@kbn/security-plugin-types-common'; @@ -31,8 +32,10 @@ export const transformESToPrompts = (response: EsPromptsSchema[]): PromptRespons namespace: promptSchema.namespace, id: promptSchema.id, name: promptSchema.name, - promptType: promptSchema.prompt_type, - isShared: promptSchema.is_shared, + promptType: promptSchema.prompt_type as unknown as PromptType, + color: promptSchema.color, + categories: promptSchema.categories, + consumer: promptSchema.consumer, createdBy: promptSchema.created_by, updatedBy: promptSchema.updated_by, }; @@ -64,8 +67,10 @@ export const transformESSearchToPrompts = ( namespace: promptSchema.namespace, id: hit._id, name: promptSchema.name, - promptType: promptSchema.prompt_type, - isShared: promptSchema.is_shared, + promptType: promptSchema.prompt_type as unknown as PromptType, + color: promptSchema.color, + categories: promptSchema.categories, + consumer: promptSchema.consumer, createdBy: promptSchema.created_by, updatedBy: promptSchema.updated_by, }; @@ -77,14 +82,15 @@ export const transformESSearchToPrompts = ( export const transformToUpdateScheme = ( user: AuthenticatedUser, updatedAt: string, - { content, isNewConversationDefault, isShared, id }: PromptUpdateProps + { content, isNewConversationDefault, categories, color, id }: PromptUpdateProps ): UpdatePromptSchema => { return { id, updated_at: updatedAt, content: content ?? '', is_new_conversation_default: isNewConversationDefault, - is_shared: isShared, + categories, + color, users: [ { id: user.profile_uid, @@ -97,13 +103,25 @@ export const transformToUpdateScheme = ( export const transformToCreateScheme = ( user: AuthenticatedUser, updatedAt: string, - { content, isDefault, isNewConversationDefault, isShared, name, promptType }: PromptCreateProps + { + content, + isDefault, + isNewConversationDefault, + categories, + color, + consumer, + name, + promptType, + }: PromptCreateProps ): CreatePromptSchema => { return { + '@timestamp': updatedAt, updated_at: updatedAt, content: content ?? '', is_new_conversation_default: isNewConversationDefault, - is_shared: isShared, + color, + consumer, + categories, name, is_default: isDefault, prompt_type: promptType, diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/types.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/types.ts index 91f52fb3a0829..0d936cc852aca 100644 --- a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/types.ts +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/types.ts @@ -12,7 +12,9 @@ export interface EsPromptsSchema { created_by: string; content: string; is_default?: boolean; - is_shared?: boolean; + consumer?: string; + color?: string; + categories?: string[]; is_new_conversation_default?: boolean; name: string; prompt_type: string; @@ -28,7 +30,8 @@ export interface EsPromptsSchema { export interface UpdatePromptSchema { id: string; '@timestamp'?: string; - is_shared?: boolean; + color?: string; + categories?: string[]; is_new_conversation_default?: boolean; content?: string; updated_at?: string; @@ -42,7 +45,9 @@ export interface UpdatePromptSchema { export interface CreatePromptSchema { '@timestamp'?: string; - is_shared?: boolean; + consumer?: string; + color?: string; + categories?: string[]; is_new_conversation_default?: boolean; is_default?: boolean; name: string; diff --git a/x-pack/plugins/elastic_assistant/server/routes/prompts/find_route.ts b/x-pack/plugins/elastic_assistant/server/routes/prompts/find_route.ts index df2ec323bc356..8838db3c44943 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/prompts/find_route.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/prompts/find_route.ts @@ -59,7 +59,7 @@ export const findPromptsRoute = (router: ElasticAssistantPluginRouter, logger: L page: query.page, sortField: query.sort_field, sortOrder: query.sort_order, - filter: query.filter, + filter: query.filter ? decodeURIComponent(query.filter) : undefined, fields: query.fields, }); diff --git a/x-pack/plugins/security_solution/public/assistant/provider.tsx b/x-pack/plugins/security_solution/public/assistant/provider.tsx index 8516ec455aac0..f63de698f3865 100644 --- a/x-pack/plugins/security_solution/public/assistant/provider.tsx +++ b/x-pack/plugins/security_solution/public/assistant/provider.tsx @@ -28,8 +28,6 @@ import { getComments } from './get_comments'; import { LOCAL_STORAGE_KEY, augmentMessageCodeBlocks } from './helpers'; import { useBaseConversations } from './use_conversation_store'; import { PROMPT_CONTEXTS } from './content/prompt_contexts'; -import { BASE_SECURITY_QUICK_PROMPTS } from './content/quick_prompts'; -import { BASE_SECURITY_SYSTEM_PROMPTS } from './content/prompts/system'; import { useAssistantAvailability } from './use_assistant_availability'; import { useAppToasts } from '../common/hooks/use_app_toasts'; import { useSignalIndex } from '../detections/containers/detection_engine/alerts/use_signal_index'; @@ -165,8 +163,6 @@ export const AssistantProvider: FC> = ({ children }) docLinks={{ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }} basePath={basePath} basePromptContexts={Object.values(PROMPT_CONTEXTS)} - baseQuickPrompts={BASE_SECURITY_QUICK_PROMPTS} // to server and plugin start - baseSystemPrompts={BASE_SECURITY_SYSTEM_PROMPTS} // to server and plugin start baseConversations={baseConversations} getComments={getComments} http={http} From 5019292e1a5514aa9d61eee3b9aa0a8a9b874422 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 10:24:28 -0700 Subject: [PATCH 02/22] fixed merge --- .../conversation_settings.tsx | 28 -- .../system_prompt/index.test.tsx | 13 +- .../system_prompt_editor.tsx | 94 ++++- .../system_prompt_selector.tsx | 7 - .../system_prompt_settings.tsx | 349 +----------------- .../system_prompt_modal/types.ts | 3 + .../use_system_prompt_editor.tsx | 42 ++- .../index.tsx | 16 +- .../use_system_prompt_table.test.tsx | 8 +- .../use_system_prompt_table.tsx | 8 +- .../quick_prompt_selector.tsx | 6 - .../quick_prompt_editor.tsx | 26 +- .../quick_prompt_settings.tsx | 154 +------- .../use_quick_prompt_editor.tsx | 23 +- .../assistant/settings/assistant_settings.tsx | 17 +- .../assistant_settings_management.tsx | 19 +- .../use_settings_updater.test.tsx | 27 +- .../use_settings_updater.tsx | 10 +- .../impl/assistant/types.ts | 16 - .../impl/assistant_context/index.tsx | 6 - 20 files changed, 186 insertions(+), 686 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx index 410756ff7c4cc..4aef092580ab9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx @@ -34,12 +34,8 @@ import { getConversationApiConfig } from '../../use_conversation/helpers'; export interface ConversationSettingsProps { actionTypeRegistry: ActionTypeRegistryContract; -<<<<<<< HEAD allSystemPrompts: PromptResponse[]; -======= - allSystemPrompts: Prompt[]; connectors?: AIConnector[]; ->>>>>>> upstream/main conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; defaultConnector?: AIConnector; @@ -125,29 +121,6 @@ export const ConversationSettings: React.FC = React.m onConversationSelectionChange={onConversationSelectionChange} /> -<<<<<<< HEAD - - - -======= = React.m setConversationSettings={setConversationSettings} setConversationsSettingsBulkActions={setConversationsSettingsBulkActions} /> ->>>>>>> upstream/main diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx index e0fed34795dfc..5cb99e6ec6155 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx @@ -13,11 +13,11 @@ import { mockSystemPrompt } from '../../../mock/system_prompt'; import { SystemPrompt } from '.'; import { Conversation } from '../../../..'; import { DEFAULT_CONVERSATION_TITLE } from '../../use_conversation/translations'; -import { Prompt } from '../../types'; import { TestProviders } from '../../../mock/test_providers/test_providers'; import { TEST_IDS } from '../../constants'; import { useAssistantContext } from '../../../assistant_context'; import { WELCOME_CONVERSATION } from '../../use_conversation/sample_conversations'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; const BASE_CONVERSATION: Conversation = { ...WELCOME_CONVERSATION, @@ -32,7 +32,7 @@ const mockConversations = { [DEFAULT_CONVERSATION_TITLE]: BASE_CONVERSATION, }; -const mockSystemPrompts: Prompt[] = [mockSystemPrompt]; +const mockSystemPrompts: PromptResponse[] = [mockSystemPrompt]; const mockUseAssistantContext = { conversations: mockConversations, @@ -91,6 +91,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); }); @@ -122,6 +123,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); }); @@ -157,6 +159,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); @@ -204,6 +207,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); @@ -265,6 +269,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); @@ -333,6 +338,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); @@ -416,6 +422,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); @@ -486,6 +493,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); @@ -505,6 +513,7 @@ describe('SystemPrompt', () => { onSystemPromptSelectionChange={onSystemPromptSelectionChange} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode={false} + allSystemPrompts={mockSystemPrompts} /> ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_editor.tsx index 3fd7dfeb00e73..fecb2ed401a4b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_editor.tsx @@ -18,9 +18,13 @@ import { import { keyBy } from 'lodash/fp'; import { css } from '@emotion/react'; +import { + PromptResponse, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { ApiConfig } from '@kbn/elastic-assistant-common'; import { AIConnector } from '../../../../connectorland/connector_selector'; -import { Conversation, Prompt } from '../../../../..'; +import { Conversation } from '../../../../..'; import * as i18n from './translations'; import { ConversationMultiSelector } from './conversation_multi_selector/conversation_multi_selector'; import { SystemPromptSelector } from './system_prompt_selector/system_prompt_selector'; @@ -34,16 +38,18 @@ interface Props { connectors: AIConnector[] | undefined; conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; - onSelectedSystemPromptChange: (systemPrompt?: Prompt) => void; - selectedSystemPrompt: Prompt | undefined; - setUpdatedSystemPromptSettings: React.Dispatch>; + onSelectedSystemPromptChange: (systemPrompt?: PromptResponse) => void; + selectedSystemPrompt: PromptResponse | undefined; + setUpdatedSystemPromptSettings: React.Dispatch>; setConversationSettings: React.Dispatch>>; - systemPromptSettings: Prompt[]; + systemPromptSettings: PromptResponse[]; setConversationsSettingsBulkActions: React.Dispatch< React.SetStateAction >; defaultConnector?: AIConnector; resetSettings?: () => void; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; } /** @@ -61,6 +67,8 @@ export const SystemPromptEditorComponent: React.FC = ({ setConversationsSettingsBulkActions, defaultConnector, resetSettings, + promptsBulkActions, + setPromptsBulkActions, }) => { // Prompt const promptContent = useMemo( @@ -72,11 +80,11 @@ export const SystemPromptEditorComponent: React.FC = ({ const handlePromptContentChange = useCallback( (e: React.ChangeEvent) => { if (selectedSystemPrompt != null) { - setUpdatedSystemPromptSettings((prev): Prompt[] => { + setUpdatedSystemPromptSettings((prev): PromptResponse[] => { const alreadyExists = prev.some((sp) => sp.id === selectedSystemPrompt.id); if (alreadyExists) { - return prev.map((sp): Prompt => { + return prev.map((sp): PromptResponse => { if (sp.id === selectedSystemPrompt.id) { return { ...sp, @@ -89,9 +97,44 @@ export const SystemPromptEditorComponent: React.FC = ({ return prev; }); + const existingPrompt = systemPromptSettings.find((sp) => sp.id === selectedSystemPrompt.id); + if (existingPrompt) { + setPromptsBulkActions({ + ...promptsBulkActions, + ...(selectedSystemPrompt.name !== selectedSystemPrompt.id + ? { + update: [ + ...(promptsBulkActions.update ?? []).filter( + (p) => p.id !== selectedSystemPrompt.id + ), + { + ...selectedSystemPrompt, + content: e.target.value, + }, + ], + } + : { + create: [ + ...(promptsBulkActions.create ?? []).filter( + (p) => p.name !== selectedSystemPrompt.name + ), + { + ...selectedSystemPrompt, + content: e.target.value, + }, + ], + }), + }); + } } }, - [selectedSystemPrompt, setUpdatedSystemPromptSettings] + [ + promptsBulkActions, + selectedSystemPrompt, + setPromptsBulkActions, + setUpdatedSystemPromptSettings, + systemPromptSettings, + ] ); const conversationsWithApiConfig = Object.entries(conversationSettings).reduce< @@ -258,14 +301,47 @@ export const SystemPromptEditorComponent: React.FC = ({ }; }); }); + setPromptsBulkActions({ + ...promptsBulkActions, + ...(selectedSystemPrompt.name !== selectedSystemPrompt.id + ? { + update: [ + ...(promptsBulkActions.update ?? []).filter( + (p) => p.id !== selectedSystemPrompt.id + ), + { + ...selectedSystemPrompt, + isNewConversationDefault: isChecked, + }, + ], + } + : { + create: [ + ...(promptsBulkActions.create ?? []).filter( + (p) => p.name !== selectedSystemPrompt.name + ), + { + ...selectedSystemPrompt, + isNewConversationDefault: isChecked, + }, + ], + }), + }); } }, - [selectedSystemPrompt, setUpdatedSystemPromptSettings] + [ + promptsBulkActions, + selectedSystemPrompt, + setPromptsBulkActions, + setUpdatedSystemPromptSettings, + ] ); const { onSystemPromptSelectionChange, onSystemPromptDeleted } = useSystemPromptEditor({ setUpdatedSystemPromptSettings, onSelectedSystemPromptChange, + promptsBulkActions, + setPromptsBulkActions, }); return ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx index 846deea21e32d..4c67a475484c4 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx @@ -28,17 +28,10 @@ export const SYSTEM_PROMPT_SELECTOR_CLASSNAME = 'systemPromptSelector'; interface Props { autoFocus?: boolean; onSystemPromptDeleted: (systemPromptTitle: string) => void; -<<<<<<< HEAD onSystemPromptSelectionChange: (systemPrompt?: PromptResponse | string) => void; systemPrompts: PromptResponse[]; - autoFocus?: boolean; selectedSystemPrompt?: PromptResponse; -======= - onSystemPromptSelectionChange: (systemPrompt?: Prompt | string) => void; resetSettings?: () => void; - selectedSystemPrompt?: Prompt; - systemPrompts: Prompt[]; ->>>>>>> upstream/main } export type SystemPromptSelectorOption = EuiComboBoxOptionOption<{ diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx index bc95da0addf99..7b8e451449884 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.tsx @@ -8,43 +8,9 @@ import React from 'react'; import { EuiTitle, EuiText, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -<<<<<<< HEAD -import { keyBy } from 'lodash/fp'; - -import { css } from '@emotion/react'; -import { ApiConfig } from '@kbn/elastic-assistant-common'; -import { - PerformBulkActionRequestBody, - PromptResponse, -} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; -import { AIConnector } from '../../../../connectorland/connector_selector'; -import { Conversation } from '../../../../..'; -import * as i18n from './translations'; -import { ConversationMultiSelector } from './conversation_multi_selector/conversation_multi_selector'; -import { SystemPromptSelector } from './system_prompt_selector/system_prompt_selector'; -import { TEST_IDS } from '../../../constants'; -import { ConversationsBulkActions } from '../../../api'; - -interface Props { - conversationSettings: Record; - conversationsSettingsBulkActions: ConversationsBulkActions; - onSelectedSystemPromptChange: (systemPrompt?: PromptResponse) => void; - selectedSystemPrompt: PromptResponse | undefined; - setPromptsBulkActions: React.Dispatch>; - setUpdatedSystemPromptSettings: React.Dispatch>; - setConversationSettings: React.Dispatch>>; - systemPromptSettings: PromptResponse[]; - setConversationsSettingsBulkActions: React.Dispatch< - React.SetStateAction - >; - promptsBulkActions: PerformBulkActionRequestBody; - defaultConnector?: AIConnector; -} -======= import * as i18n from './translations'; import { SystemPromptEditor } from './system_prompt_editor'; import { SystemPromptSettingsProps } from './types'; ->>>>>>> upstream/main /** * Settings for adding/removing system prompts. Configure name, prompt and default conversations. @@ -64,319 +30,6 @@ export const SystemPromptSettings: React.FC = React.m defaultConnector, setPromptsBulkActions, }) => { -<<<<<<< HEAD - // Prompt - const promptContent = useMemo( - () => selectedSystemPrompt?.content ?? '', - [selectedSystemPrompt?.content] - ); - - const handlePromptContentChange = useCallback( - (e: React.ChangeEvent) => { - if (selectedSystemPrompt != null) { - setUpdatedSystemPromptSettings((prev): PromptResponse[] => { - const alreadyExists = prev.some((sp) => sp.id === selectedSystemPrompt.id); - - if (alreadyExists) { - return prev.map((sp): PromptResponse => { - if (sp.id === selectedSystemPrompt.id) { - return { - ...sp, - content: e.target.value, - }; - } - return sp; - }); - } - - return prev; - }); - - const existingPrompt = systemPromptSettings.find( - (sp) => sp.id === selectedSystemPrompt.id - ); - if (existingPrompt) { - setPromptsBulkActions({ - ...promptsBulkActions, - ...(selectedSystemPrompt.name !== selectedSystemPrompt.id - ? { - update: [ - ...(promptsBulkActions.update ?? []).filter( - (p) => p.id !== selectedSystemPrompt.id - ), - { - ...selectedSystemPrompt, - content: e.target.value, - }, - ], - } - : { - create: [ - ...(promptsBulkActions.create ?? []).filter( - (p) => p.name !== selectedSystemPrompt.name - ), - { - ...selectedSystemPrompt, - content: e.target.value, - }, - ], - }), - }); - } - } - }, - [ - promptsBulkActions, - selectedSystemPrompt, - setPromptsBulkActions, - setUpdatedSystemPromptSettings, - systemPromptSettings, - ] - ); - - // Conversations this system prompt should be a default for - const conversationOptions = useMemo( - () => Object.values(conversationSettings), - [conversationSettings] - ); - const selectedConversations = useMemo(() => { - return selectedSystemPrompt != null - ? Object.values(conversationSettings).filter( - (conversation) => - conversation.apiConfig?.defaultSystemPromptId === selectedSystemPrompt.id - ) - : []; - }, [conversationSettings, selectedSystemPrompt]); - - const handleConversationSelectionChange = useCallback( - (currentPromptConversations: Conversation[]) => { - const currentPromptConversationTitles = currentPromptConversations.map( - (convo) => convo.title - ); - const getDefaultSystemPromptId = (convo: Conversation) => - currentPromptConversationTitles.includes(convo.title) - ? selectedSystemPrompt?.id - : convo.apiConfig && convo.apiConfig.defaultSystemPromptId === selectedSystemPrompt?.id - ? // remove the default System Prompt if it is assigned to a conversation - // but that conversation is not in the currentPromptConversationList - // This means conversation was removed in the current transaction - undefined - : // leave it as it is .. if that conversation was neither added nor removed. - convo.apiConfig?.defaultSystemPromptId; - - if (selectedSystemPrompt != null) { - setConversationSettings((prev) => - keyBy( - 'title', - /* - * updatedConversationWithPrompts calculates the present of prompt for - * each conversation. Based on the values of selected conversation, it goes - * through each conversation adds/removed the selected prompt on each conversation. - * - * */ - Object.values(prev).map((convo) => ({ - ...convo, - ...(convo.apiConfig - ? { - apiConfig: { - ...convo.apiConfig, - defaultSystemPromptId: getDefaultSystemPromptId(convo), - }, - } - : { - apiConfig: { - defaultSystemPromptId: getDefaultSystemPromptId(convo), - connectorId: defaultConnector?.id ?? '', - actionTypeId: defaultConnector?.actionTypeId ?? '', - }, - }), - })) - ) - ); - - let updatedConversationsSettingsBulkActions = { ...conversationsSettingsBulkActions }; - Object.values(conversationSettings).forEach((convo) => { - const getApiConfig = (): ApiConfig | {} => { - if (convo.apiConfig) { - return { - apiConfig: { - ...convo.apiConfig, - defaultSystemPromptId: getDefaultSystemPromptId(convo), - }, - }; - } - return {}; - }; - const createOperation = - convo.id === '' - ? { - create: { - ...(updatedConversationsSettingsBulkActions.create ?? {}), - [convo.id]: { - ...convo, - ...(convo.apiConfig - ? { - apiConfig: { - ...convo.apiConfig, - defaultSystemPromptId: getDefaultSystemPromptId(convo), - }, - } - : {}), - }, - }, - } - : {}; - - const updateOperation = - convo.id !== '' - ? { - update: { - ...(updatedConversationsSettingsBulkActions.update ?? {}), - [convo.id]: { - ...(updatedConversationsSettingsBulkActions.update - ? updatedConversationsSettingsBulkActions.update[convo.id] ?? {} - : {}), - ...getApiConfig(), - }, - }, - } - : {}; - - updatedConversationsSettingsBulkActions = { - ...updatedConversationsSettingsBulkActions, - ...createOperation, - ...updateOperation, - }; - }); - setConversationsSettingsBulkActions(updatedConversationsSettingsBulkActions); - } - }, - [ - conversationSettings, - conversationsSettingsBulkActions, - defaultConnector?.actionTypeId, - defaultConnector?.id, - selectedSystemPrompt, - setConversationSettings, - setConversationsSettingsBulkActions, - ] - ); - - // Whether this system prompt should be the default for new conversations - const isNewConversationDefault = useMemo( - () => selectedSystemPrompt?.isNewConversationDefault ?? false, - [selectedSystemPrompt?.isNewConversationDefault] - ); - - const handleNewConversationDefaultChange = useCallback( - (e) => { - const isChecked = e.target.checked; - - if (selectedSystemPrompt != null) { - setUpdatedSystemPromptSettings((prev) => { - return prev.map((pp) => { - return { - ...pp, - isNewConversationDefault: selectedSystemPrompt.id === pp.id && isChecked, - }; - }); - }); - setPromptsBulkActions({ - ...promptsBulkActions, - ...(selectedSystemPrompt.name !== selectedSystemPrompt.id - ? { - update: [ - ...(promptsBulkActions.update ?? []).filter( - (p) => p.id !== selectedSystemPrompt.id - ), - { - ...selectedSystemPrompt, - isNewConversationDefault: isChecked, - }, - ], - } - : { - create: [ - ...(promptsBulkActions.create ?? []).filter( - (p) => p.name !== selectedSystemPrompt.name - ), - { - ...selectedSystemPrompt, - isNewConversationDefault: isChecked, - }, - ], - }), - }); - } - }, - [ - promptsBulkActions, - selectedSystemPrompt, - setUpdatedSystemPromptSettings, - setPromptsBulkActions, - ] - ); - - // When top level system prompt selection changes - const onSystemPromptSelectionChange = useCallback( - (systemPrompt?: PromptResponse | string) => { - const isNew = typeof systemPrompt === 'string'; - const newSelectedSystemPrompt: PromptResponse | undefined = isNew - ? { - id: systemPrompt, - content: '', - name: systemPrompt ?? '', - promptType: 'system', - consumer: 'security', - } - : systemPrompt; - - if (newSelectedSystemPrompt != null) { - setUpdatedSystemPromptSettings((prev) => { - const alreadyExists = prev.some((sp) => sp.id === newSelectedSystemPrompt.id); - - if (!alreadyExists) { - return [...prev, newSelectedSystemPrompt]; - } - - return prev; - }); - setPromptsBulkActions({ - ...promptsBulkActions, - create: [ - ...(promptsBulkActions.create ?? []), - { - ...newSelectedSystemPrompt, - }, - ], - }); - } - - onSelectedSystemPromptChange(newSelectedSystemPrompt); - }, - [ - onSelectedSystemPromptChange, - promptsBulkActions, - setPromptsBulkActions, - setUpdatedSystemPromptSettings, - ] - ); - - const onSystemPromptDeleted = useCallback( - (id: string) => { - setUpdatedSystemPromptSettings((prev) => prev.filter((sp) => sp.id !== id)); - setPromptsBulkActions({ - ...promptsBulkActions, - delete: { - ids: [...(promptsBulkActions.delete?.ids ?? []), id], - }, - }); - }, - [promptsBulkActions, setPromptsBulkActions, setUpdatedSystemPromptSettings] - ); - -======= ->>>>>>> upstream/main return ( <> @@ -397,6 +50,8 @@ export const SystemPromptSettings: React.FC = React.m conversationsSettingsBulkActions={conversationsSettingsBulkActions} setConversationsSettingsBulkActions={setConversationsSettingsBulkActions} defaultConnector={defaultConnector} + setPromptsBulkActions={setPromptsBulkActions} + promptsBulkActions={promptsBulkActions} /> ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts index 63025566c9400..a311b99e2b7a0 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { AIConnector } from '../../../../connectorland/connector_selector'; import { Conversation, Prompt } from '../../../../..'; import { ConversationsBulkActions } from '../../../api'; @@ -21,4 +22,6 @@ export interface SystemPromptSettingsProps { React.SetStateAction >; defaultConnector?: AIConnector; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; } diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.tsx index 87e284d6dcf25..142abf4dadf15 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.tsx @@ -5,23 +5,30 @@ * 2.0. */ +import { + PromptResponse, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { useCallback } from 'react'; -import { Prompt } from '../../../types'; interface Props { - setUpdatedSystemPromptSettings: React.Dispatch>; - onSelectedSystemPromptChange: (systemPrompt?: Prompt) => void; + setUpdatedSystemPromptSettings: React.Dispatch>; + onSelectedSystemPromptChange: (systemPrompt?: PromptResponse) => void; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; } export const useSystemPromptEditor = ({ setUpdatedSystemPromptSettings, onSelectedSystemPromptChange, + promptsBulkActions, + setPromptsBulkActions, }: Props) => { // When top level system prompt selection changes const onSystemPromptSelectionChange = useCallback( - (systemPrompt?: Prompt | string) => { + (systemPrompt?: PromptResponse | string) => { const isNew = typeof systemPrompt === 'string'; - const newSelectedSystemPrompt: Prompt | undefined = isNew + const newSelectedSystemPrompt: PromptResponse | undefined = isNew ? { id: systemPrompt ?? '', content: '', @@ -40,18 +47,39 @@ export const useSystemPromptEditor = ({ return prev; }); + + setPromptsBulkActions({ + ...promptsBulkActions, + create: [ + ...(promptsBulkActions.create ?? []), + { + ...newSelectedSystemPrompt, + }, + ], + }); } onSelectedSystemPromptChange(newSelectedSystemPrompt); }, - [onSelectedSystemPromptChange, setUpdatedSystemPromptSettings] + [ + onSelectedSystemPromptChange, + promptsBulkActions, + setPromptsBulkActions, + setUpdatedSystemPromptSettings, + ] ); const onSystemPromptDeleted = useCallback( (id: string) => { setUpdatedSystemPromptSettings((prev) => prev.filter((sp) => sp.id !== id)); + setPromptsBulkActions({ + ...promptsBulkActions, + delete: { + ids: [...(promptsBulkActions.delete?.ids ?? []), id], + }, + }); }, - [setUpdatedSystemPromptSettings] + [promptsBulkActions, setPromptsBulkActions, setUpdatedSystemPromptSettings] ); return { onSystemPromptSelectionChange, onSystemPromptDeleted }; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx index e0f27f3fa8c7d..8f21c11cf2f87 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx @@ -16,6 +16,7 @@ import { } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation, ConversationsBulkActions, useAssistantContext } from '../../../../..'; import { SYSTEM_PROMPT_TABLE_SESSION_STORAGE_KEY } from '../../../../assistant_context/constants'; import { AIConnector } from '../../../../connectorland/connector_selector'; @@ -26,7 +27,6 @@ import { useSessionPagination, } from '../../../common/components/assistant_settings_management/pagination/use_session_pagination'; import { CANCEL, DELETE } from '../../../settings/translations'; -import { Prompt } from '../../../types'; import { SystemPromptEditor } from '../system_prompt_modal/system_prompt_editor'; import { SETTINGS_TITLE } from '../system_prompt_modal/translations'; import { useSystemPromptEditor } from '../system_prompt_modal/use_system_prompt_editor'; @@ -37,11 +37,11 @@ interface Props { connectors: AIConnector[] | undefined; conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; - onSelectedSystemPromptChange: (systemPrompt?: Prompt) => void; - selectedSystemPrompt: Prompt | undefined; - setUpdatedSystemPromptSettings: React.Dispatch>; + onSelectedSystemPromptChange: (systemPrompt?: PromptResponse) => void; + selectedSystemPrompt: PromptResponse | undefined; + setUpdatedSystemPromptSettings: React.Dispatch>; setConversationSettings: React.Dispatch>>; - systemPromptSettings: Prompt[]; + systemPromptSettings: PromptResponse[]; setConversationsSettingsBulkActions: React.Dispatch< React.SetStateAction >; @@ -73,7 +73,7 @@ const SystemPromptSettingsManagementComponent = ({ openFlyout: openConfirmModal, closeFlyout: closeConfirmModal, } = useFlyoutModalVisibility(); - const [deletedPrompt, setDeletedPrompt] = useState(); + const [deletedPrompt, setDeletedPrompt] = useState(); const onCreate = useCallback(() => { onSelectedSystemPromptChange({ @@ -91,7 +91,7 @@ const SystemPromptSettingsManagementComponent = ({ }); const onEditActionClicked = useCallback( - (prompt: Prompt) => { + (prompt: PromptResponse) => { onSystemPromptSelectionChange(prompt); openFlyout(); }, @@ -99,7 +99,7 @@ const SystemPromptSettingsManagementComponent = ({ ); const onDeleteActionClicked = useCallback( - (prompt: Prompt) => { + (prompt: PromptResponse) => { setDeletedPrompt(prompt); onSystemPromptDeleted(prompt.id); openConfirmModal(); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx index 90cea2319714d..60bc81cbe976b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx @@ -7,26 +7,26 @@ import { renderHook } from '@testing-library/react-hooks'; import { useSystemPromptTable } from './use_system_prompt_table'; -import { Prompt } from '../../../types'; import { Conversation } from '../../../../assistant_context/types'; import { AIConnector } from '../../../../connectorland/connector_selector'; import { customConvo, welcomeConvo } from '../../../../mock/conversation'; import { mockConnectors } from '../../../../mock/connectors'; import { ApiConfig } from '@kbn/elastic-assistant-common'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; // Mock data for tests -const mockSystemPrompts: Prompt[] = [ +const mockSystemPrompts: PromptResponse[] = [ { id: 'prompt-1', content: 'Prompt 1', name: 'Prompt 1', - promptType: 'user', + promptType: 'quick', }, { id: 'prompt-2', content: 'Prompt 2', name: 'Prompt 2', - promptType: 'user', + promptType: 'quick', isNewConversationDefault: true, }, ]; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx index 7cf907bb7adf5..05ad2360a9412 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx @@ -6,11 +6,11 @@ */ import { EuiBasicTableColumn, EuiIcon, EuiLink } from '@elastic/eui'; import React, { useCallback } from 'react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation } from '../../../../assistant_context/types'; import { AIConnector } from '../../../../connectorland/connector_selector'; import { BadgesColumn } from '../../../common/components/assistant_settings_management/badges'; import { RowActions } from '../../../common/components/assistant_settings_management/row_actions'; -import { Prompt } from '../../../types'; import { getConversationApiConfig, getInitialDefaultSystemPrompt, @@ -21,10 +21,10 @@ import { getSelectedConversations } from './utils'; type ConversationsWithSystemPrompt = Record< string, - Conversation & { systemPrompt: Prompt | undefined } + Conversation & { systemPrompt: PromptResponse | undefined } >; -type SystemPromptTableItem = Prompt & { defaultConversations: string[] }; +type SystemPromptTableItem = PromptResponse & { defaultConversations: string[] }; export const useSystemPromptTable = () => { const getColumns = useCallback( @@ -97,7 +97,7 @@ export const useSystemPromptTable = () => { connectors: AIConnector[] | undefined; conversationSettings: Record; defaultConnector: AIConnector | undefined; - systemPromptSettings: Prompt[]; + systemPromptSettings: PromptResponse[]; }): SystemPromptTableItem[] => { const conversationsWithApiConfig = Object.entries( conversationSettings diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx index 19bd8c43ba661..38d14e2cae8ba 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx @@ -24,16 +24,10 @@ import * as i18n from './translations'; interface Props { isDisabled?: boolean; onQuickPromptDeleted: (quickPromptTitle: string) => void; -<<<<<<< HEAD onQuickPromptSelectionChange: (quickPrompt?: PromptResponse | string) => void; quickPrompts: PromptResponse[]; selectedQuickPrompt?: PromptResponse; -======= - onQuickPromptSelectionChange: (quickPrompt?: QuickPrompt | string) => void; - quickPrompts: QuickPrompt[]; resetSettings?: () => void; - selectedQuickPrompt?: QuickPrompt; ->>>>>>> upstream/main } export type QuickPromptSelectorOption = EuiComboBoxOptionOption<{ isDefault: boolean }>; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx index 4300e53525b33..1a5baf8685304 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx @@ -10,9 +10,9 @@ import { EuiFormRow, EuiColorPicker, EuiTextArea } from '@elastic/eui'; import { EuiSetColorMethod } from '@elastic/eui/src/services/color_picker/color_picker'; import { css } from '@emotion/react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { PromptContextTemplate } from '../../../..'; import * as i18n from './translations'; -import { QuickPrompt } from '../types'; import { QuickPromptSelector } from '../quick_prompt_selector/quick_prompt_selector'; import { PromptContextSelector } from '../prompt_context_selector/prompt_context_selector'; import { useAssistantContext } from '../../../assistant_context'; @@ -21,11 +21,11 @@ import { useQuickPromptEditor } from './use_quick_prompt_editor'; const DEFAULT_COLOR = '#D36086'; interface Props { - onSelectedQuickPromptChange: (quickPrompt?: QuickPrompt) => void; - quickPromptSettings: QuickPrompt[]; + onSelectedQuickPromptChange: (quickPrompt?: PromptResponse) => void; + quickPromptSettings: PromptResponse[]; resetSettings?: () => void; - selectedQuickPrompt: QuickPrompt | undefined; - setUpdatedQuickPromptSettings: React.Dispatch>; + selectedQuickPrompt: PromptResponse | undefined; + setUpdatedQuickPromptSettings: React.Dispatch>; } const QuickPromptSettingsEditorComponent = ({ @@ -40,19 +40,19 @@ const QuickPromptSettingsEditorComponent = ({ // Prompt const prompt = useMemo( // Fixing Cursor Jump in text area - () => quickPromptSettings.find((p) => p.title === selectedQuickPrompt?.title)?.prompt ?? '', - [selectedQuickPrompt?.title, quickPromptSettings] + () => quickPromptSettings.find((p) => p.name === selectedQuickPrompt?.name)?.content ?? '', + [selectedQuickPrompt?.name, quickPromptSettings] ); const handlePromptChange = useCallback( (e: React.ChangeEvent) => { if (selectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === selectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); if (alreadyExists) { return prev.map((qp) => { - if (qp.title === selectedQuickPrompt.title) { + if (qp.name === selectedQuickPrompt.name) { return { ...qp, prompt: e.target.value, @@ -79,11 +79,11 @@ const QuickPromptSettingsEditorComponent = ({ (color, { hex, isValid }) => { if (selectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === selectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); if (alreadyExists) { return prev.map((qp) => { - if (qp.title === selectedQuickPrompt.title) { + if (qp.name === selectedQuickPrompt.name) { return { ...qp, color, @@ -112,11 +112,11 @@ const QuickPromptSettingsEditorComponent = ({ (pc: PromptContextTemplate[]) => { if (selectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === selectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); if (alreadyExists) { return prev.map((qp) => { - if (qp.title === selectedQuickPrompt.title) { + if (qp.name === selectedQuickPrompt.name) { return { ...qp, categories: pc.map((p) => p.category), diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx index 61768df840ed8..bbb15268ad7d2 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx @@ -8,24 +8,9 @@ import React from 'react'; import { EuiTitle, EuiText, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -<<<<<<< HEAD -import { EuiSetColorMethod } from '@elastic/eui/src/services/color_picker/color_picker'; -import { css } from '@emotion/react'; -import { - PromptResponse, - PromptTypeEnum, -} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; -import { PromptContextTemplate, useAssistantContext } from '../../../..'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import * as i18n from './translations'; -import { QuickPromptSelector } from '../quick_prompt_selector/quick_prompt_selector'; -import { PromptContextSelector } from '../prompt_context_selector/prompt_context_selector'; - -const DEFAULT_COLOR = '#D36086'; -======= -import * as i18n from './translations'; -import { QuickPrompt } from '../types'; import { QuickPromptSettingsEditor } from './quick_prompt_editor'; ->>>>>>> upstream/main interface Props { onSelectedQuickPromptChange: (quickPrompt?: PromptResponse) => void; @@ -44,143 +29,6 @@ export const QuickPromptSettings: React.FC = React.memo( selectedQuickPrompt, setUpdatedQuickPromptSettings, }) => { -<<<<<<< HEAD - const { basePromptContexts } = useAssistantContext(); - // Prompt - const prompt = useMemo( - () => selectedQuickPrompt?.content ?? '', - [selectedQuickPrompt?.content] - ); - - const handlePromptChange = useCallback( - (e: React.ChangeEvent) => { - if (selectedQuickPrompt != null) { - setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); - - if (alreadyExists) { - return prev.map((qp) => { - if (qp.name === selectedQuickPrompt.name) { - return { - ...qp, - prompt: e.target.value, - }; - } - return qp; - }); - } - - return prev; - }); - } - }, - [selectedQuickPrompt, setUpdatedQuickPromptSettings] - ); - - // Color - const selectedColor = useMemo( - () => selectedQuickPrompt?.color ?? DEFAULT_COLOR, - [selectedQuickPrompt?.color] - ); - - const handleColorChange = useCallback( - (color, { hex, isValid }) => { - if (selectedQuickPrompt != null) { - setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); - - if (alreadyExists) { - return prev.map((qp) => { - if (qp.name === selectedQuickPrompt.name) { - return { - ...qp, - color, - }; - } - return qp; - }); - } - return prev; - }); - } - }, - [selectedQuickPrompt, setUpdatedQuickPromptSettings] - ); - - // Prompt Contexts - const selectedPromptContexts = useMemo( - () => - basePromptContexts?.filter((bpc) => - selectedQuickPrompt?.categories?.some((cat) => bpc?.category === cat) - ) ?? [], - [basePromptContexts, selectedQuickPrompt?.categories] - ); - - const onPromptContextSelectionChange = useCallback( - (pc: PromptContextTemplate[]) => { - if (selectedQuickPrompt != null) { - setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); - - if (alreadyExists) { - return prev.map((qp) => { - if (qp.name === selectedQuickPrompt.name) { - return { - ...qp, - categories: pc.map((p) => p.category), - }; - } - return qp; - }); - } - return prev; - }); - } - }, - [selectedQuickPrompt, setUpdatedQuickPromptSettings] - ); - - // When top level quick prompt selection changes - const onQuickPromptSelectionChange = useCallback( - (quickPrompt?: PromptResponse | string) => { - const isNew = typeof quickPrompt === 'string'; - const newSelectedQuickPrompt: PromptResponse | undefined = isNew - ? { - name: quickPrompt ?? '', - content: '', - id: '', - color: DEFAULT_COLOR, - categories: [], - promptType: PromptTypeEnum.quick, - } - : quickPrompt; - - if (newSelectedQuickPrompt != null) { - setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.name === newSelectedQuickPrompt.name); - - if (!alreadyExists) { - return [...prev, newSelectedQuickPrompt]; - } - - return prev; - }); - } - - onSelectedQuickPromptChange(newSelectedQuickPrompt); - }, - [onSelectedQuickPromptChange, setUpdatedQuickPromptSettings] - ); - - const onQuickPromptDeleted = useCallback( - (name: string) => { - setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.name !== name)); - }, - [setUpdatedQuickPromptSettings] - ); - -======= ->>>>>>> upstream/main return ( <> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx index 716298afb21da..ccb79aaa006d0 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx @@ -5,8 +5,11 @@ * 2.0. */ +import { + PromptResponse, + PromptTypeEnum, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { useCallback } from 'react'; -import { QuickPrompt } from '../types'; export const DEFAULT_COLOR = '#D36086'; @@ -14,32 +17,34 @@ export const useQuickPromptEditor = ({ onSelectedQuickPromptChange, setUpdatedQuickPromptSettings, }: { - onSelectedQuickPromptChange: (quickPrompt?: QuickPrompt) => void; - setUpdatedQuickPromptSettings: React.Dispatch>; + onSelectedQuickPromptChange: (quickPrompt?: PromptResponse) => void; + setUpdatedQuickPromptSettings: React.Dispatch>; }) => { const onQuickPromptDeleted = useCallback( (title: string) => { - setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.title !== title)); + setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.name !== title)); }, [setUpdatedQuickPromptSettings] ); // When top level quick prompt selection changes const onQuickPromptSelectionChange = useCallback( - (quickPrompt?: QuickPrompt | string) => { + (quickPrompt?: PromptResponse | string) => { const isNew = typeof quickPrompt === 'string'; - const newSelectedQuickPrompt: QuickPrompt | undefined = isNew + const newSelectedQuickPrompt: PromptResponse | undefined = isNew ? { - title: quickPrompt ?? '', - prompt: '', + name: quickPrompt, + id: quickPrompt, + content: '', color: DEFAULT_COLOR, categories: [], + promptType: PromptTypeEnum.quick, } : quickPrompt; if (newSelectedQuickPrompt != null) { setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.title === newSelectedQuickPrompt.title); + const alreadyExists = prev.some((qp) => qp.name === newSelectedQuickPrompt.name); if (!alreadyExists) { return [...prev, newSelectedQuickPrompt]; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx index df32c296dc22c..7e60e0780f3c9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx @@ -25,11 +25,7 @@ import styled from 'styled-components'; import { css } from '@emotion/react'; import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { AIConnector } from '../../connectorland/connector_selector'; -<<<<<<< HEAD -import { Conversation } from '../../..'; -======= -import { Conversation, Prompt, QuickPrompt, useLoadConnectors } from '../../..'; ->>>>>>> upstream/main +import { Conversation, useLoadConnectors } from '../../..'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; import { TEST_IDS } from '../constants'; @@ -43,9 +39,6 @@ import { SystemPromptSettings, } from '.'; import { useFetchAnonymizationFields } from '../api/anonymization_fields/use_fetch_anonymization_fields'; -<<<<<<< HEAD -import { useFetchPrompts } from '../api/prompts/use_fetch_prompts'; -======= import { ANONYMIZATION_TAB, CONVERSATIONS_TAB, @@ -54,7 +47,7 @@ import { QUICK_PROMPTS_TAB, SYSTEM_PROMPTS_TAB, } from './const'; ->>>>>>> upstream/main +import { useFetchPrompts } from '../api/prompts/use_fetch_prompts'; const StyledEuiModal = styled(EuiModal)` width: 800px; @@ -130,13 +123,9 @@ export const AssistantSettings: React.FC = React.memo( anonymizationFieldsBulkActions, setAnonymizationFieldsBulkActions, setUpdatedAnonymizationData, -<<<<<<< HEAD setPromptsBulkActions, setUpdatedSystemPromptSettings, - } = useSettingsUpdater(conversations, anonymizationFields, allPrompts); -======= - } = useSettingsUpdater(conversations, conversationsLoaded, anonymizationFields); ->>>>>>> upstream/main + } = useSettingsUpdater(conversations, allPrompts, conversationsLoaded, anonymizationFields); // Local state for saving previously selected items so tab switching is friendlier // Conversation Selection State diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx index dd90c5ba1ded9..885009116088c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx @@ -28,15 +28,11 @@ import { KnowledgeBaseSettings, EvaluationSettings } from '.'; import { useLoadConnectors } from '../../connectorland/use_load_connectors'; import { getDefaultConnector } from '../helpers'; import { useFetchAnonymizationFields } from '../api/anonymization_fields/use_fetch_anonymization_fields'; -<<<<<<< HEAD -import { useFetchPrompts } from '../api/prompts/use_fetch_prompts'; -======= import { ConnectorsSettingsManagement } from '../../connectorland/connector_settings_management'; import { ConversationSettingsManagement } from '../conversations/conversation_settings_management'; import { QuickPromptSettingsManagement } from '../quick_prompts/quick_prompt_settings_management'; import { SystemPromptSettingsManagement } from '../prompt_editor/system_prompt/system_prompt_settings_management'; import { AnonymizationSettingsManagement } from '../../data_anonymization/settings/anonymization_settings_management'; ->>>>>>> upstream/main import { ANONYMIZATION_TAB, @@ -78,12 +74,9 @@ export const AssistantSettingsManagement: React.FC = React.memo( const { data: anonymizationFields } = useFetchAnonymizationFields(); -<<<<<<< HEAD const { data: allPrompts } = useFetchPrompts(); // Connector details -======= ->>>>>>> upstream/main const { data: connectors } = useLoadConnectors({ http, }); @@ -116,13 +109,9 @@ export const AssistantSettingsManagement: React.FC = React.memo( resetSettings, } = useSettingsUpdater( conversations, -<<<<<<< HEAD - anonymizationFields ?? { page: 0, perPage: 0, total: 0, data: [] }, - allPrompts -======= + allPrompts, conversationsLoaded, anonymizationFields ?? { page: 0, perPage: 0, total: 0, data: [] } ->>>>>>> upstream/main ); // Local state for saving previously selected items so tab switching is friendlier @@ -312,11 +301,6 @@ export const AssistantSettingsManagement: React.FC = React.memo( connectors={connectors} conversationSettings={conversationSettings} conversationsSettingsBulkActions={conversationsSettingsBulkActions} -<<<<<<< HEAD - setUpdatedSystemPromptSettings={handleChange(setUpdatedSystemPromptSettings)} - promptsBulkActions={promptsBulkActions} - setPromptsBulkActions={handleChange(setPromptsBulkActions)} -======= defaultConnector={defaultConnector} handleSave={handleSave} onCancelClick={onCancelClick} @@ -338,7 +322,6 @@ export const AssistantSettingsManagement: React.FC = React.memo( resetSettings={resetSettings} selectedQuickPrompt={selectedQuickPrompt} setUpdatedQuickPromptSettings={setUpdatedQuickPromptSettings} ->>>>>>> upstream/main /> )} {selectedSettingsTab === ANONYMIZATION_TAB && ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx index f172bbeb1d4bf..d995149cc97d7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx @@ -66,13 +66,8 @@ const mockValues = { }; const updatedValues = { -<<<<<<< HEAD - conversations: { [customConvo.title]: customConvo }, - allSystemPrompts: { update: [mockSuperheroSystemPrompt] }, -======= conversations: { ...mockConversations }, allSystemPrompts: [mockSuperheroSystemPrompt], ->>>>>>> upstream/main allQuickPrompts: [{ title: 'Prompt 2', prompt: 'Prompt 2', color: 'red' }], updatedAnonymizationData: { total: 2, @@ -106,11 +101,7 @@ describe('useSettingsUpdater', () => { it('should set all state variables to their initial values when resetSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => -<<<<<<< HEAD - useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) -======= - useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) ->>>>>>> upstream/main + useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields, mockSystemPrompts) ); await waitForNextUpdate(); const { @@ -158,11 +149,7 @@ describe('useSettingsUpdater', () => { it('should update all state variables to their updated values when saveSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => -<<<<<<< HEAD - useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) -======= useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) ->>>>>>> upstream/main ); await waitForNextUpdate(); const { @@ -201,11 +188,7 @@ describe('useSettingsUpdater', () => { it('should track which toggles have been updated when saveSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => -<<<<<<< HEAD - useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) -======= useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) ->>>>>>> upstream/main ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; @@ -222,11 +205,7 @@ describe('useSettingsUpdater', () => { it('should track only toggles that updated', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => -<<<<<<< HEAD - useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) -======= useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) ->>>>>>> upstream/main ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; @@ -244,11 +223,7 @@ describe('useSettingsUpdater', () => { it('if no toggles update, do not track anything', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => -<<<<<<< HEAD - useSettingsUpdater(mockConversations, anonymizationFields, mockSystemPrompts) -======= useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) ->>>>>>> upstream/main ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx index ddccd301ca1f4..61f95f557b1a3 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx @@ -55,13 +55,9 @@ interface UseSettingsUpdater { export const useSettingsUpdater = ( conversations: Record, -<<<<<<< HEAD - anonymizationFields: FindAnonymizationFieldsResponse, - allSystemPrompts: FindPromptsResponse -======= + allSystemPrompts: FindPromptsResponse, conversationsLoaded: boolean, anonymizationFields: FindAnonymizationFieldsResponse ->>>>>>> upstream/main ): UseSettingsUpdater => { // Initial state from assistant context const { @@ -171,7 +167,6 @@ export const useSettingsUpdater = ( const bulkAnonymizationFieldsResult = hasBulkAnonymizationFields ? await bulkUpdateAnonymizationFields(http, anonymizationFieldsBulkActions, toasts) : undefined; -<<<<<<< HEAD const bulkPromptsResult = hasBulkPrompts ? await bulkUpdatePrompts(http, promptsBulkActions, toasts) @@ -182,9 +177,6 @@ export const useSettingsUpdater = ( (bulkAnonymizationFieldsResult?.success ?? true) && (bulkPromptsResult?.success ?? true) ); -======= - return (bulkResult?.success ?? true) && (bulkAnonymizationFieldsResult?.success ?? true); ->>>>>>> upstream/main }, [ hasBulkConversations, http, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts index e22f3f714a375..587be76910c3e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/types.ts @@ -5,22 +5,6 @@ * 2.0. */ -<<<<<<< HEAD -======= -export type PromptType = 'system' | 'user'; - -export interface Prompt { - id: string; - content: string; - name: string; - promptType: PromptType; - isDefault?: boolean; // TODO: Should be renamed to isImmutable as this flag is used to prevent users from deleting prompts - isNewConversationDefault?: boolean; - isFlyoutMode?: boolean; - label?: string; -} - ->>>>>>> upstream/main export interface KnowledgeBaseConfig { isEnabledRAGAlerts: boolean; isEnabledKnowledgeBase: boolean; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx index f00b54fea6b45..11db1e41aa3c6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx @@ -122,13 +122,7 @@ export interface UseAssistantContext { navigateToApp: (appId: string, options?: NavigateToAppOptions | undefined) => Promise; nameSpace: string; registerPromptContext: RegisterPromptContext; -<<<<<<< HEAD - selectedSettingsTab: SettingsTabs; -======= selectedSettingsTab: SettingsTabs | null; - setAllQuickPrompts: React.Dispatch>; - setAllSystemPrompts: React.Dispatch>; ->>>>>>> upstream/main setAssistantStreamingEnabled: React.Dispatch>; setKnowledgeBase: React.Dispatch>; setLastConversationId: React.Dispatch>; From 492aa250278a14fdd4c2a88106f4e0924216e4d1 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 10:41:22 -0700 Subject: [PATCH 03/22] fixed type checks --- .../index.tsx | 13 +++++++++- .../index.tsx | 24 +++++++++---------- .../use_quick_prompt_table.tsx | 24 +++++++++---------- .../assistant_settings_management.tsx | 3 +++ 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx index 8f21c11cf2f87..14b6ecb868ead 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/index.tsx @@ -16,7 +16,10 @@ import { } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { + PromptResponse, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation, ConversationsBulkActions, useAssistantContext } from '../../../../..'; import { SYSTEM_PROMPT_TABLE_SESSION_STORAGE_KEY } from '../../../../assistant_context/constants'; import { AIConnector } from '../../../../connectorland/connector_selector'; @@ -49,6 +52,8 @@ interface Props { handleSave: (shouldRefetchConversation?: boolean) => void; onCancelClick: () => void; resetSettings: () => void; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; } const SystemPromptSettingsManagementComponent = ({ @@ -65,6 +70,8 @@ const SystemPromptSettingsManagementComponent = ({ handleSave, onCancelClick, resetSettings, + promptsBulkActions, + setPromptsBulkActions, }: Props) => { const { nameSpace } = useAssistantContext(); const { isFlyoutOpen: editFlyoutVisible, openFlyout, closeFlyout } = useFlyoutModalVisibility(); @@ -88,6 +95,8 @@ const SystemPromptSettingsManagementComponent = ({ const { onSystemPromptSelectionChange, onSystemPromptDeleted } = useSystemPromptEditor({ setUpdatedSystemPromptSettings, onSelectedSystemPromptChange, + promptsBulkActions, + setPromptsBulkActions, }); const onEditActionClicked = useCallback( @@ -200,6 +209,8 @@ const SystemPromptSettingsManagementComponent = ({ setConversationsSettingsBulkActions={setConversationsSettingsBulkActions} defaultConnector={defaultConnector} resetSettings={resetSettings} + promptsBulkActions={promptsBulkActions} + setPromptsBulkActions={setPromptsBulkActions} /> {deleteConfirmModalVisibility && deletedPrompt?.name && ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx index e8362db441719..0f0726dbf14b6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx @@ -14,7 +14,7 @@ import { EuiPanel, EuiSpacer, } from '@elastic/eui'; -import { QuickPrompt } from '../types'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { QuickPromptSettingsEditor } from '../quick_prompt_settings/quick_prompt_editor'; import * as i18n from './translations'; import { useFlyoutModalVisibility } from '../../common/components/assistant_settings_management/flyout/use_flyout_modal_visibility'; @@ -32,11 +32,11 @@ import { useAssistantContext } from '../../../assistant_context'; interface Props { handleSave: (shouldRefetchConversation?: boolean) => void; onCancelClick: () => void; - onSelectedQuickPromptChange: (quickPrompt?: QuickPrompt) => void; - quickPromptSettings: QuickPrompt[]; + onSelectedQuickPromptChange: (quickPrompt?: PromptResponse) => void; + quickPromptSettings: PromptResponse[]; resetSettings?: () => void; - selectedQuickPrompt: QuickPrompt | undefined; - setUpdatedQuickPromptSettings: React.Dispatch>; + selectedQuickPrompt: PromptResponse | undefined; + setUpdatedQuickPromptSettings: React.Dispatch>; } const QuickPromptSettingsManagementComponent = ({ @@ -51,7 +51,7 @@ const QuickPromptSettingsManagementComponent = ({ const { nameSpace, basePromptContexts } = useAssistantContext(); const { isFlyoutOpen: editFlyoutVisible, openFlyout, closeFlyout } = useFlyoutModalVisibility(); - const [deletedQuickPrompt, setDeletedQuickPrompt] = useState(); + const [deletedQuickPrompt, setDeletedQuickPrompt] = useState(); const { isFlyoutOpen: deleteConfirmModalVisibility, openFlyout: openConfirmModal, @@ -64,7 +64,7 @@ const QuickPromptSettingsManagementComponent = ({ }); const onEditActionClicked = useCallback( - (prompt: QuickPrompt) => { + (prompt: PromptResponse) => { onQuickPromptSelectionChange(prompt); openFlyout(); }, @@ -72,9 +72,9 @@ const QuickPromptSettingsManagementComponent = ({ ); const onDeleteActionClicked = useCallback( - (prompt: QuickPrompt) => { + (prompt: PromptResponse) => { setDeletedQuickPrompt(prompt); - onQuickPromptDeleted(prompt.title); + onQuickPromptDeleted(prompt.name); openConfirmModal(); }, [onQuickPromptDeleted, openConfirmModal] @@ -123,10 +123,10 @@ const QuickPromptSettingsManagementComponent = ({ const confirmationTitle = useMemo( () => - deletedQuickPrompt?.title - ? i18n.DELETE_QUICK_PROMPT_MODAL_TITLE(deletedQuickPrompt.title) + deletedQuickPrompt?.name + ? i18n.DELETE_QUICK_PROMPT_MODAL_TITLE(deletedQuickPrompt.name) : i18n.DELETE_QUICK_PROMPT_MODAL_DEFAULT_TITLE, - [deletedQuickPrompt?.title] + [deletedQuickPrompt?.name] ); return ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx index 9ec334f817340..fb3138ccab56a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx @@ -7,10 +7,10 @@ import { EuiBasicTableColumn, EuiLink } from '@elastic/eui'; import React, { useCallback } from 'react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { BadgesColumn } from '../../common/components/assistant_settings_management/badges'; import { RowActions } from '../../common/components/assistant_settings_management/row_actions'; import { PromptContextTemplate } from '../../prompt_context/types'; -import { QuickPrompt } from '../types'; import * as i18n from './translations'; export const useQuickPromptTable = () => { @@ -21,29 +21,29 @@ export const useQuickPromptTable = () => { onDeleteActionClicked, }: { basePromptContexts: PromptContextTemplate[]; - onEditActionClicked: (prompt: QuickPrompt) => void; - onDeleteActionClicked: (prompt: QuickPrompt) => void; - }): Array> => [ + onEditActionClicked: (prompt: PromptResponse) => void; + onDeleteActionClicked: (prompt: PromptResponse) => void; + }): Array> => [ { align: 'left', name: i18n.QUICK_PROMPTS_TABLE_COLUMN_NAME, - render: (prompt: QuickPrompt) => - prompt?.title ? ( - onEditActionClicked(prompt)}>{prompt?.title} + render: (prompt: PromptResponse) => + prompt?.name ? ( + onEditActionClicked(prompt)}>{prompt?.name} ) : null, - sortable: ({ title }: QuickPrompt) => title, + sortable: ({ name }: PromptResponse) => name, }, { align: 'left', name: i18n.QUICK_PROMPTS_TABLE_COLUMN_CONTEXTS, - render: (prompt: QuickPrompt) => { + render: (prompt: PromptResponse) => { const selectedPromptContexts = ( basePromptContexts.filter((bpc) => prompt?.categories?.some((cat) => bpc?.category === cat) ) ?? [] ).map((bpc) => bpc?.description); return selectedPromptContexts ? ( - + ) : null; }, }, @@ -58,13 +58,13 @@ export const useQuickPromptTable = () => { align: 'center', name: i18n.QUICK_PROMPTS_TABLE_COLUMN_ACTIONS, width: '120px', - render: (prompt: QuickPrompt) => { + render: (prompt: PromptResponse) => { if (!prompt) { return null; } const isDeletable = !prompt.isDefault; return ( - + rowItem={prompt} onDelete={isDeletable ? onDeleteActionClicked : undefined} onEdit={onEditActionClicked} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx index 885009116088c..9512051fbca9e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx @@ -43,6 +43,7 @@ import { QUICK_PROMPTS_TAB, SYSTEM_PROMPTS_TAB, } from './const'; +import { useFetchPrompts } from '../api/prompts/use_fetch_prompts'; interface Props { conversations: Record; @@ -311,6 +312,8 @@ export const AssistantSettingsManagement: React.FC = React.memo( setConversationsSettingsBulkActions={setConversationsSettingsBulkActions} setUpdatedSystemPromptSettings={setUpdatedSystemPromptSettings} systemPromptSettings={systemPromptSettings} + promptsBulkActions={promptsBulkActions} + setPromptsBulkActions={setPromptsBulkActions} /> )} {selectedSettingsTab === QUICK_PROMPTS_TAB && ( From 5ef4eb1488a4c3cd65ed020f8140abcea1cae981 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 11:45:54 -0700 Subject: [PATCH 04/22] fixed create new --- .../conversation_settings_editor.tsx | 7 +++--- .../use_system_prompt_editor.tsx | 24 ++++++++++++------- .../impl/assistant_context/index.tsx | 5 ++++ .../mock/test_providers/test_providers.tsx | 1 + .../public/assistant/provider.tsx | 5 +++- .../common/mock/mock_assistant_provider.tsx | 1 + .../rule_status_failed_callout.test.tsx | 1 + 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx index a0ddd33b34d05..5bb3c4597b8a5 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx @@ -12,7 +12,8 @@ import { HttpSetup } from '@kbn/core-http-browser'; import { FormattedMessage } from '@kbn/i18n-react'; import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; import { noop } from 'lodash/fp'; -import { Conversation, Prompt } from '../../../..'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { Conversation } from '../../../..'; import * as i18n from './translations'; import * as i18nModel from '../../../connectorland/models/model_selector/translations'; @@ -25,7 +26,7 @@ import { ConversationsBulkActions } from '../../api'; import { getDefaultSystemPrompt } from '../../use_conversation/helpers'; export interface ConversationSettingsEditorProps { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; http: HttpSetup; @@ -268,7 +269,7 @@ export const ConversationSettingsEditor: React.FC >; @@ -24,6 +25,7 @@ export const useSystemPromptEditor = ({ promptsBulkActions, setPromptsBulkActions, }: Props) => { + const { currentAppId } = useAssistantContext(); // When top level system prompt selection changes const onSystemPromptSelectionChange = useCallback( (systemPrompt?: PromptResponse | string) => { @@ -34,6 +36,7 @@ export const useSystemPromptEditor = ({ content: '', name: systemPrompt ?? '', promptType: 'system', + consumer: currentAppId, } : systemPrompt; @@ -48,20 +51,23 @@ export const useSystemPromptEditor = ({ return prev; }); - setPromptsBulkActions({ - ...promptsBulkActions, - create: [ - ...(promptsBulkActions.create ?? []), - { - ...newSelectedSystemPrompt, - }, - ], - }); + if (isNew) { + setPromptsBulkActions({ + ...promptsBulkActions, + create: [ + ...(promptsBulkActions.create ?? []), + { + ...newSelectedSystemPrompt, + }, + ], + }); + } } onSelectedSystemPromptChange(newSelectedSystemPrompt); }, [ + currentAppId, onSelectedSystemPromptChange, promptsBulkActions, setPromptsBulkActions, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx index 11db1e41aa3c6..78336f8a8b03d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx @@ -81,6 +81,7 @@ export interface AssistantProviderProps { navigateToApp: (appId: string, options?: NavigateToAppOptions | undefined) => Promise; title?: string; toasts?: IToasts; + currentAppId: string; } export interface UserAvatar { @@ -139,6 +140,7 @@ export interface UseAssistantContext { traceOptions: TraceOptions; basePromptContexts: PromptContextTemplate[]; unRegisterPromptContext: UnRegisterPromptContext; + currentAppId: string; } const AssistantContext = React.createContext(undefined); @@ -160,6 +162,7 @@ export const AssistantProvider: React.FC = ({ nameSpace = DEFAULT_ASSISTANT_NAMESPACE, title = DEFAULT_ASSISTANT_TITLE, toasts, + currentAppId, }) => { /** * Session storage for traceOptions, including APM URL and LangSmith Project/API Key @@ -286,6 +289,7 @@ export const AssistantProvider: React.FC = ({ getLastConversationId, setLastConversationId: setLocalStorageLastConversationId, baseConversations, + currentAppId, }), [ actionTypeRegistry, @@ -317,6 +321,7 @@ export const AssistantProvider: React.FC = ({ getLastConversationId, setLocalStorageLastConversationId, baseConversations, + currentAppId, ] ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx index 17e977fdbf80f..13e543a02b3b2 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx @@ -81,6 +81,7 @@ export const TestProvidersComponent: React.FC = ({ baseConversations={{}} navigateToApp={mockNavigateToApp} {...providerContext} + currentAppId={'test'} > {children} diff --git a/x-pack/plugins/security_solution/public/assistant/provider.tsx b/x-pack/plugins/security_solution/public/assistant/provider.tsx index d1d62d047defa..cf38392333356 100644 --- a/x-pack/plugins/security_solution/public/assistant/provider.tsx +++ b/x-pack/plugins/security_solution/public/assistant/provider.tsx @@ -21,6 +21,7 @@ import { once } from 'lodash/fp'; import type { HttpSetup } from '@kbn/core-http-browser'; import type { Message } from '@kbn/elastic-assistant-common'; import { loadAllActions as loadConnectors } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; +import { useObservable } from 'react-use'; import { APP_ID } from '../../common'; import { useBasePath, useKibana } from '../common/lib/kibana'; import { useAssistantTelemetry } from './use_assistant_telemetry'; @@ -115,7 +116,7 @@ export const createConversations = async ( */ export const AssistantProvider: FC> = ({ children }) => { const { - application: { navigateToApp }, + application: { navigateToApp, currentAppId$ }, http, notifications, storage, @@ -127,6 +128,7 @@ export const AssistantProvider: FC> = ({ children }) const baseConversations = useBaseConversations(); const assistantAvailability = useAssistantAvailability(); const assistantTelemetry = useAssistantTelemetry(); + const currentAppId = useObservable(currentAppId$, ''); useEffect(() => { const migrateConversationsFromLocalStorage = once(async () => { @@ -170,6 +172,7 @@ export const AssistantProvider: FC> = ({ children }) navigateToApp={navigateToApp} title={ASSISTANT_TITLE} toasts={toasts} + currentAppId={currentAppId ?? 'securitySolutionUI'} > {children} diff --git a/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx b/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx index b9a83fd280b10..04860ba9c6c71 100644 --- a/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx @@ -50,6 +50,7 @@ export const MockAssistantProviderComponent: React.FC = ({ http={mockHttp} navigateToApp={mockNavigateToApp} baseConversations={BASE_SECURITY_CONVERSATIONS} + currentAppId={'test'} > {children} diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.test.tsx index b5e7737be38f7..23c2d2e7b9f6b 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.test.tsx @@ -64,6 +64,7 @@ const ContextWrapper: FC> = ({ children }) => ( http={mockHttp} navigateToApp={mockNavigationToApp} baseConversations={BASE_SECURITY_CONVERSATIONS} + currentAppId={'security'} > {children} From bb2ce242b6fb4929a0b7c9ac25b3a1d2688b5287 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 12:36:35 -0700 Subject: [PATCH 05/22] fixed tests --- .../quick_prompt_selector.test.tsx | 6 +-- .../quick_prompt_editor.tsx | 11 ++++- .../quick_prompt_settings.test.tsx | 3 ++ .../quick_prompt_settings.tsx | 11 ++++- .../use_quick_prompt_editor.test.tsx | 29 +++++++---- .../use_quick_prompt_editor.tsx | 28 ++++++++++- .../index.tsx | 13 ++++- .../use_quick_prompt_table.test.tsx | 10 ++-- .../quick_prompts/quick_prompts.test.tsx | 1 + .../assistant/settings/assistant_settings.tsx | 2 + .../assistant_settings_management.tsx | 2 + .../impl/mock/quick_prompt.ts | 49 +++++++++++++------ 12 files changed, 128 insertions(+), 37 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx index 04ccd478e3bc5..29db7a3500bd2 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx @@ -25,9 +25,9 @@ describe('QuickPromptSelector', () => { }); it('Selects an existing quick prompt', () => { const { getByTestId } = render(); - expect(getByTestId('euiComboBoxPill')).toHaveTextContent(MOCK_QUICK_PROMPTS[0].title); + expect(getByTestId('euiComboBoxPill')).toHaveTextContent(MOCK_QUICK_PROMPTS[0].name); fireEvent.click(getByTestId('comboBoxToggleListButton')); - fireEvent.click(getByTestId(MOCK_QUICK_PROMPTS[1].title)); + fireEvent.click(getByTestId(MOCK_QUICK_PROMPTS[1].name)); expect(onQuickPromptSelectionChange).toHaveBeenCalledWith(MOCK_QUICK_PROMPTS[1]); }); it('Only custom option can be deleted', () => { @@ -60,7 +60,7 @@ describe('QuickPromptSelector', () => { ); // changing the selection fireEvent.change(getByTestId('comboBoxSearchInput'), { - target: { value: MOCK_QUICK_PROMPTS[1].title }, + target: { value: MOCK_QUICK_PROMPTS[1].name }, }); fireEvent.keyDown(getByTestId('comboBoxSearchInput'), { key: 'Enter', diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx index 1a5baf8685304..428761ae73907 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx @@ -10,7 +10,10 @@ import { EuiFormRow, EuiColorPicker, EuiTextArea } from '@elastic/eui'; import { EuiSetColorMethod } from '@elastic/eui/src/services/color_picker/color_picker'; import { css } from '@emotion/react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { + PromptResponse, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { PromptContextTemplate } from '../../../..'; import * as i18n from './translations'; import { QuickPromptSelector } from '../quick_prompt_selector/quick_prompt_selector'; @@ -26,6 +29,8 @@ interface Props { resetSettings?: () => void; selectedQuickPrompt: PromptResponse | undefined; setUpdatedQuickPromptSettings: React.Dispatch>; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; } const QuickPromptSettingsEditorComponent = ({ @@ -34,6 +39,8 @@ const QuickPromptSettingsEditorComponent = ({ resetSettings, selectedQuickPrompt, setUpdatedQuickPromptSettings, + promptsBulkActions, + setPromptsBulkActions, }: Props) => { const { basePromptContexts } = useAssistantContext(); @@ -136,6 +143,8 @@ const QuickPromptSettingsEditorComponent = ({ const { onQuickPromptDeleted, onQuickPromptSelectionChange } = useQuickPromptEditor({ onSelectedQuickPromptChange, setUpdatedQuickPromptSettings, + promptsBulkActions, + setPromptsBulkActions, }); return ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx index 6aa939934d585..48792146f9036 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx @@ -13,6 +13,7 @@ import { MOCK_QUICK_PROMPTS } from '../../../mock/quick_prompt'; import { mockPromptContexts } from '../../../mock/prompt_context'; const onSelectedQuickPromptChange = jest.fn(); +const setPromptsBulkActions = jest.fn(); const setUpdatedQuickPromptSettings = jest.fn().mockImplementation((fn) => { return fn(MOCK_QUICK_PROMPTS); }); @@ -22,6 +23,8 @@ const testProps = { quickPromptSettings: MOCK_QUICK_PROMPTS, selectedQuickPrompt: MOCK_QUICK_PROMPTS[0], setUpdatedQuickPromptSettings, + promptsBulkActions: {}, + setPromptsBulkActions, }; const mockContext = { basePromptContexts: MOCK_QUICK_PROMPTS, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx index bbb15268ad7d2..61496c64fd73a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.tsx @@ -8,7 +8,10 @@ import React from 'react'; import { EuiTitle, EuiText, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { + PromptResponse, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import * as i18n from './translations'; import { QuickPromptSettingsEditor } from './quick_prompt_editor'; @@ -17,6 +20,8 @@ interface Props { quickPromptSettings: PromptResponse[]; selectedQuickPrompt: PromptResponse | undefined; setUpdatedQuickPromptSettings: React.Dispatch>; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; } /** @@ -28,6 +33,8 @@ export const QuickPromptSettings: React.FC = React.memo( quickPromptSettings, selectedQuickPrompt, setUpdatedQuickPromptSettings, + promptsBulkActions, + setPromptsBulkActions, }) => { return ( <> @@ -43,6 +50,8 @@ export const QuickPromptSettings: React.FC = React.memo( quickPromptSettings={quickPromptSettings} selectedQuickPrompt={selectedQuickPrompt} setUpdatedQuickPromptSettings={setUpdatedQuickPromptSettings} + promptsBulkActions={promptsBulkActions} + setPromptsBulkActions={setPromptsBulkActions} /> ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx index ec3a0256716ae..7f130a201443b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx @@ -7,14 +7,15 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useQuickPromptEditor, DEFAULT_COLOR } from './use_quick_prompt_editor'; -import { QuickPrompt } from '../types'; import { mockAlertPromptContext } from '../../../mock/prompt_context'; import { MOCK_QUICK_PROMPTS } from '../../../mock/quick_prompt'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; // Mock functions for the tests const mockOnSelectedQuickPromptChange = jest.fn(); const mockSetUpdatedQuickPromptSettings = jest.fn(); const mockPreviousQuickPrompts = [...MOCK_QUICK_PROMPTS]; +const setPromptsBulkActions = jest.fn(); describe('useQuickPromptEditor', () => { beforeEach(() => { @@ -26,6 +27,8 @@ describe('useQuickPromptEditor', () => { useQuickPromptEditor({ onSelectedQuickPromptChange: mockOnSelectedQuickPromptChange, setUpdatedQuickPromptSettings: mockSetUpdatedQuickPromptSettings, + setPromptsBulkActions, + promptsBulkActions: {}, }) ); @@ -34,7 +37,7 @@ describe('useQuickPromptEditor', () => { }); expect(mockSetUpdatedQuickPromptSettings.mock.calls[0][0]?.(mockPreviousQuickPrompts)).toEqual( - MOCK_QUICK_PROMPTS.filter((qp) => qp.title !== 'ALERT_SUMMARIZATION_TITLE') + MOCK_QUICK_PROMPTS.filter((qp) => qp.name !== 'ALERT_SUMMARIZATION_TITLE') ); }); @@ -44,6 +47,8 @@ describe('useQuickPromptEditor', () => { useQuickPromptEditor({ onSelectedQuickPromptChange: mockOnSelectedQuickPromptChange, setUpdatedQuickPromptSettings: mockSetUpdatedQuickPromptSettings, + setPromptsBulkActions, + promptsBulkActions: {}, }) ); @@ -51,11 +56,13 @@ describe('useQuickPromptEditor', () => { result.current.onQuickPromptSelectionChange(newPromptTitle); }); - const newPrompt: QuickPrompt = { - title: newPromptTitle, - prompt: '', + const newPrompt: PromptResponse = { + name: newPromptTitle, + content: '', color: DEFAULT_COLOR, categories: [], + id: '', + promptType: 'quick', }; expect(mockOnSelectedQuickPromptChange).toHaveBeenCalledWith(newPrompt); @@ -70,17 +77,21 @@ describe('useQuickPromptEditor', () => { useQuickPromptEditor({ onSelectedQuickPromptChange: mockOnSelectedQuickPromptChange, setUpdatedQuickPromptSettings: mockSetUpdatedQuickPromptSettings, + setPromptsBulkActions, + promptsBulkActions: {}, }) ); const alertData = await mockAlertPromptContext.getPromptContext(); - const expectedPrompt: QuickPrompt = { - title: mockAlertPromptContext.description, - prompt: alertData, + const expectedPrompt: PromptResponse = { + name: mockAlertPromptContext.description, + content: alertData.content ?? '', color: DEFAULT_COLOR, categories: [mockAlertPromptContext.category], - } as QuickPrompt; + id: '', + promptType: 'quick', + }; act(() => { result.current.onQuickPromptSelectionChange(expectedPrompt); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx index ccb79aaa006d0..d4918faef0e45 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx @@ -8,18 +8,25 @@ import { PromptResponse, PromptTypeEnum, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { useCallback } from 'react'; +import { useAssistantContext } from '../../../..'; export const DEFAULT_COLOR = '#D36086'; export const useQuickPromptEditor = ({ onSelectedQuickPromptChange, setUpdatedQuickPromptSettings, + promptsBulkActions, + setPromptsBulkActions, }: { onSelectedQuickPromptChange: (quickPrompt?: PromptResponse) => void; setUpdatedQuickPromptSettings: React.Dispatch>; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; }) => { + const { currentAppId } = useAssistantContext(); const onQuickPromptDeleted = useCallback( (title: string) => { setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.name !== title)); @@ -39,6 +46,7 @@ export const useQuickPromptEditor = ({ color: DEFAULT_COLOR, categories: [], promptType: PromptTypeEnum.quick, + consumer: currentAppId, } : quickPrompt; @@ -52,11 +60,29 @@ export const useQuickPromptEditor = ({ return prev; }); + + if (isNew) { + setPromptsBulkActions({ + ...promptsBulkActions, + create: [ + ...(promptsBulkActions.create ?? []), + { + ...newSelectedQuickPrompt, + }, + ], + }); + } } onSelectedQuickPromptChange(newSelectedQuickPrompt); }, - [onSelectedQuickPromptChange, setUpdatedQuickPromptSettings] + [ + currentAppId, + onSelectedQuickPromptChange, + promptsBulkActions, + setPromptsBulkActions, + setUpdatedQuickPromptSettings, + ] ); return { onQuickPromptDeleted, onQuickPromptSelectionChange }; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx index 0f0726dbf14b6..fea6264b72a9a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx @@ -14,7 +14,10 @@ import { EuiPanel, EuiSpacer, } from '@elastic/eui'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { + PromptResponse, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { QuickPromptSettingsEditor } from '../quick_prompt_settings/quick_prompt_editor'; import * as i18n from './translations'; import { useFlyoutModalVisibility } from '../../common/components/assistant_settings_management/flyout/use_flyout_modal_visibility'; @@ -37,6 +40,8 @@ interface Props { resetSettings?: () => void; selectedQuickPrompt: PromptResponse | undefined; setUpdatedQuickPromptSettings: React.Dispatch>; + promptsBulkActions: PromptsPerformBulkActionRequestBody; + setPromptsBulkActions: React.Dispatch>; } const QuickPromptSettingsManagementComponent = ({ @@ -47,6 +52,8 @@ const QuickPromptSettingsManagementComponent = ({ resetSettings, selectedQuickPrompt, setUpdatedQuickPromptSettings, + promptsBulkActions, + setPromptsBulkActions, }: Props) => { const { nameSpace, basePromptContexts } = useAssistantContext(); @@ -61,6 +68,8 @@ const QuickPromptSettingsManagementComponent = ({ const { onQuickPromptDeleted, onQuickPromptSelectionChange } = useQuickPromptEditor({ onSelectedQuickPromptChange, setUpdatedQuickPromptSettings, + promptsBulkActions, + setPromptsBulkActions, }); const onEditActionClicked = useCallback( @@ -161,6 +170,8 @@ const QuickPromptSettingsManagementComponent = ({ resetSettings={resetSettings} selectedQuickPrompt={selectedQuickPrompt} setUpdatedQuickPromptSettings={setUpdatedQuickPromptSettings} + promptsBulkActions={promptsBulkActions} + setPromptsBulkActions={setPromptsBulkActions} /> {deleteConfirmModalVisibility && deletedQuickPrompt && ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx index 316b43f6cfb3d..8a852a904aedc 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx @@ -8,9 +8,9 @@ import { renderHook } from '@testing-library/react-hooks'; import { useQuickPromptTable } from './use_quick_prompt_table'; import { EuiTableComputedColumnType } from '@elastic/eui'; -import { QuickPrompt } from '../types'; import { MOCK_QUICK_PROMPTS } from '../../../mock/quick_prompt'; import { mockPromptContexts } from '../../../mock/prompt_context'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; const mockOnEditActionClicked = jest.fn(); const mockOnDeleteActionClicked = jest.fn(); @@ -43,7 +43,7 @@ describe('useQuickPromptTable', () => { }); const mockQuickPrompt = { ...MOCK_QUICK_PROMPTS[0], categories: ['alert'] }; - const mockBadgesColumn = (columns[1] as EuiTableComputedColumnType).render( + const mockBadgesColumn = (columns[1] as EuiTableComputedColumnType).render( mockQuickPrompt ); const selectedPromptContexts = mockPromptContexts @@ -51,7 +51,7 @@ describe('useQuickPromptTable', () => { .map((bpc) => bpc.description); expect(mockBadgesColumn).toHaveProperty('props', { items: selectedPromptContexts, - prefix: MOCK_QUICK_PROMPTS[0].title, + prefix: MOCK_QUICK_PROMPTS[0].name, }); }); @@ -62,7 +62,7 @@ describe('useQuickPromptTable', () => { onDeleteActionClicked: mockOnDeleteActionClicked, }); - const mockRowActions = (columns[2] as EuiTableComputedColumnType).render( + const mockRowActions = (columns[2] as EuiTableComputedColumnType).render( MOCK_QUICK_PROMPTS[0] ); @@ -83,7 +83,7 @@ describe('useQuickPromptTable', () => { const nonDefaultPrompt = MOCK_QUICK_PROMPTS.find((qp) => !qp.isDefault); if (nonDefaultPrompt) { - const mockRowActions = (columns[2] as EuiTableComputedColumnType).render( + const mockRowActions = (columns[2] as EuiTableComputedColumnType).render( nonDefaultPrompt ); expect(mockRowActions).toHaveProperty('props', { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx index 7fb2c9760fc7b..a7de474bf396c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx @@ -20,6 +20,7 @@ const testProps = { setIsSettingsModalVisible, trackPrompt, isFlyoutMode: false, + allPrompts: MOCK_QUICK_PROMPTS, }; const setSelectedSettingsTab = jest.fn(); const mockUseAssistantContext = { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx index 7e60e0780f3c9..5fb6255559aa6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx @@ -347,6 +347,8 @@ export const AssistantSettings: React.FC = React.memo( onSelectedQuickPromptChange={onHandleSelectedQuickPromptChange} selectedQuickPrompt={selectedQuickPrompt} setUpdatedQuickPromptSettings={setUpdatedQuickPromptSettings} + setPromptsBulkActions={setPromptsBulkActions} + promptsBulkActions={promptsBulkActions} /> )} {selectedSettingsTab === SYSTEM_PROMPTS_TAB && ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx index 9512051fbca9e..a932db0b195a7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx @@ -325,6 +325,8 @@ export const AssistantSettingsManagement: React.FC = React.memo( resetSettings={resetSettings} selectedQuickPrompt={selectedQuickPrompt} setUpdatedQuickPromptSettings={setUpdatedQuickPromptSettings} + promptsBulkActions={promptsBulkActions} + setPromptsBulkActions={setPromptsBulkActions} /> )} {selectedSettingsTab === ANONYMIZATION_TAB && ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/quick_prompt.ts b/x-pack/packages/kbn-elastic-assistant/impl/mock/quick_prompt.ts index 14318f4b1b534..31fa9bb6508b8 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/quick_prompt.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/quick_prompt.ts @@ -5,52 +5,69 @@ * 2.0. */ -import { QuickPrompt } from '../..'; +import { + PromptResponse, + PromptTypeEnum, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; -export const MOCK_QUICK_PROMPTS: QuickPrompt[] = [ +export const MOCK_QUICK_PROMPTS: PromptResponse[] = [ { - title: 'ALERT_SUMMARIZATION_TITLE', - prompt: 'ALERT_SUMMARIZATION_PROMPT', + name: 'ALERT_SUMMARIZATION_TITLE', + content: 'ALERT_SUMMARIZATION_PROMPT', color: '#F68FBE', categories: ['PROMPT_CONTEXT_ALERT_CATEGORY'], isDefault: true, + id: 'ALERT_SUMMARIZATION_TITLE', + promptType: PromptTypeEnum.quick, }, { - title: 'RULE_CREATION_TITLE', - prompt: 'RULE_CREATION_PROMPT', + name: 'RULE_CREATION_TITLE', + content: 'RULE_CREATION_PROMPT', categories: ['PROMPT_CONTEXT_DETECTION_RULES_CATEGORY'], color: '#7DDED8', isDefault: true, + id: 'RULE_CREATION_TITLE', + promptType: PromptTypeEnum.quick, }, { - title: 'WORKFLOW_ANALYSIS_TITLE', - prompt: 'WORKFLOW_ANALYSIS_PROMPT', + name: 'WORKFLOW_ANALYSIS_TITLE', + content: 'WORKFLOW_ANALYSIS_PROMPT', color: '#36A2EF', isDefault: true, + id: 'WORKFLOW_ANALYSIS_TITLE', + promptType: PromptTypeEnum.quick, }, { - title: 'THREAT_INVESTIGATION_GUIDES_TITLE', - prompt: 'THREAT_INVESTIGATION_GUIDES_PROMPT', + name: 'THREAT_INVESTIGATION_GUIDES_TITLE', + content: 'THREAT_INVESTIGATION_GUIDES_PROMPT', categories: ['PROMPT_CONTEXT_EVENT_CATEGORY'], color: '#F3D371', isDefault: true, + id: 'THREAT_INVESTIGATION_GUIDES_TITLE', + promptType: PromptTypeEnum.quick, }, { - title: 'SPL_QUERY_CONVERSION_TITLE', - prompt: 'SPL_QUERY_CONVERSION_PROMPT', + name: 'SPL_QUERY_CONVERSION_TITLE', + content: 'SPL_QUERY_CONVERSION_PROMPT', color: '#BADA55', isDefault: true, + id: 'SPL_QUERY_CONVERSION_TITLE', + promptType: PromptTypeEnum.quick, }, { - title: 'AUTOMATION_TITLE', - prompt: 'AUTOMATION_PROMPT', + name: 'AUTOMATION_TITLE', + content: 'AUTOMATION_PROMPT', color: '#FFA500', isDefault: true, + id: 'AUTOMATION_TITLE', + promptType: PromptTypeEnum.quick, }, { - title: 'A_CUSTOM_OPTION', - prompt: 'quickly prompt please', + name: 'A_CUSTOM_OPTION', + content: 'quickly prompt please', color: '#D36086', categories: [], + id: 'A_CUSTOM_OPTION', + promptType: PromptTypeEnum.quick, }, ]; From 3aec5931222247ac610cedb04ae81a235b727786 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 12:55:43 -0700 Subject: [PATCH 06/22] fixed tests --- .../utils.test.tsx | 4 +- .../utils.tsx | 4 +- .../use_settings_updater.test.tsx | 66 ++++++++++++++++--- .../impl/content/prompts/system/index.tsx | 8 +-- .../impl/mock/user_prompt/index.ts | 6 +- 5 files changed, 68 insertions(+), 20 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.test.tsx index 5f10e3bb59c65..9fbfb3a8782e0 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.test.tsx @@ -6,8 +6,8 @@ */ import { ProviderEnum } from '@kbn/elastic-assistant-common'; import { mockSystemPrompts } from '../../../../mock/system_prompt'; -import { PromptType } from '../../../types'; import { getSelectedConversations } from './utils'; +import { PromptTypeEnum } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; describe('getSelectedConversations', () => { const allSystemPrompts = [...mockSystemPrompts]; const conversationSettings = { @@ -39,7 +39,7 @@ describe('getSelectedConversations', () => { content: 'You are a helpful, expert assistant who answers questions about Elastic Security. Do not answer questions unrelated to Elastic Security.\nProvide the most detailed and relevant answer possible, as if you were relaying this information back to a cyber security expert.\nIf you answer a question related to KQL, EQL, or ES|QL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query. xxx', name: 'Enhanced system prompt', - promptType: 'system' as PromptType, + promptType: PromptTypeEnum.system, isDefault: true, isNewConversationDefault: true, }, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx index 5fde200db9b17..a9761e9de2135 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx @@ -5,11 +5,11 @@ * 2.0. */ +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation } from '../../../../assistant_context/types'; -import { Prompt } from '../../../types'; export const getSelectedConversations = ( - allSystemPrompts: Prompt[], + allSystemPrompts: PromptResponse[], conversationSettings: Record, systemPromptId: string ) => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx index d995149cc97d7..45e06f5589163 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx @@ -101,14 +101,22 @@ describe('useSettingsUpdater', () => { it('should set all state variables to their initial values when resetSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields, mockSystemPrompts) + useSettingsUpdater( + mockConversations, + { + data: mockSystemPrompts, + page: 1, + perPage: 100, + total: 10, + }, + conversationsLoaded, + anonymizationFields + ) ); await waitForNextUpdate(); const { setConversationSettings, setConversationsSettingsBulkActions, - setUpdatedQuickPromptSettings, - setUpdatedSystemPromptSettings, setUpdatedKnowledgeBaseSettings, setUpdatedAssistantStreamingEnabled, resetSettings, @@ -117,7 +125,7 @@ describe('useSettingsUpdater', () => { setConversationSettings(updatedValues.conversations); setConversationsSettingsBulkActions({}); - setPromptsBulkActions(updatedValues.allSystemPrompts); + setPromptsBulkActions({}); setUpdatedAnonymizationData(updatedValues.updatedAnonymizationData); setUpdatedKnowledgeBaseSettings(updatedValues.knowledgeBase); setUpdatedAssistantStreamingEnabled(updatedValues.assistantStreamingEnabled); @@ -149,7 +157,17 @@ describe('useSettingsUpdater', () => { it('should update all state variables to their updated values when saveSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) + useSettingsUpdater( + mockConversations, + { + data: mockSystemPrompts, + page: 1, + perPage: 100, + total: 10, + }, + conversationsLoaded, + anonymizationFields + ) ); await waitForNextUpdate(); const { @@ -163,7 +181,7 @@ describe('useSettingsUpdater', () => { setConversationSettings(updatedValues.conversations); setConversationsSettingsBulkActions({ delete: { ids: ['1'] } }); setAnonymizationFieldsBulkActions({ delete: { ids: ['1'] } }); - setPromptsBulkActions(updatedValues.allSystemPrompts); + setPromptsBulkActions({}); setUpdatedAnonymizationData(updatedValues.updatedAnonymizationData); setUpdatedKnowledgeBaseSettings(updatedValues.knowledgeBase); @@ -188,7 +206,17 @@ describe('useSettingsUpdater', () => { it('should track which toggles have been updated when saveSettings is called', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) + useSettingsUpdater( + mockConversations, + { + data: mockSystemPrompts, + page: 1, + perPage: 100, + total: 10, + }, + conversationsLoaded, + anonymizationFields + ) ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; @@ -205,7 +233,17 @@ describe('useSettingsUpdater', () => { it('should track only toggles that updated', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) + useSettingsUpdater( + mockConversations, + { + data: mockSystemPrompts, + page: 1, + perPage: 100, + total: 10, + }, + conversationsLoaded, + anonymizationFields + ) ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; @@ -223,7 +261,17 @@ describe('useSettingsUpdater', () => { it('if no toggles update, do not track anything', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => - useSettingsUpdater(mockConversations, conversationsLoaded, anonymizationFields) + useSettingsUpdater( + mockConversations, + { + data: mockSystemPrompts, + page: 1, + perPage: 100, + total: 10, + }, + conversationsLoaded, + anonymizationFields + ) ); await waitForNextUpdate(); const { setUpdatedKnowledgeBaseSettings } = result.current; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx index a73fbf4854ef1..f0e9e3d9b99c6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { Prompt } from '../../../..'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { DEFAULT_SYSTEM_PROMPT_LABEL, DEFAULT_SYSTEM_PROMPT_NAME, @@ -18,19 +18,19 @@ import { /** * Base System Prompts for Elastic AI Assistant (if not overridden on initialization). */ -export const BASE_SYSTEM_PROMPTS: Prompt[] = [ +export const BASE_SYSTEM_PROMPTS: PromptResponse[] = [ { id: 'default-system-prompt', content: DEFAULT_SYSTEM_PROMPT_NON_I18N, name: DEFAULT_SYSTEM_PROMPT_NAME, promptType: 'system', - label: DEFAULT_SYSTEM_PROMPT_LABEL, + // label: DEFAULT_SYSTEM_PROMPT_LABEL, }, { id: 'CB9FA555-B59F-4F71-AFF9-8A891AC5BC28', content: SUPERHERO_SYSTEM_PROMPT_NON_I18N, name: SUPERHERO_SYSTEM_PROMPT_NAME, promptType: 'system', - label: SUPERHERO_SYSTEM_PROMPT_LABEL, + // label: SUPERHERO_SYSTEM_PROMPT_LABEL, }, ]; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts b/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts index 5bc23b0d680e3..e0f326f4e4f38 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { Prompt } from '../../assistant/types'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; -export const mockUserPrompt: Prompt = { +export const mockUserPrompt: PromptResponse = { id: 'mock-user-prompt-1', content: `Explain the meaning from the context above, then summarize a list of suggested Elasticsearch KQL and EQL queries. Finally, suggest an investigation guide, and format it as markdown.`, name: 'Mock user prompt', - promptType: 'user', + promptType: 'quick', }; From 45c33e8d8ebd539491dfb60712c68251410381a3 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 13:57:34 -0700 Subject: [PATCH 07/22] fixed delete --- .../system_prompt_selector.test.tsx | 4 +- .../system_prompt_selector.tsx | 6 ++- .../quick_prompt_selector.tsx | 6 ++- .../quick_prompt_editor.tsx | 52 ++++++++++++++++--- .../use_quick_prompt_editor.test.tsx | 2 +- .../use_quick_prompt_editor.tsx | 12 +++-- .../index.tsx | 2 +- 7 files changed, 67 insertions(+), 17 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx index 45f320528ec64..cbf5efe79213f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx @@ -35,7 +35,7 @@ describe('SystemPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete system prompt because there is only one custom option fireEvent.click(getAllByTestId('delete-prompt')[1]); - expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[1].name); + expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[1].id); expect(onSystemPromptSelectionChange).not.toHaveBeenCalled(); }); it('Deletes a system prompt that is selected', () => { @@ -43,7 +43,7 @@ describe('SystemPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete system prompt because there is only one custom option fireEvent.click(getAllByTestId('delete-prompt')[0]); - expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[0].name); + expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[0].id); expect(onSystemPromptSelectionChange).toHaveBeenCalledWith(undefined); }); it('Selects existing system prompt from the search input', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx index 4c67a475484c4..455f6128ef928 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx @@ -59,6 +59,7 @@ export const SystemPromptSelector: React.FC = React.memo( isNewConversationDefault: sp.isNewConversationDefault ?? false, }, label: sp.name, + id: sp.id, 'data-test-subj': `${TEST_IDS.SYSTEM_PROMPT_SELECTOR}-${sp.id}`, })) ); @@ -70,6 +71,7 @@ export const SystemPromptSelector: React.FC = React.memo( isDefault: selectedSystemPrompt.isDefault ?? false, isNewConversationDefault: selectedSystemPrompt.isNewConversationDefault ?? false, }, + id: selectedSystemPrompt.id, label: selectedSystemPrompt.name, }, ] @@ -106,6 +108,7 @@ export const SystemPromptSelector: React.FC = React.memo( const newOption = { value: searchValue, + id: searchValue, label: searchValue, }; @@ -132,11 +135,12 @@ export const SystemPromptSelector: React.FC = React.memo( // Callback for when user deletes a quick prompt const onDelete = useCallback( (label: string) => { + const deleteId = options.find((o) => o.label !== label)?.id; setOptions(options.filter((o) => o.label !== label)); if (selectedOptions?.[0]?.label === label) { handleSelectionChange([]); } - onSystemPromptDeleted(label); + onSystemPromptDeleted(deleteId ?? label); }, [handleSelectionChange, onSystemPromptDeleted, options, selectedOptions] ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx index 38d14e2cae8ba..89edd5e3ffbfd 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx @@ -52,6 +52,7 @@ export const QuickPromptSelector: React.FC = React.memo( }, label: qp.name, 'data-test-subj': qp.name, + id: qp.id, color: qp.color, })) ); @@ -63,6 +64,7 @@ export const QuickPromptSelector: React.FC = React.memo( isDefault: true, }, label: selectedQuickPrompt.name, + id: selectedQuickPrompt.id, color: selectedQuickPrompt.color, }, ] @@ -100,6 +102,7 @@ export const QuickPromptSelector: React.FC = React.memo( const newOption = { value: searchValue, label: searchValue, + id: searchValue, }; if (!optionExists) { @@ -125,11 +128,12 @@ export const QuickPromptSelector: React.FC = React.memo( // Callback for when user deletes a quick prompt const onDelete = useCallback( (label: string) => { + const deleteId = options.find((o) => o.label !== label)?.id; setOptions(options.filter((o) => o.label !== label)); if (selectedOptions?.[0]?.label === label) { handleSelectionChange([]); } - onQuickPromptDeleted(label); + onQuickPromptDeleted(deleteId ?? label); }, [handleSelectionChange, onQuickPromptDeleted, options, selectedOptions] ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx index 428761ae73907..51a7558f65a77 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx @@ -45,21 +45,21 @@ const QuickPromptSettingsEditorComponent = ({ const { basePromptContexts } = useAssistantContext(); // Prompt - const prompt = useMemo( + const promptContent = useMemo( // Fixing Cursor Jump in text area - () => quickPromptSettings.find((p) => p.name === selectedQuickPrompt?.name)?.content ?? '', - [selectedQuickPrompt?.name, quickPromptSettings] + () => quickPromptSettings.find((p) => p.id === selectedQuickPrompt?.id)?.content ?? '', + [selectedQuickPrompt?.id, quickPromptSettings] ); const handlePromptChange = useCallback( (e: React.ChangeEvent) => { if (selectedQuickPrompt != null) { - setUpdatedQuickPromptSettings((prev) => { - const alreadyExists = prev.some((qp) => qp.name === selectedQuickPrompt.name); + setUpdatedQuickPromptSettings((prev): PromptResponse[] => { + const alreadyExists = prev.some((qp) => qp.id === selectedQuickPrompt.id); if (alreadyExists) { return prev.map((qp) => { - if (qp.name === selectedQuickPrompt.name) { + if (qp.id === selectedQuickPrompt.id) { return { ...qp, prompt: e.target.value, @@ -71,9 +71,45 @@ const QuickPromptSettingsEditorComponent = ({ return prev; }); + + const existingPrompt = quickPromptSettings.find((sp) => sp.id === selectedQuickPrompt.id); + if (existingPrompt) { + setPromptsBulkActions({ + ...promptsBulkActions, + ...(selectedQuickPrompt.name !== selectedQuickPrompt.id + ? { + update: [ + ...(promptsBulkActions.update ?? []).filter( + (p) => p.id !== selectedQuickPrompt.id + ), + { + ...selectedQuickPrompt, + content: e.target.value, + }, + ], + } + : { + create: [ + ...(promptsBulkActions.create ?? []).filter( + (p) => p.name !== selectedQuickPrompt.name + ), + { + ...selectedQuickPrompt, + content: e.target.value, + }, + ], + }), + }); + } } }, - [selectedQuickPrompt, setUpdatedQuickPromptSettings] + [ + promptsBulkActions, + quickPromptSettings, + selectedQuickPrompt, + setPromptsBulkActions, + setUpdatedQuickPromptSettings, + ] ); // Color @@ -167,7 +203,7 @@ const QuickPromptSettingsEditorComponent = ({ data-test-subj="quick-prompt-prompt" onChange={handlePromptChange} placeholder={i18n.QUICK_PROMPT_PROMPT_PLACEHOLDER} - value={prompt} + value={promptContent} css={css` min-height: 150px; `} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx index 7f130a201443b..88b9dd5d1db4c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx @@ -86,7 +86,7 @@ describe('useQuickPromptEditor', () => { const expectedPrompt: PromptResponse = { name: mockAlertPromptContext.description, - content: alertData.content ?? '', + content: JSON.stringify(alertData ?? {}), color: DEFAULT_COLOR, categories: [mockAlertPromptContext.category], id: '', diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx index d4918faef0e45..d96c4fca716d1 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.tsx @@ -28,10 +28,16 @@ export const useQuickPromptEditor = ({ }) => { const { currentAppId } = useAssistantContext(); const onQuickPromptDeleted = useCallback( - (title: string) => { - setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.name !== title)); + (id: string) => { + setUpdatedQuickPromptSettings((prev) => prev.filter((qp) => qp.id !== id)); + setPromptsBulkActions({ + ...promptsBulkActions, + delete: { + ids: [...(promptsBulkActions.delete?.ids ?? []), id], + }, + }); }, - [setUpdatedQuickPromptSettings] + [promptsBulkActions, setPromptsBulkActions, setUpdatedQuickPromptSettings] ); // When top level quick prompt selection changes diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx index fea6264b72a9a..ac93161d35c17 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/index.tsx @@ -83,7 +83,7 @@ const QuickPromptSettingsManagementComponent = ({ const onDeleteActionClicked = useCallback( (prompt: PromptResponse) => { setDeletedQuickPrompt(prompt); - onQuickPromptDeleted(prompt.name); + onQuickPromptDeleted(prompt.id); openConfirmModal(); }, [onQuickPromptDeleted, openConfirmModal] From cb8d7fc46339832dcc239a953df6254022ea80eb Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 14:23:28 -0700 Subject: [PATCH 08/22] fixed types --- .../api/prompts/bulk_update_prompts.test.ts | 12 +++++--- .../assistant/assistant_header/index.test.tsx | 1 + .../conversation_selector/index.test.tsx | 1 + .../use_conversation_changed.tsx | 5 ++-- .../index.tsx | 4 +-- .../use_conversations_table.tsx | 10 +++---- .../impl/assistant/index.tsx | 7 +---- .../assistant/prompt_editor/helpers.test.tsx | 4 +-- .../assistant/prompt_editor/index.test.tsx | 1 + .../system_prompt_settings.test.tsx | 2 ++ .../system_prompt_modal/types.ts | 15 ++++++---- .../use_system_prompt_editor.test.tsx | 17 ++++++++--- .../quick_prompts/quick_prompts.test.tsx | 2 +- .../assistant/quick_prompts/quick_prompts.tsx | 9 +++--- .../use_conversation/helpers.test.ts | 25 ++++++++-------- .../assistant/use_conversation/helpers.ts | 8 ++--- .../impl/assistant/use_conversation/index.tsx | 8 +++-- .../server/__mocks__/prompts_schema.mock.ts | 30 ++++++++++++------- 18 files changed, 95 insertions(+), 66 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts index 8a676d35465e4..3159f1bc69a91 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts @@ -12,16 +12,20 @@ import { import { httpServiceMock } from '@kbn/core-http-browser-mocks'; import { IToasts } from '@kbn/core-notifications-browser'; import { bulkUpdatePrompts } from './bulk_update_prompts'; +import { PromptTypeEnum } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; const prompt1 = { id: 'field1', - field: 'Prompt field 1', - allowed: true, + content: 'Prompt field 1', + name: 'test', + promptType: PromptTypeEnum.system, }; const prompt2 = { ...prompt1, id: 'field2', - field: 'field 2', + content: 'Prompt field 2', + name: 'test2', + promptType: PromptTypeEnum.system, }; const toasts = { addError: jest.fn(), @@ -100,7 +104,7 @@ describe('bulkUpdatePrompts', () => { { statusCode: 400, message: 'Error updating prompt', - prompts: [{ id: prompt1.id, name: prompt1.field }], + prompts: [{ id: prompt1.id, name: prompt1.content }], }, ], }, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx index 2301078d57ba1..f806f5d1ef7c6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx @@ -38,6 +38,7 @@ const testProps = { refetchConversationsState: jest.fn(), anonymizationFields: { total: 0, page: 1, perPage: 1000, data: [] }, refetchAnonymizationFieldsResults: jest.fn(), + allPrompts: [], }; jest.mock('../../connectorland/use_load_connectors', () => ({ diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.test.tsx index 6c2ae3b6af211..613163db196ae 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_selector/index.test.tsx @@ -50,6 +50,7 @@ const defaultProps = { defaultProvider: OpenAiProviderType.OpenAi, conversations: mockConversations, onConversationDeleted, + allPrompts: [], }; describe('Conversation selector', () => { beforeAll(() => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx index 670832ac83798..6ed8037327781 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx @@ -6,13 +6,14 @@ */ import { useCallback, useMemo } from 'react'; -import { Conversation, Prompt } from '../../../..'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { Conversation } from '../../../..'; import { getDefaultSystemPrompt } from '../../use_conversation/helpers'; import { ConversationsBulkActions } from '../../api'; import { AIConnector } from '../../../connectorland/connector_selector'; interface Props { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; defaultConnector?: AIConnector; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx index c4b2f834ecec5..0a754fcd50d03 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx @@ -8,13 +8,13 @@ import { EuiPanel, EuiSpacer, EuiConfirmModal, EuiInMemoryTable } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation } from '../../../assistant_context/types'; import { ConversationTableItem, useConversationsTable } from './use_conversations_table'; import { ConversationStreamingSwitch } from '../conversation_settings/conversation_streaming_switch'; import { AIConnector } from '../../../connectorland/connector_selector'; import * as i18n from './translations'; -import { Prompt } from '../../types'; import { ConversationsBulkActions } from '../../api'; import { useAssistantContext } from '../../../assistant_context'; import { useConversationDeleted } from '../conversation_settings/use_conversation_deleted'; @@ -27,7 +27,7 @@ import { CONVERSATION_TABLE_SESSION_STORAGE_KEY } from '../../../assistant_conte import { useSessionPagination } from '../../common/components/assistant_settings_management/pagination/use_session_pagination'; import { DEFAULT_PAGE_SIZE } from '../../settings/const'; interface Props { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; assistantStreamingEnabled: boolean; connectors: AIConnector[] | undefined; conversationSettings: Record; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx index fb705db6bb33c..24744b0645388 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx @@ -11,10 +11,10 @@ import { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/publ import { EuiBadge, EuiBasicTableColumn, EuiLink } from '@elastic/eui'; import { FormattedDate } from '@kbn/i18n-react'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { Conversation } from '../../../assistant_context/types'; import { AIConnector } from '../../../connectorland/connector_selector'; import { getConnectorTypeTitle } from '../../../connectorland/helpers'; -import { Prompt } from '../../../..'; import { getConversationApiConfig, getInitialDefaultSystemPrompt, @@ -25,7 +25,7 @@ import { RowActions } from '../../common/components/assistant_settings_managemen const emptyConversations = {}; export interface GetConversationsListParams { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; actionTypeRegistry: ActionTypeRegistryContract; connectors: AIConnector[] | undefined; conversations: Record; @@ -126,7 +126,7 @@ export const useConversationsTable = () => { ); const connectorTypeTitle = getConnectorTypeTitle(connector, actionTypeRegistry); - const systemPrompt: Prompt | undefined = allSystemPrompts.find( + const systemPrompt: PromptResponse | undefined = allSystemPrompts.find( ({ id }) => id === conversation.apiConfig?.defaultSystemPromptId ); const defaultSystemPrompt = getInitialDefaultSystemPrompt({ @@ -135,9 +135,9 @@ export const useConversationsTable = () => { }); const systemPromptTitle = - systemPrompt?.label || + systemPrompt?.id || systemPrompt?.name || - defaultSystemPrompt?.label || + defaultSystemPrompt?.id || defaultSystemPrompt?.name; return { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx index 94671847c7ed4..4f33b3b480570 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx @@ -182,12 +182,7 @@ const AssistantComponent: React.FC = ({ isFetched: isFetchedAnonymizationFields, } = useFetchAnonymizationFields(); - const { - data: allPrompts, - isLoading: isLoadingPrompts, - isError: isErrorPrompts, - isFetched: isFetchedPrompts, - } = useFetchPrompts(); + const { data: allPrompts } = useFetchPrompts(); // Connector details const { data: connectors, isFetchedAfterMount: areConnectorsFetched } = useLoadConnectors({ diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx index c055d9bd6bb95..edd3615314846 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx @@ -7,11 +7,11 @@ import { getPromptById } from './helpers'; import { mockSystemPrompt, mockSuperheroSystemPrompt } from '../../mock/system_prompt'; -import type { Prompt } from '../types'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; describe('helpers', () => { describe('getPromptById', () => { - const prompts: Prompt[] = [mockSystemPrompt, mockSuperheroSystemPrompt]; + const prompts: PromptResponse[] = [mockSystemPrompt, mockSuperheroSystemPrompt]; it('returns the correct prompt by id', () => { const result = getPromptById({ prompts, id: mockSuperheroSystemPrompt.id }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.test.tsx index 6a18b9794c597..6d421b649a380 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.test.tsx @@ -40,6 +40,7 @@ const defaultProps: Props = { setIsSettingsModalVisible: jest.fn(), setSelectedPromptContexts: jest.fn(), isFlyoutMode: false, + allSystemPrompts: [], }; describe('PromptEditorComponent', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx index be9e33f615e4b..f62dee170e2bb 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx @@ -36,6 +36,8 @@ const testProps = { systemPromptSettings: mockSystemPrompts, conversationsSettingsBulkActions: {}, setConversationsSettingsBulkActions: jest.fn(), + promptsBulkActions: {}, + setPromptsBulkActions: jest.fn(), }; jest.mock('./system_prompt_selector/system_prompt_selector', () => ({ diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts index a311b99e2b7a0..e92961cb1763f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/types.ts @@ -4,20 +4,23 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { + PromptResponse, + PerformBulkActionRequestBody as PromptsPerformBulkActionRequestBody, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { AIConnector } from '../../../../connectorland/connector_selector'; -import { Conversation, Prompt } from '../../../../..'; +import { Conversation } from '../../../../..'; import { ConversationsBulkActions } from '../../../api'; export interface SystemPromptSettingsProps { connectors: AIConnector[] | undefined; conversationSettings: Record; conversationsSettingsBulkActions: ConversationsBulkActions; - onSelectedSystemPromptChange: (systemPrompt?: Prompt) => void; - selectedSystemPrompt: Prompt | undefined; - setUpdatedSystemPromptSettings: React.Dispatch>; + onSelectedSystemPromptChange: (systemPrompt?: PromptResponse) => void; + selectedSystemPrompt: PromptResponse | undefined; + setUpdatedSystemPromptSettings: React.Dispatch>; setConversationSettings: React.Dispatch>>; - systemPromptSettings: Prompt[]; + systemPromptSettings: PromptResponse[]; setConversationsSettingsBulkActions: React.Dispatch< React.SetStateAction >; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx index 85efe99979650..eafbe0349ac9d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx @@ -6,16 +6,17 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; import { useSystemPromptEditor } from './use_system_prompt_editor'; -import { Prompt } from '../../../types'; import { mockSystemPrompt, mockSuperheroSystemPrompt, mockSystemPrompts, } from '../../../../mock/system_prompt'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; // Mock functions for the tests const mockOnSelectedSystemPromptChange = jest.fn(); const mockSetUpdatedSystemPromptSettings = jest.fn(); +const mockSetPromptsBulkActions = jest.fn(); const mockPreviousSystemPrompts = [...mockSystemPrompts]; describe('useSystemPromptEditor', () => { @@ -28,6 +29,8 @@ describe('useSystemPromptEditor', () => { useSystemPromptEditor({ onSelectedSystemPromptChange: mockOnSelectedSystemPromptChange, setUpdatedSystemPromptSettings: mockSetUpdatedSystemPromptSettings, + setPromptsBulkActions: mockSetPromptsBulkActions, + promptsBulkActions: {}, }) ); @@ -41,11 +44,13 @@ describe('useSystemPromptEditor', () => { }); test('should handle selection of an existing system prompt', () => { - const existingPrompt: Prompt = mockSystemPrompt; + const existingPrompt: PromptResponse = mockSystemPrompt; const { result } = renderHook(() => useSystemPromptEditor({ onSelectedSystemPromptChange: mockOnSelectedSystemPromptChange, setUpdatedSystemPromptSettings: mockSetUpdatedSystemPromptSettings, + setPromptsBulkActions: mockSetPromptsBulkActions, + promptsBulkActions: {}, }) ); @@ -65,6 +70,8 @@ describe('useSystemPromptEditor', () => { useSystemPromptEditor({ onSelectedSystemPromptChange: mockOnSelectedSystemPromptChange, setUpdatedSystemPromptSettings: mockSetUpdatedSystemPromptSettings, + setPromptsBulkActions: mockSetPromptsBulkActions, + promptsBulkActions: {}, }) ); @@ -72,7 +79,7 @@ describe('useSystemPromptEditor', () => { result.current.onSystemPromptSelectionChange(newPromptId); }); - const newPrompt: Prompt = { + const newPrompt: PromptResponse = { id: newPromptId, content: '', name: newPromptId, @@ -90,10 +97,12 @@ describe('useSystemPromptEditor', () => { useSystemPromptEditor({ onSelectedSystemPromptChange: mockOnSelectedSystemPromptChange, setUpdatedSystemPromptSettings: mockSetUpdatedSystemPromptSettings, + setPromptsBulkActions: mockSetPromptsBulkActions, + promptsBulkActions: {}, }) ); - const expectedPrompt: Prompt = mockSuperheroSystemPrompt; + const expectedPrompt: PromptResponse = mockSuperheroSystemPrompt; act(() => { result.current.onSystemPromptSelectionChange(expectedPrompt); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx index a7de474bf396c..6e5172dc0c2ad 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.test.tsx @@ -7,10 +7,10 @@ import React from 'react'; import { fireEvent, render } from '@testing-library/react'; -import { QuickPrompts } from './quick_prompts'; import { TestProviders } from '../../mock/test_providers/test_providers'; import { MOCK_QUICK_PROMPTS } from '../../mock/quick_prompt'; import { QUICK_PROMPTS_TAB } from '../settings/const'; +import { QuickPrompts } from './quick_prompts'; const setInput = jest.fn(); const setIsSettingsModalVisible = jest.fn(); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx index c8659ba0310b8..c578a58be728d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompts.tsx @@ -21,7 +21,6 @@ import { PromptResponse, PromptTypeEnum, } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; -import { QuickPrompt } from '../../..'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; import { QUICK_PROMPTS_TAB } from '../settings/const'; @@ -79,10 +78,10 @@ export const QuickPrompts: React.FC = React.memo( const closeOverflowPopover = useCallback(() => setIsOverflowPopoverOpen(false), []); const onClickAddQuickPrompt = useCallback( - (badge: QuickPrompt) => { - setInput(badge.prompt); + (badge: PromptResponse) => { + setInput(badge.content); if (badge.isDefault) { - trackPrompt(badge.title); + trackPrompt(badge.name); } else { trackPrompt('Custom'); } @@ -91,7 +90,7 @@ export const QuickPrompts: React.FC = React.memo( ); const onClickOverflowQuickPrompt = useCallback( - (badge: QuickPrompt) => { + (badge: PromptResponse) => { onClickAddQuickPrompt(badge); closeOverflowPopover(); }, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts index c8c8ab5ff7727..6e96270b827ed 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts @@ -13,7 +13,8 @@ import { getDefaultSystemPrompt, } from './helpers'; import { AIConnector } from '../../connectorland/connector_selector'; -import { Conversation, Prompt } from '../../..'; +import { Conversation } from '../../..'; +import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; const tilde = '`'; const codeDelimiter = '```'; @@ -61,28 +62,28 @@ ${codeDelimiter} This query will filter the events based on the condition that the ${tilde}user.name${tilde} field should exactly match the value \"9dcc9960-78cf-4ef6-9a2e-dbd5816daa60\".`; describe('useConversation helpers', () => { - const allSystemPrompts: Prompt[] = [ + const allSystemPrompts: PromptResponse[] = [ { id: '1', content: 'Prompt 1', name: 'Prompt 1', - promptType: 'user', + promptType: 'quick', }, { id: '2', content: 'Prompt 2', name: 'Prompt 2', - promptType: 'user', + promptType: 'quick', isNewConversationDefault: true, }, { id: '3', content: 'Prompt 3', name: 'Prompt 3', - promptType: 'user', + promptType: 'quick', }, ]; - const allSystemPromptsNoDefault: Prompt[] = allSystemPrompts.filter( + const allSystemPromptsNoDefault: PromptResponse[] = allSystemPrompts.filter( ({ isNewConversationDefault }) => isNewConversationDefault !== true ); @@ -237,25 +238,25 @@ describe('useConversation helpers', () => { }); describe('getConversationApiConfig', () => { - const allSystemPrompts: Prompt[] = [ + const allSystemPrompts: PromptResponse[] = [ { id: '1', content: 'Prompt 1', name: 'Prompt 1', - promptType: 'user', + promptType: 'quick', }, { id: '2', content: 'Prompt 2', name: 'Prompt 2', - promptType: 'user', + promptType: 'quick', isNewConversationDefault: true, }, { id: '3', content: 'Prompt 3', name: 'Prompt 3', - promptType: 'user', + promptType: 'quick', }, ]; @@ -390,7 +391,7 @@ describe('getConversationApiConfig', () => { }); test('should return the first system prompt if both conversation system prompt and default new system prompt do not exist', () => { - const allSystemPromptsNoDefault: Prompt[] = allSystemPrompts.filter( + const allSystemPromptsNoDefault: PromptResponse[] = allSystemPrompts.filter( ({ isNewConversationDefault }) => isNewConversationDefault !== true ); @@ -418,7 +419,7 @@ describe('getConversationApiConfig', () => { }); test('should return the first system prompt if conversation system prompt does not exist within all system prompts', () => { - const allSystemPromptsNoDefault: Prompt[] = allSystemPrompts.filter( + const allSystemPromptsNoDefault: PromptResponse[] = allSystemPrompts.filter( ({ isNewConversationDefault }) => isNewConversationDefault !== true ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts index 57ef1fa668034..31da9e30ae535 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts @@ -75,7 +75,7 @@ export const analyzeMarkdown = (markdown: string): CodeBlockDetails[] => { * * @param allSystemPrompts All available System Prompts */ -export const getDefaultNewSystemPrompt = (allSystemPrompts: Prompt[]) => +export const getDefaultNewSystemPrompt = (allSystemPrompts: PromptResponse[]) => allSystemPrompts.find((prompt) => prompt.isNewConversationDefault) ?? allSystemPrompts?.[0]; /** @@ -109,9 +109,9 @@ export const getInitialDefaultSystemPrompt = ({ allSystemPrompts, conversation, }: { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; conversation: Conversation | undefined; -}): Prompt | undefined => { +}): PromptResponse | undefined => { const conversationSystemPrompt = allSystemPrompts.find( (prompt) => prompt.id === conversation?.apiConfig?.defaultSystemPromptId ); @@ -133,7 +133,7 @@ export const getConversationApiConfig = ({ connectors, defaultConnector, }: { - allSystemPrompts: Prompt[]; + allSystemPrompts: PromptResponse[]; conversation: Conversation; connectors?: AIConnector[]; defaultConnector?: AIConnector; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx index 84fa21417ae70..5906d28a76aa7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx @@ -18,6 +18,7 @@ import { updateConversation, } from '../api/conversations'; import { WELCOME_CONVERSATION } from './sample_conversations'; +import { useFetchPrompts } from '../api/prompts/use_fetch_prompts'; export const DEFAULT_CONVERSATION_STATE: Conversation = { id: '', @@ -63,7 +64,8 @@ interface UseConversation { } export const useConversation = (): UseConversation => { - const { allSystemPrompts, http, toasts } = useAssistantContext(); + const { http, toasts } = useAssistantContext(); + const { data: allPrompts } = useFetchPrompts(); const getConversation = useCallback( async (conversationId: string, silent?: boolean) => { @@ -101,7 +103,7 @@ export const useConversation = (): UseConversation => { async (conversation: Conversation) => { if (conversation.apiConfig) { const defaultSystemPromptId = getDefaultSystemPrompt({ - allSystemPrompts, + allSystemPrompts: allPrompts.data, conversation, })?.id; @@ -115,7 +117,7 @@ export const useConversation = (): UseConversation => { }); } }, - [allSystemPrompts, http, toasts] + [allPrompts.data, http, toasts] ); /** diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/prompts_schema.mock.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/prompts_schema.mock.ts index 404ff5954c004..adbe299c33993 100644 --- a/x-pack/plugins/elastic_assistant/server/__mocks__/prompts_schema.mock.ts +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/prompts_schema.mock.ts @@ -42,8 +42,10 @@ export const getPromptsSearchEsMock = () => { id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', content: 'test content', name: 'test', - prompt_type: 'quickPrompt', - is_shared: false, + prompt_type: 'quick', + consumer: 'securitySolutionUI', + categories: [], + color: 'red', created_by: 'elastic', users: [ { @@ -62,15 +64,19 @@ export const getCreatePromptSchemaMock = (): PromptCreateProps => ({ name: 'test', content: 'test content', isNewConversationDefault: false, - isShared: true, + consumer: 'securitySolutionUI', + categories: [], + color: 'red', isDefault: false, - promptType: 'quickPrompt', + promptType: 'quick', }); export const getUpdatePromptSchemaMock = (promptId = 'prompt-1'): PromptUpdateProps => ({ content: 'test content', isNewConversationDefault: false, - isShared: true, + consumer: 'securitySolutionUI', + categories: [], + color: 'red', isDefault: false, id: promptId, }); @@ -79,7 +85,7 @@ export const getPromptMock = (params: PromptCreateProps | PromptUpdateProps): Pr id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', content: 'test content', name: 'test', - promptType: 'quickPrompt', + promptType: 'quick', isDefault: false, ...params, createdAt: '2019-12-13T16:40:33.400Z', @@ -97,19 +103,23 @@ export const getQueryPromptParams = (isUpdate?: boolean): PromptCreateProps | Pr ? { content: 'test 2', name: 'test', - promptType: 'quickPrompt', + promptType: 'quick', isDefault: false, isNewConversationDefault: true, - isShared: true, + consumer: 'securitySolutionUI', + categories: [], + color: 'red', id: '1', } : { content: 'test 2', name: 'test', - promptType: 'quickPrompt', + promptType: 'quick', isDefault: false, isNewConversationDefault: true, - isShared: true, + consumer: 'securitySolutionUI', + categories: [], + color: 'red', }; }; From 2c6c32c6fe0ac818c0b59e1229b3fca9edae0d17 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:16:12 +0000 Subject: [PATCH 09/22] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../kbn-elastic-assistant/impl/content/prompts/system/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx index f0e9e3d9b99c6..6fff9ae742536 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx @@ -7,10 +7,8 @@ import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { - DEFAULT_SYSTEM_PROMPT_LABEL, DEFAULT_SYSTEM_PROMPT_NAME, DEFAULT_SYSTEM_PROMPT_NON_I18N, - SUPERHERO_SYSTEM_PROMPT_LABEL, SUPERHERO_SYSTEM_PROMPT_NAME, SUPERHERO_SYSTEM_PROMPT_NON_I18N, } from './translations'; From a71e190556cdc77e88a91d87f8d3f597d2953a97 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 16:42:26 -0700 Subject: [PATCH 10/22] fixed prompts update --- .../quick_prompt_editor.tsx | 77 ++++++++++++++++++- .../use_settings_updater.tsx | 4 +- .../prompts/helpers.ts | 7 +- 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx index 51a7558f65a77..01ffe00d11100 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_editor.tsx @@ -62,7 +62,7 @@ const QuickPromptSettingsEditorComponent = ({ if (qp.id === selectedQuickPrompt.id) { return { ...qp, - prompt: e.target.value, + content: e.target.value, }; } return qp; @@ -137,9 +137,44 @@ const QuickPromptSettingsEditorComponent = ({ } return prev; }); + const existingPrompt = quickPromptSettings.find((sp) => sp.id === selectedQuickPrompt.id); + if (existingPrompt) { + setPromptsBulkActions({ + ...promptsBulkActions, + ...(selectedQuickPrompt.name !== selectedQuickPrompt.id + ? { + update: [ + ...(promptsBulkActions.update ?? []).filter( + (p) => p.id !== selectedQuickPrompt.id + ), + { + ...selectedQuickPrompt, + color, + }, + ], + } + : { + create: [ + ...(promptsBulkActions.create ?? []).filter( + (p) => p.name !== selectedQuickPrompt.name + ), + { + ...selectedQuickPrompt, + color, + }, + ], + }), + }); + } } }, - [selectedQuickPrompt, setUpdatedQuickPromptSettings] + [ + promptsBulkActions, + quickPromptSettings, + selectedQuickPrompt, + setPromptsBulkActions, + setUpdatedQuickPromptSettings, + ] ); // Prompt Contexts @@ -170,9 +205,45 @@ const QuickPromptSettingsEditorComponent = ({ } return prev; }); + + const existingPrompt = quickPromptSettings.find((sp) => sp.id === selectedQuickPrompt.id); + if (existingPrompt) { + setPromptsBulkActions({ + ...promptsBulkActions, + ...(selectedQuickPrompt.name !== selectedQuickPrompt.id + ? { + update: [ + ...(promptsBulkActions.update ?? []).filter( + (p) => p.id !== selectedQuickPrompt.id + ), + { + ...selectedQuickPrompt, + categories: pc.map((p) => p.category), + }, + ], + } + : { + create: [ + ...(promptsBulkActions.create ?? []).filter( + (p) => p.name !== selectedQuickPrompt.name + ), + { + ...selectedQuickPrompt, + categories: pc.map((p) => p.category), + }, + ], + }), + }); + } } }, - [selectedQuickPrompt, setUpdatedQuickPromptSettings] + [ + promptsBulkActions, + quickPromptSettings, + selectedQuickPrompt, + setPromptsBulkActions, + setUpdatedQuickPromptSettings, + ] ); // When top level quick prompt selection changes diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx index 61f95f557b1a3..e9f65160e6d29 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx @@ -112,7 +112,9 @@ export const useSettingsUpdater = ( ); setUpdatedKnowledgeBaseSettings(knowledgeBase); setUpdatedAssistantStreamingEnabled(assistantStreamingEnabled); - setUpdatedSystemPromptSettings(allSystemPrompts.data); + setUpdatedSystemPromptSettings( + allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.system) + ); setUpdatedAnonymizationData(anonymizationFields); }, [ allSystemPrompts, diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts index 5e9b00aaa3e69..a4534972c8478 100644 --- a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/prompts/helpers.ts @@ -150,8 +150,11 @@ export const getUpdateScript = ({ if (params.assignEmpty == true || params.containsKey('is_new_conversation_default')) { ctx._source.is_new_conversation_default = params.is_new_conversation_default; } - if (params.assignEmpty == true || params.containsKey('is_shared')) { - ctx._source.is_shared = params.is_shared; + if (params.assignEmpty == true || params.containsKey('color')) { + ctx._source.color = params.color; + } + if (params.assignEmpty == true || params.containsKey('categories')) { + ctx._source.categories = params.categories; } ctx._source.updated_at = params.updated_at; `, From 9ae6ee8156e1c9f20c119321d03fca7843d5f47c Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Mon, 1 Jul 2024 21:59:38 -0700 Subject: [PATCH 11/22] added default conversations --- .../impl/assistant/api/index.tsx | 1 + .../api/prompts/bulk_update_prompts.test.ts | 6 +- .../impl/assistant/api/prompts/index.tsx | 9 +++ .../api/prompts/use_fetch_prompts.test.tsx | 1 + .../api/prompts/use_fetch_prompts.ts | 27 +++++++++ .../use_conversations_table.tsx | 6 +- .../system_prompt/helpers.test.tsx | 8 +-- .../prompt_editor/system_prompt/helpers.tsx | 29 +++++++++- .../select_system_prompt/index.test.tsx | 25 +++++++++ .../system_prompt_selector.test.tsx | 4 +- .../system_prompt_settings.test.tsx | 1 + .../use_system_prompt_editor.test.tsx | 6 ++ .../quick_prompt_selector.test.tsx | 8 ++- .../quick_prompt_settings.test.tsx | 9 ++- .../use_quick_prompt_editor.test.tsx | 8 ++- .../impl/assistant/quick_prompts/types.tsx | 25 --------- .../use_settings_updater.test.tsx | 30 +++++----- .../impl/content/prompts/system/index.tsx | 34 ----------- .../impl/content/prompts/user/translations.ts | 26 --------- .../impl/mock/system_prompt/index.ts | 13 +++++ .../packages/kbn-elastic-assistant/index.ts | 14 +---- .../mock/test_providers/test_providers.tsx | 1 + .../prompts/field_maps_configuration.ts | 4 +- .../content/prompts/system/index.tsx | 6 +- .../assistant/content/quick_prompts/index.tsx | 56 +++++++++++++------ .../public/assistant/provider.tsx | 41 ++++++++++++++ 26 files changed, 243 insertions(+), 155 deletions(-) create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/index.tsx delete mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/types.tsx delete mode 100644 x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx delete mode 100644 x-pack/packages/kbn-elastic-assistant/impl/content/prompts/user/translations.ts diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx index b8c42a787621b..8b6bba33f680a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx @@ -11,6 +11,7 @@ import { API_ERROR } from '../translations'; import { getOptionalRequestParams } from '../helpers'; import { TraceOptions } from '../types'; export * from './conversations'; +export * from './prompts'; export interface FetchConnectorExecuteAction { conversationId: string; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts index 3159f1bc69a91..d6ba2e726a76f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/bulk_update_prompts.test.ts @@ -16,14 +16,14 @@ import { PromptTypeEnum } from '@kbn/elastic-assistant-common/impl/schemas/promp const prompt1 = { id: 'field1', - content: 'Prompt field 1', + content: 'Prompt 1', name: 'test', promptType: PromptTypeEnum.system, }; const prompt2 = { ...prompt1, id: 'field2', - content: 'Prompt field 2', + content: 'Prompt 2', name: 'test2', promptType: PromptTypeEnum.system, }; @@ -116,7 +116,7 @@ describe('bulkUpdatePrompts', () => { }; await bulkUpdatePrompts(httpMock, promptsActions, toasts as unknown as IToasts); expect(toasts.addError.mock.calls[0][0]).toEqual( - new Error('Error message: Error updating prompt for Prompt 1') + new Error('Error message: Error updating prompt for prompt Prompt 1') ); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/index.tsx new file mode 100644 index 0000000000000..5a2f6bb80992b --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/index.tsx @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export * from './bulk_update_prompts'; +export * from './use_fetch_prompts'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx index 78c45a3329dfa..3ec1586d6cb44 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx @@ -49,6 +49,7 @@ describe('useFetchPrompts', () => { query: { page: 1, per_page: 1000, + filter: 'consumer:*', }, version: API_VERSIONS.internal.v1, signal: undefined, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts index 74b646a8c8223..ffb876bb28aef 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts @@ -8,6 +8,8 @@ import { FindPromptsResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/find_prompts_route.gen'; import { useQuery } from '@tanstack/react-query'; import { API_VERSIONS, ELASTIC_AI_ASSISTANT_PROMPTS_URL_FIND } from '@kbn/elastic-assistant-common'; +import { HttpSetup, IToasts } from '@kbn/core/public'; +import { i18n } from '@kbn/i18n'; import { useAssistantContext } from '../../../assistant_context'; export interface UseFetchPromptsParams { @@ -72,3 +74,28 @@ export const useFetchPrompts = (payload?: UseFetchPromptsParams) => { } ); }; + +export const getPrompts = async ({ + http, + signal, + toasts, +}: { + http: HttpSetup; + toasts?: IToasts; + signal?: AbortSignal | undefined; +}) => { + try { + return await http.fetch(ELASTIC_AI_ASSISTANT_PROMPTS_URL_FIND, { + method: 'GET', + version: API_VERSIONS.internal.v1, + signal, + }); + } catch (error) { + toasts?.addError(error.body && error.body.message ? new Error(error.body.message) : error, { + title: i18n.translate('xpack.elasticAssistant.prompts.getPromptsError', { + defaultMessage: 'Error fetching prompts', + }), + }); + throw error; + } +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx index 24744b0645388..5f005875eb520 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx @@ -135,10 +135,10 @@ export const useConversationsTable = () => { }); const systemPromptTitle = - systemPrompt?.id || systemPrompt?.name || - defaultSystemPrompt?.id || - defaultSystemPrompt?.name; + systemPrompt?.id || + defaultSystemPrompt?.name || + defaultSystemPrompt?.id; return { ...conversation, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.test.tsx index 4a26b22b0b2d3..82b04c60a569c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.test.tsx @@ -16,13 +16,13 @@ import { getOptions, getOptionFromPrompt } from './helpers'; describe('helpers', () => { describe('getOptionFromPrompt', () => { it('returns an EuiSuperSelectOption with the correct value', () => { - const option = getOptionFromPrompt(mockSystemPrompt); + const option = getOptionFromPrompt({ ...mockSystemPrompt, isFlyoutMode: true }); expect(option.value).toBe(mockSystemPrompt.id); }); it('returns an EuiSuperSelectOption with the correct inputDisplay', () => { - const option = getOptionFromPrompt(mockSystemPrompt); + const option = getOptionFromPrompt({ ...mockSystemPrompt, isFlyoutMode: false }); render(<>{option.inputDisplay}); @@ -30,7 +30,7 @@ describe('helpers', () => { }); it('shows the expected name in the dropdownDisplay', () => { - const option = getOptionFromPrompt(mockSystemPrompt); + const option = getOptionFromPrompt({ ...mockSystemPrompt, isFlyoutMode: true }); render({option.dropdownDisplay}); @@ -38,7 +38,7 @@ describe('helpers', () => { }); it('shows the expected prompt content in the dropdownDisplay', () => { - const option = getOptionFromPrompt(mockSystemPrompt); + const option = getOptionFromPrompt({ ...mockSystemPrompt, isFlyoutMode: true }); render({option.dropdownDisplay}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx index 33850b6725d9a..465c120d187e9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx @@ -11,6 +11,7 @@ import React from 'react'; // eslint-disable-next-line @kbn/eslint/module_migration import styled from 'styled-components'; +import { css } from '@emotion/react'; import { isEmpty } from 'lodash/fp'; import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { EMPTY_PROMPT } from './translations'; @@ -23,9 +24,30 @@ export const getOptionFromPrompt = ({ content, id, name, -}: PromptResponse & { showTitles?: boolean }): EuiSuperSelectOption => ({ + showTitles = false, + isFlyoutMode, +}: PromptResponse & { + showTitles?: boolean; + isFlyoutMode: boolean; +}): EuiSuperSelectOption => ({ value: id, - inputDisplay: name, + inputDisplay: isFlyoutMode ? ( + name + ) : ( + + {showTitles ? name : content} + + ), dropdownDisplay: ( <> {name} @@ -48,5 +70,6 @@ interface GetOptionsProps { export const getOptions = ({ prompts, showTitles = false, + isFlyoutMode, }: GetOptionsProps): Array> => - prompts?.map((p) => getOptionFromPrompt({ ...p, showTitles })) ?? []; + prompts?.map((p) => getOptionFromPrompt({ ...p, showTitles, isFlyoutMode })) ?? []; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.test.tsx index c731e86a5f002..3796e5b4a81eb 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.test.tsx @@ -11,6 +11,29 @@ import userEvent from '@testing-library/user-event'; import { Props, SelectSystemPrompt } from '.'; import { TEST_IDS } from '../../../constants'; +import { defaultAssistantFeatures } from '@kbn/elastic-assistant-common'; +import { HttpSetup } from '@kbn/core/public'; +import { useFetchPrompts } from '../../../api'; +import { mockSystemPrompts } from '../../../../mock/system_prompt'; +import { DefinedUseQueryResult } from '@tanstack/react-query'; + +jest.mock('../../../api/prompts/use_fetch_prompts'); +const http = { + fetch: jest.fn().mockResolvedValue(defaultAssistantFeatures), +} as unknown as HttpSetup; + +jest.mocked(useFetchPrompts).mockReturnValue({ + data: { page: 1, perPage: 1000, data: mockSystemPrompts, total: 10 }, + isLoading: false, + refetch: jest.fn().mockResolvedValue({ + isLoading: false, + data: { + ...mockSystemPrompts, + }, + }), + isFetched: true, + // eslint-disable-next-line @typescript-eslint/no-explicit-any +} as unknown as DefinedUseQueryResult); const props: Props = { allPrompts: [ @@ -31,6 +54,8 @@ const props: Props = { }; const mockUseAssistantContext = { + http, + assistantAvailability: { isAssistantEnabled: true }, allSystemPrompts: [ { id: 'default-system-prompt', diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx index cbf5efe79213f..37e5fb5a131a4 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx @@ -35,7 +35,7 @@ describe('SystemPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete system prompt because there is only one custom option fireEvent.click(getAllByTestId('delete-prompt')[1]); - expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[1].id); + expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[0].id); expect(onSystemPromptSelectionChange).not.toHaveBeenCalled(); }); it('Deletes a system prompt that is selected', () => { @@ -43,7 +43,7 @@ describe('SystemPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete system prompt because there is only one custom option fireEvent.click(getAllByTestId('delete-prompt')[0]); - expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[0].id); + expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[1].id); expect(onSystemPromptSelectionChange).toHaveBeenCalledWith(undefined); }); it('Selects existing system prompt from the search input', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx index f62dee170e2bb..5116da2a56207 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_settings.test.tsx @@ -98,6 +98,7 @@ describe('SystemPromptSettings', () => { ); fireEvent.click(getByTestId('change-sp-custom')); const customOption = { + consumer: 'test', content: '', id: 'sooper custom prompt', name: 'sooper custom prompt', diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx index eafbe0349ac9d..69403b74a5322 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx @@ -12,7 +12,9 @@ import { mockSystemPrompts, } from '../../../../mock/system_prompt'; import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { useAssistantContext } from '../../../../assistant_context'; +jest.mock('../../../../assistant_context'); // Mock functions for the tests const mockOnSelectedSystemPromptChange = jest.fn(); const mockSetUpdatedSystemPromptSettings = jest.fn(); @@ -22,6 +24,9 @@ const mockPreviousSystemPrompts = [...mockSystemPrompts]; describe('useSystemPromptEditor', () => { beforeEach(() => { jest.clearAllMocks(); + (useAssistantContext as jest.Mock).mockReturnValue({ + currentAppId: 'securitySolutionUI', + }); }); test('should delete a system prompt by id', () => { @@ -84,6 +89,7 @@ describe('useSystemPromptEditor', () => { content: '', name: newPromptId, promptType: 'system', + consumer: 'securitySolutionUI', }; expect(mockOnSelectedSystemPromptChange).toHaveBeenCalledWith(newPrompt); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx index 29db7a3500bd2..033028104e002 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx @@ -35,7 +35,7 @@ describe('QuickPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete quick prompt because there is only one custom option fireEvent.click(getByTestId('delete-quick-prompt')); - expect(onQuickPromptDeleted).toHaveBeenCalledWith('A_CUSTOM_OPTION'); + expect(onQuickPromptDeleted).toHaveBeenCalledWith('ALERT_SUMMARIZATION_TITLE'); }); it('Selects existing quick prompt from the search input', () => { const { getByTestId } = render(); @@ -49,8 +49,10 @@ describe('QuickPromptSelector', () => { expect(onQuickPromptSelectionChange).toHaveBeenCalledWith({ categories: [], color: '#D36086', - prompt: 'quickly prompt please', - title: 'A_CUSTOM_OPTION', + content: 'quickly prompt please', + id: 'A_CUSTOM_OPTION', + name: 'A_CUSTOM_OPTION', + promptType: 'quick', }); }); it('Reset settings every time before selecting an system prompt from the input if resetSettings is provided', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx index 48792146f9036..eb8cc2cb2569c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/quick_prompt_settings.test.tsx @@ -94,8 +94,11 @@ describe('QuickPromptSettings', () => { const customOption = { categories: [], color: '#D36086', - prompt: '', - title: 'sooper custom prompt', + consumer: undefined, + content: '', + id: 'sooper custom prompt', + name: 'sooper custom prompt', + promptType: 'quick', }; expect(setUpdatedQuickPromptSettings).toHaveReturnedWith([...MOCK_QUICK_PROMPTS, customOption]); expect(onSelectedQuickPromptChange).toHaveBeenCalledWith(customOption); @@ -133,7 +136,7 @@ describe('QuickPromptSettings', () => { const previousFirstElementOfTheArray = mutatableQuickPrompts.shift(); expect(setUpdatedQuickPromptSettings).toHaveReturnedWith([ - { ...previousFirstElementOfTheArray, prompt: 'what does this do' }, + { ...previousFirstElementOfTheArray, content: 'what does this do' }, ...mutatableQuickPrompts, ]); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx index 88b9dd5d1db4c..56a1106a9752c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx @@ -10,7 +10,9 @@ import { useQuickPromptEditor, DEFAULT_COLOR } from './use_quick_prompt_editor'; import { mockAlertPromptContext } from '../../../mock/prompt_context'; import { MOCK_QUICK_PROMPTS } from '../../../mock/quick_prompt'; import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { useAssistantContext } from '../../../assistant_context'; +jest.mock('../../../assistant_context'); // Mock functions for the tests const mockOnSelectedQuickPromptChange = jest.fn(); const mockSetUpdatedQuickPromptSettings = jest.fn(); @@ -20,6 +22,9 @@ const setPromptsBulkActions = jest.fn(); describe('useQuickPromptEditor', () => { beforeEach(() => { jest.clearAllMocks(); + (useAssistantContext as jest.Mock).mockReturnValue({ + currentAppId: 'securitySolutionUI', + }); }); test('should delete a quick prompt by title', () => { @@ -61,8 +66,9 @@ describe('useQuickPromptEditor', () => { content: '', color: DEFAULT_COLOR, categories: [], - id: '', + id: newPromptTitle, promptType: 'quick', + consumer: 'securitySolutionUI', }; expect(mockOnSelectedQuickPromptChange).toHaveBeenCalledWith(newPrompt); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/types.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/types.tsx deleted file mode 100644 index c0688f432e7dd..0000000000000 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/types.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 { PromptContext } from '../../..'; - -/** - * A QuickPrompt is a badge that is displayed below the Assistant's input field. They provide - * a quick way for users to insert prompts as templates into the Assistant's input field. If no - * categories are provided they will always display with the assistant, however categories can be - * supplied to only display the QuickPrompt when the Assistant is registered with corresponding - * PromptContext's containing the same category. - * - * isDefault: If true, this QuickPrompt cannot be deleted by the user - */ -export interface QuickPrompt { - title: string; - prompt: string; - color: string; - categories?: Array; - isDefault?: boolean; -} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx index 45e06f5589163..b9aefa9c422ae 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx @@ -9,11 +9,7 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { DEFAULT_LATEST_ALERTS } from '../../../assistant_context/constants'; import { alertConvo, welcomeConvo } from '../../../mock/conversation'; import { useSettingsUpdater } from './use_settings_updater'; -import { - defaultSystemPrompt, - mockSuperheroSystemPrompt, - mockSystemPrompt, -} from '../../../mock/system_prompt'; +import { defaultQuickPrompt, mockSystemPrompt } from '../../../mock/system_prompt'; import { HttpSetup } from '@kbn/core/public'; import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; @@ -28,7 +24,7 @@ const mockHttp = { } as unknown as HttpSetup; const mockSystemPrompts: PromptResponse[] = [mockSystemPrompt]; -const mockQuickPrompts: PromptResponse[] = [defaultSystemPrompt]; +const mockQuickPrompts: PromptResponse[] = [defaultQuickPrompt]; const anonymizationFields = { total: 2, @@ -40,8 +36,6 @@ const anonymizationFields = { ], }; -const setAllQuickPromptsMock = jest.fn(); -const setAllSystemPromptsMock = jest.fn(); const setAssistantStreamingEnabled = jest.fn(); const setKnowledgeBaseMock = jest.fn(); const reportAssistantSettingToggled = jest.fn(); @@ -58,8 +52,6 @@ const mockValues = { latestAlerts: DEFAULT_LATEST_ALERTS, }, baseConversations: {}, - setAllQuickPrompts: setAllQuickPromptsMock, - setAllSystemPrompts: setAllSystemPromptsMock, setKnowledgeBase: setKnowledgeBaseMock, http: mockHttp, anonymizationFieldsBulkActions: {}, @@ -67,8 +59,18 @@ const mockValues = { const updatedValues = { conversations: { ...mockConversations }, - allSystemPrompts: [mockSuperheroSystemPrompt], - allQuickPrompts: [{ title: 'Prompt 2', prompt: 'Prompt 2', color: 'red' }], + allSystemPrompts: [mockSystemPrompt], + allQuickPrompts: [ + { + consumer: 'securitySolutionUI', + content: + 'You are a helpful, expert assistant who answers questions about Elastic Security. Do not answer questions unrelated to Elastic Security.\nIf you answer a question related to KQL or EQL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query.\nUse the following context to answer questions:', + id: 'default-system-prompt', + name: 'Default system prompt', + promptType: 'quick', + color: 'red', + }, + ], updatedAnonymizationData: { total: 2, page: 1, @@ -104,7 +106,7 @@ describe('useSettingsUpdater', () => { useSettingsUpdater( mockConversations, { - data: mockSystemPrompts, + data: [...mockSystemPrompts, ...mockQuickPrompts], page: 1, perPage: 100, total: 10, @@ -195,8 +197,6 @@ describe('useSettingsUpdater', () => { body: '{"delete":{"ids":["1"]}}', } ); - expect(setAllQuickPromptsMock).toHaveBeenCalledWith(updatedValues.allQuickPrompts); - expect(setAllSystemPromptsMock).toHaveBeenCalledWith(updatedValues.allSystemPrompts); expect(setUpdatedAnonymizationData).toHaveBeenCalledWith( updatedValues.updatedAnonymizationData ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx deleted file mode 100644 index 6fff9ae742536..0000000000000 --- a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/system/index.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; -import { - DEFAULT_SYSTEM_PROMPT_NAME, - DEFAULT_SYSTEM_PROMPT_NON_I18N, - SUPERHERO_SYSTEM_PROMPT_NAME, - SUPERHERO_SYSTEM_PROMPT_NON_I18N, -} from './translations'; - -/** - * Base System Prompts for Elastic AI Assistant (if not overridden on initialization). - */ -export const BASE_SYSTEM_PROMPTS: PromptResponse[] = [ - { - id: 'default-system-prompt', - content: DEFAULT_SYSTEM_PROMPT_NON_I18N, - name: DEFAULT_SYSTEM_PROMPT_NAME, - promptType: 'system', - // label: DEFAULT_SYSTEM_PROMPT_LABEL, - }, - { - id: 'CB9FA555-B59F-4F71-AFF9-8A891AC5BC28', - content: SUPERHERO_SYSTEM_PROMPT_NON_I18N, - name: SUPERHERO_SYSTEM_PROMPT_NAME, - promptType: 'system', - // label: SUPERHERO_SYSTEM_PROMPT_LABEL, - }, -]; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/user/translations.ts b/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/user/translations.ts deleted file mode 100644 index 28cda1f9414a8..0000000000000 --- a/x-pack/packages/kbn-elastic-assistant/impl/content/prompts/user/translations.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; - -export const THEN_SUMMARIZE_SUGGESTED_KQL_AND_EQL_QUERIES = i18n.translate( - 'xpack.elasticAssistant.assistant.content.prompts.user.thenSummarizeSuggestedKqlAndEqlQueries', - { - defaultMessage: - 'Evaluate the event from the context above and format your output neatly in markdown syntax for my Elastic Security case.', - } -); - -export const FINALLY_SUGGEST_INVESTIGATION_GUIDE_AND_FORMAT_AS_MARKDOWN = i18n.translate( - 'xpack.elasticAssistant.assistant.content.prompts.user.finallySuggestInvestigationGuideAndFormatAsMarkdown', - { - defaultMessage: `Add your description, recommended actions and bulleted triage steps. Use the MITRE ATT&CK data provided to add more context and recommendations from MITRE, and hyperlink to the relevant pages on MITRE\'s website. Be sure to include the user and host risk score data from the context. Your response should include steps that point to Elastic Security specific features, including endpoint response actions, the Elastic Agent OSQuery manager integration (with example osquery queries), timelines and entity analytics and link to all the relevant Elastic Security documentation.`, - } -); - -export const EXPLAIN_THEN_SUMMARIZE_SUGGEST_INVESTIGATION_GUIDE_NON_I18N = `${THEN_SUMMARIZE_SUGGESTED_KQL_AND_EQL_QUERIES} -${FINALLY_SUGGEST_INVESTIGATION_GUIDE_AND_FORMAT_AS_MARKDOWN}`; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts b/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts index 9516d95289813..6607c1987403f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts @@ -11,6 +11,7 @@ export const mockSystemPrompt: PromptResponse = { id: 'mock-system-prompt-1', content: 'You are a helpful, expert assistant who answers questions about Elastic Security.', name: 'Mock system prompt', + consumer: 'securitySolutionUI', promptType: 'system', }; @@ -19,6 +20,7 @@ export const mockSuperheroSystemPrompt: PromptResponse = { content: `You are a helpful, expert assistant who answers questions about Elastic Security. You have the personality of a mutant superhero who says "bub" a lot.`, name: 'Mock superhero system prompt', + consumer: 'securitySolutionUI', promptType: 'system', }; @@ -28,10 +30,21 @@ export const defaultSystemPrompt: PromptResponse = { 'You are a helpful, expert assistant who answers questions about Elastic Security. Do not answer questions unrelated to Elastic Security.\nIf you answer a question related to KQL or EQL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query.\nUse the following context to answer questions:', name: 'Default system prompt', promptType: 'system', + consumer: 'securitySolutionUI', isDefault: true, isNewConversationDefault: true, }; +export const defaultQuickPrompt: PromptResponse = { + id: 'default-system-prompt', + content: + 'You are a helpful, expert assistant who answers questions about Elastic Security. Do not answer questions unrelated to Elastic Security.\nIf you answer a question related to KQL or EQL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query.\nUse the following context to answer questions:', + name: 'Default system prompt', + promptType: 'quick', + consumer: 'securitySolutionUI', + color: 'red', +}; + export const mockSystemPrompts: PromptResponse[] = [ mockSystemPrompt, mockSuperheroSystemPrompt, diff --git a/x-pack/packages/kbn-elastic-assistant/index.ts b/x-pack/packages/kbn-elastic-assistant/index.ts index 748e0ba33ebd1..7cd882cd633b8 100644 --- a/x-pack/packages/kbn-elastic-assistant/index.ts +++ b/x-pack/packages/kbn-elastic-assistant/index.ts @@ -90,12 +90,6 @@ export { WELCOME_CONVERSATION_TITLE, } from './impl/assistant/use_conversation/translations'; -/** i18n translations of system prompts */ -export * as SYSTEM_PROMPTS from './impl/content/prompts/system/translations'; - -/** i18n translations of user prompts */ -export * as USER_PROMPTS from './impl/content/prompts/user/translations'; - export type { /** for rendering results in a code block */ CodeBlockDetails, @@ -136,12 +130,6 @@ export type { PromptContext } from './impl/assistant/prompt_context/types'; */ export type { PromptContextTemplate } from './impl/assistant/prompt_context/types'; -/** - * This interface is used to pass a default or base set of Quick Prompts to the Elastic Assistant that - * can be displayed when corresponding PromptContext's are registered. - */ -export type { QuickPrompt } from './impl/assistant/quick_prompts/types'; - export { useFetchCurrentUserConversations } from './impl/assistant/api/conversations/use_fetch_current_user_conversations'; export * from './impl/assistant/api/conversations/bulk_update_actions_conversations'; export { getConversationById } from './impl/assistant/api/conversations/conversations'; @@ -149,4 +137,4 @@ export { getConversationById } from './impl/assistant/api/conversations/conversa export { mergeBaseWithPersistedConversations } from './impl/assistant/helpers'; export { UpgradeButtons } from './impl/upgrade/upgrade_buttons'; -export { getUserConversations } from './impl/assistant/api'; +export { getUserConversations, getPrompts, bulkUpdatePrompts } from './impl/assistant/api'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx index a4e6d39e720ec..b4579dd4bd50c 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx @@ -73,6 +73,7 @@ export const TestProvidersComponent: React.FC = ({ children, isILMAvailab http={mockHttp} baseConversations={{}} navigateToApp={mockNavigateToApp} + currentAppId={'securitySolutionUI'} > { + const promptsToCreate = [...BASE_SECURITY_QUICK_PROMPTS, ...BASE_SECURITY_SYSTEM_PROMPTS]; + + // post bulk create + const bulkResult = await bulkUpdatePrompts( + http, + { + create: promptsToCreate, + }, + notifications.toasts + ); + if (bulkResult && bulkResult.success) { + return true; + } +}; + /** * This component configures the Elastic AI Assistant context provider for the Security Solution app. */ @@ -152,6 +172,27 @@ export const AssistantProvider: FC> = ({ children }) storage, ]); + useEffect(() => { + const createSecurityPrompts = once(async () => { + const res = await getPrompts({ + http, + }); + if ( + assistantAvailability.isAssistantEnabled && + assistantAvailability.hasAssistantPrivilege && + res.total === 0 + ) { + await createBasePrompts(notifications, http); + } + }); + createSecurityPrompts(); + }, [ + assistantAvailability.hasAssistantPrivilege, + assistantAvailability.isAssistantEnabled, + http, + notifications, + ]); + const { signalIndexName } = useSignalIndex(); const alertsIndexPattern = signalIndexName ?? undefined; const toasts = useAppToasts() as unknown as IToasts; // useAppToasts is the current, non-deprecated method of getting the toasts service in the Security Solution, but it doesn't return the IToasts interface (defined by core) From 883d9a9232cb93e130358dc6895a1d8aec667365 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 06:04:51 -0700 Subject: [PATCH 12/22] fixed unused labels --- x-pack/plugins/translations/translations/fr-FR.json | 2 -- x-pack/plugins/translations/translations/ja-JP.json | 2 -- x-pack/plugins/translations/translations/zh-CN.json | 2 -- 3 files changed, 6 deletions(-) diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 3619b6096c0f0..f00df24a5bb5c 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -13342,8 +13342,6 @@ "xpack.elasticAssistant.assistant.content.prompts.system.superheroPersonality": "Donnez la réponse la plus pertinente et détaillée possible, comme si vous deviez communiquer ces informations à un expert en cybersécurité.", "xpack.elasticAssistant.assistant.content.prompts.system.superheroSystemPromptName": "Invite système améliorée", "xpack.elasticAssistant.assistant.content.prompts.system.youAreAHelpfulExpertAssistant": "Vous êtes un assistant expert et serviable qui répond à des questions au sujet d’Elastic Security.", - "xpack.elasticAssistant.assistant.content.prompts.user.finallySuggestInvestigationGuideAndFormatAsMarkdown": "Ajoutez votre description, les actions que vous recommandez ainsi que les étapes de triage à puces. Utilisez les données \"MITRE ATT&CK\" fournies pour ajouter du contexte et des recommandations de MITRE ainsi que des liens hypertexte vers les pages pertinentes sur le site web de MITRE. Assurez-vous d’inclure les scores de risque de l’utilisateur et de l’hôte du contexte. Votre réponse doit inclure des étapes qui pointent vers les fonctionnalités spécifiques d’Elastic Security, y compris les actions de réponse du terminal, l’intégration OSQuery Manager d’Elastic Agent (avec des exemples de requêtes OSQuery), des analyses de timeline et d’entités, ainsi qu’un lien pour toute la documentation Elastic Security pertinente.", - "xpack.elasticAssistant.assistant.content.prompts.user.thenSummarizeSuggestedKqlAndEqlQueries": "Évaluer l’événement depuis le contexte ci-dessus et formater soigneusement la sortie en syntaxe Markdown pour mon cas Elastic Security.", "xpack.elasticAssistant.assistant.conversations.settings.connectorTitle": "Connecteur", "xpack.elasticAssistant.assistant.conversations.settings.promptHelpTextTitle": "Contexte fournit dans le cadre de chaque conversation", "xpack.elasticAssistant.assistant.conversations.settings.promptTitle": "Invite système", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 86790c7959135..8102f8506b32c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -13321,8 +13321,6 @@ "xpack.elasticAssistant.assistant.content.prompts.system.superheroPersonality": "サイバーセキュリティの専門家に情報を伝えるつもりで、できるだけ詳細で関連性のある回答を入力してください。", "xpack.elasticAssistant.assistant.content.prompts.system.superheroSystemPromptName": "拡張システムプロンプト", "xpack.elasticAssistant.assistant.content.prompts.system.youAreAHelpfulExpertAssistant": "あなたはElasticセキュリティに関する質問に答える、親切で専門的なアシスタントです。", - "xpack.elasticAssistant.assistant.content.prompts.user.finallySuggestInvestigationGuideAndFormatAsMarkdown": "説明、推奨されるアクション、箇条書きのトリアージステップを追加します。提供された MITRE ATT&CKデータを使用して、MITREからのコンテキストや推奨事項を追加し、MITREのWebサイトの関連ページにハイパーリンクを貼ります。コンテキストのユーザーとホストのリスクスコアデータを必ず含めてください。回答には、エンドポイント対応アクション、ElasticエージェントOSQueryマネージャー統合(osqueryクエリの例を付けて)、タイムライン、エンティティ分析など、Elasticセキュリティ固有の機能を指す手順を含め、関連するElasticセキュリティのドキュメントすべてにリンクしてください。", - "xpack.elasticAssistant.assistant.content.prompts.user.thenSummarizeSuggestedKqlAndEqlQueries": "上記のコンテキストからイベントを評価し、Elasticセキュリティのケース用に、出力をマークダウン構文で正しく書式設定してください。", "xpack.elasticAssistant.assistant.conversations.settings.connectorTitle": "コネクター", "xpack.elasticAssistant.assistant.conversations.settings.promptHelpTextTitle": "すべての会話の一部として提供されたコンテキスト", "xpack.elasticAssistant.assistant.conversations.settings.promptTitle": "システムプロンプト", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 22ff7f4be1b70..3a19efa4a4307 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -13347,8 +13347,6 @@ "xpack.elasticAssistant.assistant.content.prompts.system.superheroPersonality": "提供可能的最详细、最相关的答案,就好像您正将此信息转发给网络安全专家一样。", "xpack.elasticAssistant.assistant.content.prompts.system.superheroSystemPromptName": "已增强系统提示", "xpack.elasticAssistant.assistant.content.prompts.system.youAreAHelpfulExpertAssistant": "您是一位可帮助回答 Elastic Security 相关问题的专家助手。", - "xpack.elasticAssistant.assistant.content.prompts.user.finallySuggestInvestigationGuideAndFormatAsMarkdown": "添加描述、建议操作和带项目符号的分类步骤。使用提供的 MITRE ATT&CK 数据以从 MITRE 添加更多上下文和建议,以及指向 MITRE 网站上的相关页面的超链接。确保包括上下文中的用户和主机风险分数数据。您的响应应包含指向 Elastic Security 特定功能的步骤,包括终端响应操作、Elastic 代理 OSQuery 管理器集成(带示例 osquery 查询)、时间线和实体分析,以及所有相关 Elastic Security 文档的链接。", - "xpack.elasticAssistant.assistant.content.prompts.user.thenSummarizeSuggestedKqlAndEqlQueries": "评估来自上述上下文的事件,并以用于我的 Elastic Security 案例的 Markdown 语法对您的输出进行全面格式化。", "xpack.elasticAssistant.assistant.conversations.settings.connectorTitle": "连接器", "xpack.elasticAssistant.assistant.conversations.settings.promptHelpTextTitle": "已作为每个对话的一部分提供上下文", "xpack.elasticAssistant.assistant.conversations.settings.promptTitle": "系统提示", From a2a7fb6321e1f7ca7eea2edd9a0c346aa53b672f Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 09:12:07 -0700 Subject: [PATCH 13/22] fixed update on save --- .../assistant_header/assistant_header_flyout.tsx | 6 ++++++ .../impl/assistant/assistant_header/index.tsx | 6 ++++++ .../kbn-elastic-assistant/impl/assistant/index.tsx | 6 +++++- .../assistant/settings/assistant_settings_button.tsx | 10 +++++++++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/assistant_header_flyout.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/assistant_header_flyout.tsx index d9ba27b96655f..2c9337ee910c8 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/assistant_header_flyout.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/assistant_header_flyout.tsx @@ -6,6 +6,7 @@ */ import React, { useState, useMemo, useCallback } from 'react'; +import { QueryObserverResult, RefetchOptions, RefetchQueryFilters } from '@tanstack/react-query'; import { EuiFlexGroup, EuiFlexItem, @@ -47,6 +48,9 @@ interface OwnProps { refetchConversationsState: () => Promise; onConversationCreate: () => Promise; isAssistantEnabled: boolean; + refetchPrompts?: ( + options?: RefetchOptions & RefetchQueryFilters + ) => Promise>; } type Props = OwnProps; @@ -74,6 +78,7 @@ export const AssistantHeaderFlyout: React.FC = ({ refetchConversationsState, onConversationCreate, isAssistantEnabled, + refetchPrompts, }) => { const showAnonymizedValuesChecked = useMemo( () => @@ -163,6 +168,7 @@ export const AssistantHeaderFlyout: React.FC = ({ conversationsLoaded={conversationsLoaded} refetchConversationsState={refetchConversationsState} isFlyoutMode={true} + refetchPrompts={refetchPrompts} /> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx index 1533cfaabf72c..20190ceda6e70 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx @@ -14,6 +14,7 @@ import { EuiSwitch, EuiToolTip, } from '@elastic/eui'; +import { QueryObserverResult, RefetchOptions, RefetchQueryFilters } from '@tanstack/react-query'; import { css } from '@emotion/react'; import { DocLinksStart } from '@kbn/core-doc-links-browser'; import { isEmpty } from 'lodash'; @@ -42,6 +43,9 @@ interface OwnProps { conversationsLoaded: boolean; refetchConversationsState: () => Promise; allPrompts: PromptResponse[]; + refetchPrompts?: ( + options?: RefetchOptions & RefetchQueryFilters + ) => Promise>; } type Props = OwnProps; @@ -67,6 +71,7 @@ export const AssistantHeader: React.FC = ({ conversationsLoaded, refetchConversationsState, allPrompts, + refetchPrompts, }) => { const showAnonymizedValuesChecked = useMemo( () => @@ -160,6 +165,7 @@ export const AssistantHeader: React.FC = ({ conversationsLoaded={conversationsLoaded} refetchConversationsState={refetchConversationsState} isFlyoutMode={false} + refetchPrompts={refetchPrompts} /> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx index 4f33b3b480570..be491e4d5f951 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx @@ -182,7 +182,7 @@ const AssistantComponent: React.FC = ({ isFetched: isFetchedAnonymizationFields, } = useFetchAnonymizationFields(); - const { data: allPrompts } = useFetchPrompts(); + const { data: allPrompts, refetch: refetchPrompts } = useFetchPrompts(); // Connector details const { data: connectors, isFetchedAfterMount: areConnectorsFetched } = useLoadConnectors({ @@ -642,6 +642,7 @@ const AssistantComponent: React.FC = ({ setSelectedPromptContexts={setSelectedPromptContexts} isFlyoutMode={isFlyoutMode} allSystemPrompts={allPrompts.data} + refetchPrompts={refetchPrompts} /> )} @@ -649,6 +650,7 @@ const AssistantComponent: React.FC = ({ ), [ getComments, + refetchPrompts, abortStream, currentConversation, showAnonymizedValues, @@ -962,6 +964,7 @@ const AssistantComponent: React.FC = ({ refetchConversationsState={refetchConversationsState} onConversationCreate={handleCreateConversation} isAssistantEnabled={isAssistantEnabled} + refetchPrompts={refetchPrompts} /> {/* Create portals for each EuiCodeBlock to add the `Investigate in Timeline` action */} @@ -1132,6 +1135,7 @@ const AssistantComponent: React.FC = ({ onConversationDeleted={handleOnConversationDeleted} refetchConversationsState={refetchConversationsState} allPrompts={allPrompts.data} + refetchPrompts={refetchPrompts} /> )} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_button.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_button.tsx index 432730194d1a3..30f141f219476 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_button.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_button.tsx @@ -8,6 +8,7 @@ import React, { useCallback } from 'react'; import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; +import { QueryObserverResult, RefetchOptions, RefetchQueryFilters } from '@tanstack/react-query'; import { AIConnector } from '../../connectorland/connector_selector'; import { Conversation } from '../../..'; import { AssistantSettings } from './assistant_settings'; @@ -26,6 +27,9 @@ interface Props { conversations: Record; conversationsLoaded: boolean; refetchConversationsState: () => Promise; + refetchPrompts?: ( + options?: RefetchOptions & RefetchQueryFilters + ) => Promise>; } /** @@ -43,6 +47,7 @@ export const AssistantSettingsButton: React.FC = React.memo( conversations, conversationsLoaded, refetchConversationsState, + refetchPrompts, }) => { const { toasts, setSelectedSettingsTab } = useAssistantContext(); @@ -59,6 +64,9 @@ export const AssistantSettingsButton: React.FC = React.memo( async (success: boolean) => { cleanupAndCloseModal(); await refetchConversationsState(); + if (refetchPrompts) { + await refetchPrompts(); + } if (success) { toasts?.addSuccess({ iconType: 'check', @@ -66,7 +74,7 @@ export const AssistantSettingsButton: React.FC = React.memo( }); } }, - [cleanupAndCloseModal, refetchConversationsState, toasts] + [cleanupAndCloseModal, refetchConversationsState, refetchPrompts, toasts] ); const handleShowConversationSettings = useCallback(() => { From e43b4d550f5f3023fcfe2f35b638d605723b4647 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 09:28:31 -0700 Subject: [PATCH 14/22] fixed delete --- x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx | 2 -- .../system_prompt_selector/system_prompt_selector.tsx | 2 +- .../quick_prompt_selector/quick_prompt_selector.tsx | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx index be491e4d5f951..1fd48f92c5c5b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx @@ -642,7 +642,6 @@ const AssistantComponent: React.FC = ({ setSelectedPromptContexts={setSelectedPromptContexts} isFlyoutMode={isFlyoutMode} allSystemPrompts={allPrompts.data} - refetchPrompts={refetchPrompts} /> )} @@ -650,7 +649,6 @@ const AssistantComponent: React.FC = ({ ), [ getComments, - refetchPrompts, abortStream, currentConversation, showAnonymizedValues, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx index 455f6128ef928..ca51b0d1bc84d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx @@ -135,7 +135,7 @@ export const SystemPromptSelector: React.FC = React.memo( // Callback for when user deletes a quick prompt const onDelete = useCallback( (label: string) => { - const deleteId = options.find((o) => o.label !== label)?.id; + const deleteId = options.find((o) => o.label === label)?.id; setOptions(options.filter((o) => o.label !== label)); if (selectedOptions?.[0]?.label === label) { handleSelectionChange([]); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx index 89edd5e3ffbfd..5cb3fbca0daee 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx @@ -128,7 +128,7 @@ export const QuickPromptSelector: React.FC = React.memo( // Callback for when user deletes a quick prompt const onDelete = useCallback( (label: string) => { - const deleteId = options.find((o) => o.label !== label)?.id; + const deleteId = options.find((o) => o.label === label)?.id; setOptions(options.filter((o) => o.label !== label)); if (selectedOptions?.[0]?.label === label) { handleSelectionChange([]); From 17d7d81703662a44ea32f7b71eb3bdfdb13154dc Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 10:45:15 -0700 Subject: [PATCH 15/22] fixed due to comments --- .../impl/schemas/index.ts | 3 ++ .../api/prompts/use_fetch_prompts.ts | 4 +- .../impl/assistant/assistant_header/index.tsx | 2 +- .../assistant/chat_send/use_chat_send.tsx | 3 +- .../conversation_settings.tsx | 2 +- .../conversation_settings_editor.tsx | 2 +- .../use_conversation_changed.tsx | 2 +- .../index.tsx | 2 +- .../use_conversations_table.tsx | 2 +- .../impl/assistant/index.tsx | 38 ++++++++++++------- .../impl/assistant/prompt/helpers.ts | 3 +- .../assistant/prompt_editor/helpers.test.tsx | 2 +- .../impl/assistant/prompt_editor/helpers.tsx | 2 +- .../impl/assistant/prompt_editor/index.tsx | 2 +- .../prompt_editor/system_prompt/helpers.tsx | 2 +- .../system_prompt/index.test.tsx | 2 +- .../prompt_editor/system_prompt/index.tsx | 2 +- .../system_prompt_selector.tsx | 2 +- .../use_system_prompt_editor.test.tsx | 2 +- .../use_system_prompt_table.test.tsx | 3 +- .../use_system_prompt_table.tsx | 2 +- .../utils.tsx | 2 +- .../quick_prompt_selector.tsx | 2 +- .../use_quick_prompt_editor.test.tsx | 2 +- .../use_quick_prompt_table.test.tsx | 2 +- .../use_quick_prompt_table.tsx | 2 +- .../assistant/settings/assistant_settings.tsx | 2 +- .../assistant_settings_management.tsx | 2 +- .../use_settings_updater.test.tsx | 2 +- .../use_conversation/helpers.test.ts | 2 +- .../assistant/use_conversation/helpers.ts | 2 +- .../impl/mock/system_prompt/index.ts | 2 +- .../impl/mock/user_prompt/index.ts | 2 +- .../content/prompts/system/index.tsx | 14 ++++--- .../assistant/content/quick_prompts/index.tsx | 15 ++++---- 35 files changed, 77 insertions(+), 60 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts index 8f47731694cf3..f337dc6deaf89 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts @@ -49,3 +49,6 @@ export * from './knowledge_base/bulk_crud_knowledge_base_route.gen'; export * from './knowledge_base/common_attributes.gen'; export * from './knowledge_base/crud_knowledge_base_route.gen'; export * from './knowledge_base/find_knowledge_base_entries_route.gen'; + +export * from './prompts/find_prompts_route.gen'; +export { PromptResponse } from './prompts/bulk_crud_prompts_route.gen'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts index ffb876bb28aef..df11bad4689f0 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts @@ -81,7 +81,7 @@ export const getPrompts = async ({ toasts, }: { http: HttpSetup; - toasts?: IToasts; + toasts: IToasts; signal?: AbortSignal | undefined; }) => { try { @@ -91,7 +91,7 @@ export const getPrompts = async ({ signal, }); } catch (error) { - toasts?.addError(error.body && error.body.message ? new Error(error.body.message) : error, { + toasts.addError(error.body && error.body.message ? new Error(error.body.message) : error, { title: i18n.translate('xpack.elasticAssistant.prompts.getPromptsError', { defaultMessage: 'Error fetching prompts', }), diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx index 20190ceda6e70..7507c14648614 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx @@ -18,7 +18,7 @@ import { QueryObserverResult, RefetchOptions, RefetchQueryFilters } from '@tanst import { css } from '@emotion/react'; import { DocLinksStart } from '@kbn/core-doc-links-browser'; import { isEmpty } from 'lodash'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { AIConnector } from '../../connectorland/connector_selector'; import { Conversation } from '../../..'; import { AssistantTitle } from '../assistant_title'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx index c0f40c83d29cd..3d51234ee3743 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx @@ -8,8 +8,7 @@ import React, { useCallback } from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; import { i18n } from '@kbn/i18n'; -import { Replacements } from '@kbn/elastic-assistant-common'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse, Replacements } from '@kbn/elastic-assistant-common'; import type { ClientMessage } from '../../assistant_context/types'; import { SelectedPromptContext } from '../prompt_context/types'; import { useSendMessage } from '../use_send_message'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx index 4aef092580ab9..cba17030e1577 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx @@ -18,7 +18,7 @@ import React, { useMemo } from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; import { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../..'; import * as i18n from './translations'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx index 5bb3c4597b8a5..41da376d21b73 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings_editor.tsx @@ -12,7 +12,7 @@ import { HttpSetup } from '@kbn/core-http-browser'; import { FormattedMessage } from '@kbn/i18n-react'; import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; import { noop } from 'lodash/fp'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../..'; import * as i18n from './translations'; import * as i18nModel from '../../../connectorland/models/model_selector/translations'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx index 6ed8037327781..78209d95c75fa 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/use_conversation_changed.tsx @@ -6,7 +6,7 @@ */ import { useCallback, useMemo } from 'react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../..'; import { getDefaultSystemPrompt } from '../../use_conversation/helpers'; import { ConversationsBulkActions } from '../../api'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx index 0a754fcd50d03..485f89358f57a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/index.tsx @@ -8,7 +8,7 @@ import { EuiPanel, EuiSpacer, EuiConfirmModal, EuiInMemoryTable } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../assistant_context/types'; import { ConversationTableItem, useConversationsTable } from './use_conversations_table'; import { ConversationStreamingSwitch } from '../conversation_settings/conversation_streaming_switch'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx index 5f005875eb520..446fb33ebb9e9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings_management/use_conversations_table.tsx @@ -11,7 +11,7 @@ import { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/publ import { EuiBadge, EuiBasicTableColumn, EuiLink } from '@elastic/eui'; import { FormattedDate } from '@kbn/i18n-react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../assistant_context/types'; import { AIConnector } from '../../../connectorland/connector_selector'; import { getConnectorTypeTitle } from '../../../connectorland/helpers'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx index 1fd48f92c5c5b..033e9b8da89c7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx @@ -39,6 +39,7 @@ import deepEqual from 'fast-deep-equal'; import { find, isEmpty, uniqBy } from 'lodash'; import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { PromptTypeEnum } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; import { useChatSend } from './chat_send/use_chat_send'; import { ChatSend } from './chat_send'; import { BlockBotCallToAction } from './block_bot/cta'; @@ -182,7 +183,18 @@ const AssistantComponent: React.FC = ({ isFetched: isFetchedAnonymizationFields, } = useFetchAnonymizationFields(); - const { data: allPrompts, refetch: refetchPrompts } = useFetchPrompts(); + const { + data: { data: allPrompts }, + refetch: refetchPrompts, + isLoading: isLoadingPrompts, + } = useFetchPrompts(); + + const allSystemPrompts = useMemo(() => { + if (!isLoadingPrompts) { + return allPrompts.filter((p) => p.promptType === PromptTypeEnum.system); + } + return []; + }, [allPrompts, isLoadingPrompts]); // Connector details const { data: connectors, isFetchedAfterMount: areConnectorsFetched } = useLoadConnectors({ @@ -401,10 +413,10 @@ const AssistantComponent: React.FC = ({ const selectedSystemPrompt = useMemo( () => getDefaultSystemPrompt({ - allSystemPrompts: allPrompts.data, + allSystemPrompts, conversation: currentConversation, }), - [allPrompts, currentConversation] + [allSystemPrompts, currentConversation] ); const [editingSystemPromptId, setEditingSystemPromptId] = useState( @@ -426,12 +438,12 @@ const AssistantComponent: React.FC = ({ } setEditingSystemPromptId( getDefaultSystemPrompt({ - allSystemPrompts: allPrompts.data, + allSystemPrompts, conversation: selectedConversation, })?.id ); }, - [allPrompts, refetchCurrentConversation, refetchResults] + [allSystemPrompts, refetchCurrentConversation, refetchResults] ); const { comments: connectorComments, prompt: connectorPrompt } = useConnectorSetup({ @@ -562,7 +574,7 @@ const AssistantComponent: React.FC = ({ handleRegenerateResponse, isLoading: isLoadingChatSend, } = useChatSend({ - allSystemPrompts: allPrompts.data, + allSystemPrompts, currentConversation, setPromptTextPreview, setUserPrompt, @@ -641,7 +653,7 @@ const AssistantComponent: React.FC = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} setSelectedPromptContexts={setSelectedPromptContexts} isFlyoutMode={isFlyoutMode} - allSystemPrompts={allPrompts.data} + allSystemPrompts={allSystemPrompts} /> )} @@ -667,7 +679,7 @@ const AssistantComponent: React.FC = ({ promptTextPreview, handleOnSystemPromptSelectionChange, selectedPromptContexts, - allPrompts.data, + allSystemPrompts, ] ); @@ -871,7 +883,7 @@ const AssistantComponent: React.FC = ({ isSettingsModalVisible={isSettingsModalVisible} setIsSettingsModalVisible={setIsSettingsModalVisible} isFlyoutMode - allSystemPrompts={allPrompts.data} + allSystemPrompts={allSystemPrompts} /> @@ -895,7 +907,7 @@ const AssistantComponent: React.FC = ({ ); }, [ - allPrompts.data, + allSystemPrompts, comments, connectorPrompt, currentConversation, @@ -1095,7 +1107,7 @@ const AssistantComponent: React.FC = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} trackPrompt={trackPrompt} isFlyoutMode={isFlyoutMode} - allPrompts={allPrompts.data} + allPrompts={allPrompts} /> )} @@ -1132,7 +1144,7 @@ const AssistantComponent: React.FC = ({ conversationsLoaded={conversationsLoaded} onConversationDeleted={handleOnConversationDeleted} refetchConversationsState={refetchConversationsState} - allPrompts={allPrompts.data} + allPrompts={allPrompts} refetchPrompts={refetchPrompts} /> )} @@ -1212,7 +1224,7 @@ const AssistantComponent: React.FC = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} trackPrompt={trackPrompt} isFlyoutMode={isFlyoutMode} - allPrompts={allPrompts.data} + allPrompts={allPrompts} /> )} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts index f23c7f4de8f59..4868eff04b4e7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt/helpers.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { Replacements, transformRawData } from '@kbn/elastic-assistant-common'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { Replacements, transformRawData, PromptResponse } from '@kbn/elastic-assistant-common'; import type { ClientMessage } from '../../assistant_context/types'; import { getAnonymizedValue as defaultGetAnonymizedValue } from '../get_anonymized_value'; import type { SelectedPromptContext } from '../prompt_context/types'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx index edd3615314846..2171b13273a28 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.test.tsx @@ -7,7 +7,7 @@ import { getPromptById } from './helpers'; import { mockSystemPrompt, mockSuperheroSystemPrompt } from '../../mock/system_prompt'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; describe('helpers', () => { describe('getPromptById', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx index 4a21c147332bd..f11d2e0af641a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/helpers.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; export const getPromptById = ({ prompts, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx index b1242c93e0dfb..1528435764acd 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/index.tsx @@ -10,7 +10,7 @@ import React, { useMemo } from 'react'; // eslint-disable-next-line @kbn/eslint/module_migration import styled from 'styled-components'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../..'; import type { PromptContext, SelectedPromptContext } from '../prompt_context/types'; import { SystemPrompt } from './system_prompt'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx index 465c120d187e9..bd217bb54e9f6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/helpers.tsx @@ -13,7 +13,7 @@ import styled from 'styled-components'; import { css } from '@emotion/react'; import { isEmpty } from 'lodash/fp'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { EMPTY_PROMPT } from './translations'; const Strong = styled.strong` diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx index 5cb99e6ec6155..00ed32b7305e3 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx @@ -17,7 +17,7 @@ import { TestProviders } from '../../../mock/test_providers/test_providers'; import { TEST_IDS } from '../../constants'; import { useAssistantContext } from '../../../assistant_context'; import { WELCOME_CONVERSATION } from '../../use_conversation/sample_conversations'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; const BASE_CONVERSATION: Conversation = { ...WELCOME_CONVERSATION, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx index 90b276def6315..02d4a88622163 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx @@ -10,7 +10,7 @@ import React, { useCallback, useMemo } from 'react'; import { css } from '@emotion/react'; import { isEmpty } from 'lodash/fp'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../..'; import * as i18n from './translations'; import { SelectSystemPrompt } from './select_system_prompt'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx index ca51b0d1bc84d..2c4826940a7ca 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { TEST_IDS } from '../../../../constants'; import * as i18n from './translations'; import { SYSTEM_PROMPT_DEFAULT_NEW_CONVERSATION } from '../translations'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx index 69403b74a5322..009ee6c5a83cd 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/use_system_prompt_editor.test.tsx @@ -11,7 +11,7 @@ import { mockSuperheroSystemPrompt, mockSystemPrompts, } from '../../../../mock/system_prompt'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { useAssistantContext } from '../../../../assistant_context'; jest.mock('../../../../assistant_context'); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx index 60bc81cbe976b..48d3232f0ae38 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.test.tsx @@ -11,8 +11,7 @@ import { Conversation } from '../../../../assistant_context/types'; import { AIConnector } from '../../../../connectorland/connector_selector'; import { customConvo, welcomeConvo } from '../../../../mock/conversation'; import { mockConnectors } from '../../../../mock/connectors'; -import { ApiConfig } from '@kbn/elastic-assistant-common'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { ApiConfig, PromptResponse } from '@kbn/elastic-assistant-common'; // Mock data for tests const mockSystemPrompts: PromptResponse[] = [ diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx index 05ad2360a9412..46e082b86f2c0 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/use_system_prompt_table.tsx @@ -6,7 +6,7 @@ */ import { EuiBasicTableColumn, EuiIcon, EuiLink } from '@elastic/eui'; import React, { useCallback } from 'react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../../assistant_context/types'; import { AIConnector } from '../../../../connectorland/connector_selector'; import { BadgesColumn } from '../../../common/components/assistant_settings_management/badges'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx index a9761e9de2135..fd01b8eb318a6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_settings_management/utils.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../../../assistant_context/types'; export const getSelectedConversations = ( diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx index 5cb3fbca0daee..d29887e8c4f6a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import * as i18n from './translations'; interface Props { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx index 56a1106a9752c..509db5991455f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings/use_quick_prompt_editor.test.tsx @@ -9,7 +9,7 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useQuickPromptEditor, DEFAULT_COLOR } from './use_quick_prompt_editor'; import { mockAlertPromptContext } from '../../../mock/prompt_context'; import { MOCK_QUICK_PROMPTS } from '../../../mock/quick_prompt'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { useAssistantContext } from '../../../assistant_context'; jest.mock('../../../assistant_context'); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx index 8a852a904aedc..ca647dc530265 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.test.tsx @@ -10,7 +10,7 @@ import { useQuickPromptTable } from './use_quick_prompt_table'; import { EuiTableComputedColumnType } from '@elastic/eui'; import { MOCK_QUICK_PROMPTS } from '../../../mock/quick_prompt'; import { mockPromptContexts } from '../../../mock/prompt_context'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; const mockOnEditActionClicked = jest.fn(); const mockOnDeleteActionClicked = jest.fn(); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx index fb3138ccab56a..1899905db0ea1 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_settings_management/use_quick_prompt_table.tsx @@ -7,7 +7,7 @@ import { EuiBasicTableColumn, EuiLink } from '@elastic/eui'; import React, { useCallback } from 'react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { BadgesColumn } from '../../common/components/assistant_settings_management/badges'; import { RowActions } from '../../common/components/assistant_settings_management/row_actions'; import { PromptContextTemplate } from '../../prompt_context/types'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx index 5fb6255559aa6..d5bbefe304208 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings.tsx @@ -23,7 +23,7 @@ import { // eslint-disable-next-line @kbn/eslint/module_migration import styled from 'styled-components'; import { css } from '@emotion/react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { AIConnector } from '../../connectorland/connector_selector'; import { Conversation, useLoadConnectors } from '../../..'; import * as i18n from './translations'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx index a932db0b195a7..ccb1769d6e3de 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx @@ -19,7 +19,7 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../..'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx index b9aefa9c422ae..0a2c72ba80ac4 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx @@ -11,7 +11,7 @@ import { alertConvo, welcomeConvo } from '../../../mock/conversation'; import { useSettingsUpdater } from './use_settings_updater'; import { defaultQuickPrompt, mockSystemPrompt } from '../../../mock/system_prompt'; import { HttpSetup } from '@kbn/core/public'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; const mockConversations = { [alertConvo.title]: alertConvo, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts index 6e96270b827ed..3e997fef5d573 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.test.ts @@ -14,7 +14,7 @@ import { } from './helpers'; import { AIConnector } from '../../connectorland/connector_selector'; import { Conversation } from '../../..'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; const tilde = '`'; const codeDelimiter = '```'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts index 31da9e30ae535..86e5ab3ba0a92 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts @@ -6,7 +6,7 @@ */ import React from 'react'; -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../assistant_context/types'; import { AIConnector } from '../../connectorland/connector_selector'; import { getGenAiConfig } from '../../connectorland/helpers'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts b/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts index 6607c1987403f..04b027cbfe578 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/system_prompt/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; export const mockSystemPrompt: PromptResponse = { id: 'mock-system-prompt-1', diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts b/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts index e0f326f4e4f38..1f7c96126bc10 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/user_prompt/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { PromptResponse } from '@kbn/elastic-assistant-common'; export const mockUserPrompt: PromptResponse = { id: 'mock-user-prompt-1', diff --git a/x-pack/plugins/security_solution/public/assistant/content/prompts/system/index.tsx b/x-pack/plugins/security_solution/public/assistant/content/prompts/system/index.tsx index f7192c58bf004..ee9d4018365c5 100644 --- a/x-pack/plugins/security_solution/public/assistant/content/prompts/system/index.tsx +++ b/x-pack/plugins/security_solution/public/assistant/content/prompts/system/index.tsx @@ -5,7 +5,11 @@ * 2.0. */ -import type { PromptResponse } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { + PromptTypeEnum, + type PromptResponse, +} from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { APP_UI_ID } from '../../../../../common'; import { DEFAULT_SYSTEM_PROMPT_NAME, DEFAULT_SYSTEM_PROMPT_NON_I18N, @@ -21,17 +25,17 @@ export const BASE_SECURITY_SYSTEM_PROMPTS: PromptResponse[] = [ id: 'default-system-prompt', content: DEFAULT_SYSTEM_PROMPT_NON_I18N, name: DEFAULT_SYSTEM_PROMPT_NAME, - promptType: 'system', + promptType: PromptTypeEnum.system, isDefault: true, isNewConversationDefault: true, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, { id: 'CB9FA555-B59F-4F71-AFF9-8A891AC5BC28', content: SUPERHERO_SYSTEM_PROMPT_NON_I18N, name: SUPERHERO_SYSTEM_PROMPT_NAME, - promptType: 'system', - consumer: 'securitySolutionUI', + promptType: PromptTypeEnum.system, + consumer: APP_UI_ID, isDefault: true, }, ]; diff --git a/x-pack/plugins/security_solution/public/assistant/content/quick_prompts/index.tsx b/x-pack/plugins/security_solution/public/assistant/content/quick_prompts/index.tsx index 6b41b3648e37f..adb952d661214 100644 --- a/x-pack/plugins/security_solution/public/assistant/content/quick_prompts/index.tsx +++ b/x-pack/plugins/security_solution/public/assistant/content/quick_prompts/index.tsx @@ -9,6 +9,7 @@ import { PromptTypeEnum, type PromptResponse, } from '@kbn/elastic-assistant-common/impl/schemas/prompts/bulk_crud_prompts_route.gen'; +import { APP_UI_ID } from '../../../../common'; import * as i18n from './translations'; import { KNOWLEDGE_BASE_CATEGORY, @@ -31,7 +32,7 @@ export const BASE_SECURITY_QUICK_PROMPTS: PromptResponse[] = [ isDefault: true, id: i18n.ALERT_SUMMARIZATION_TITLE, promptType: PromptTypeEnum.quick, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, { name: i18n.ESQL_QUERY_GENERATION_TITLE, @@ -41,7 +42,7 @@ export const BASE_SECURITY_QUICK_PROMPTS: PromptResponse[] = [ isDefault: true, id: i18n.ESQL_QUERY_GENERATION_TITLE, promptType: PromptTypeEnum.quick, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, { name: i18n.RULE_CREATION_TITLE, @@ -51,7 +52,7 @@ export const BASE_SECURITY_QUICK_PROMPTS: PromptResponse[] = [ isDefault: true, id: i18n.RULE_CREATION_TITLE, promptType: PromptTypeEnum.quick, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, { name: i18n.WORKFLOW_ANALYSIS_TITLE, @@ -60,7 +61,7 @@ export const BASE_SECURITY_QUICK_PROMPTS: PromptResponse[] = [ isDefault: true, id: i18n.WORKFLOW_ANALYSIS_TITLE, promptType: PromptTypeEnum.quick, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, { name: i18n.THREAT_INVESTIGATION_GUIDES_TITLE, @@ -70,7 +71,7 @@ export const BASE_SECURITY_QUICK_PROMPTS: PromptResponse[] = [ isDefault: true, id: i18n.THREAT_INVESTIGATION_GUIDES_TITLE, promptType: PromptTypeEnum.quick, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, { name: i18n.SPL_QUERY_CONVERSION_TITLE, @@ -79,7 +80,7 @@ export const BASE_SECURITY_QUICK_PROMPTS: PromptResponse[] = [ isDefault: true, id: i18n.SPL_QUERY_CONVERSION_TITLE, promptType: PromptTypeEnum.quick, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, { name: i18n.AUTOMATION_TITLE, @@ -88,6 +89,6 @@ export const BASE_SECURITY_QUICK_PROMPTS: PromptResponse[] = [ isDefault: true, id: i18n.AUTOMATION_TITLE, promptType: PromptTypeEnum.quick, - consumer: 'securitySolutionUI', + consumer: APP_UI_ID, }, ]; From 81534c6ecfa1fd8448d84fdf144dba1e142c2325 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 10:51:15 -0700 Subject: [PATCH 16/22] - --- .../impl/assistant/api/prompts/use_fetch_prompts.ts | 2 +- .../impl/assistant/use_conversation/index.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts index df11bad4689f0..18a229e524dc7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.ts @@ -21,7 +21,7 @@ export interface UseFetchPromptsParams { * API call for fetching prompts for current spaceId * * @param {Object} options - The options object. - * @param {HttpSetup} options.http - HttpSetup + * @param {string} options.consumer - prompt consumer * @param {AbortSignal} [options.signal] - AbortSignal * * @returns {useQuery} hook for getting the status of the prompts diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx index 5906d28a76aa7..a276aea3ff4ab 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.tsx @@ -65,7 +65,9 @@ interface UseConversation { export const useConversation = (): UseConversation => { const { http, toasts } = useAssistantContext(); - const { data: allPrompts } = useFetchPrompts(); + const { + data: { data: allPrompts }, + } = useFetchPrompts(); const getConversation = useCallback( async (conversationId: string, silent?: boolean) => { @@ -103,7 +105,7 @@ export const useConversation = (): UseConversation => { async (conversation: Conversation) => { if (conversation.apiConfig) { const defaultSystemPromptId = getDefaultSystemPrompt({ - allSystemPrompts: allPrompts.data, + allSystemPrompts: allPrompts, conversation, })?.id; @@ -117,7 +119,7 @@ export const useConversation = (): UseConversation => { }); } }, - [allPrompts.data, http, toasts] + [allPrompts, http, toasts] ); /** From 4c993d8245f5e1e27155f4c899231f0e31fa7b2f Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 10:55:39 -0700 Subject: [PATCH 17/22] fixed tests --- .../system_prompt_selector/system_prompt_selector.test.tsx | 4 ++-- .../quick_prompt_selector/quick_prompt_selector.test.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx index 37e5fb5a131a4..cbf5efe79213f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/system_prompt_modal/system_prompt_selector/system_prompt_selector.test.tsx @@ -35,7 +35,7 @@ describe('SystemPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete system prompt because there is only one custom option fireEvent.click(getAllByTestId('delete-prompt')[1]); - expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[0].id); + expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[1].id); expect(onSystemPromptSelectionChange).not.toHaveBeenCalled(); }); it('Deletes a system prompt that is selected', () => { @@ -43,7 +43,7 @@ describe('SystemPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete system prompt because there is only one custom option fireEvent.click(getAllByTestId('delete-prompt')[0]); - expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[1].id); + expect(onSystemPromptDeleted).toHaveBeenCalledWith(mockSystemPrompts[0].id); expect(onSystemPromptSelectionChange).toHaveBeenCalledWith(undefined); }); it('Selects existing system prompt from the search input', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx index 033028104e002..941b442ce4d48 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/quick_prompts/quick_prompt_selector/quick_prompt_selector.test.tsx @@ -35,7 +35,7 @@ describe('QuickPromptSelector', () => { fireEvent.click(getByTestId('comboBoxToggleListButton')); // there is only one delete quick prompt because there is only one custom option fireEvent.click(getByTestId('delete-quick-prompt')); - expect(onQuickPromptDeleted).toHaveBeenCalledWith('ALERT_SUMMARIZATION_TITLE'); + expect(onQuickPromptDeleted).toHaveBeenCalledWith('A_CUSTOM_OPTION'); }); it('Selects existing quick prompt from the search input', () => { const { getByTestId } = render(); From 09c97f01d38bfda3d6ab17d8a057025626050e8b Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 13:11:08 -0700 Subject: [PATCH 18/22] fixed default prompt --- .../prompt_editor/system_prompt/index.tsx | 7 ++--- .../select_system_prompt/index.tsx | 14 +++------- .../use_settings_updater.tsx | 28 ++++++++++++++++--- .../assistant/use_conversation/helpers.ts | 2 +- .../public/assistant/provider.tsx | 1 + 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx index 02d4a88622163..250efe8cac3aa 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.tsx @@ -36,12 +36,9 @@ const SystemPromptComponent: React.FC = ({ }) => { const selectedPrompt = useMemo(() => { if (editingSystemPromptId !== undefined) { - return ( - allSystemPrompts?.find((p) => p.id === editingSystemPromptId) ?? - allSystemPrompts?.find((p) => p.id === conversation?.apiConfig?.defaultSystemPromptId) - ); + return allSystemPrompts?.find((p) => p.id === editingSystemPromptId); } else { - return undefined; + return allSystemPrompts?.find((p) => p.id === conversation?.apiConfig?.defaultSystemPromptId); } }, [allSystemPrompts, conversation?.apiConfig?.defaultSystemPromptId, editingSystemPromptId]); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.tsx index d016d096da7fb..0296fa3e636ca 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/select_system_prompt/index.tsx @@ -77,20 +77,18 @@ const SelectSystemPromptComponent: React.FC = ({ ); const [isOpenLocal, setIsOpenLocal] = useState(isOpen); - const [valueOfSelected, setValueOfSelected] = useState( - selectedPrompt?.id ?? allSystemPrompts?.[0]?.id - ); const handleOnBlur = useCallback(() => setIsOpenLocal(false), []); + const valueOfSelected = useMemo(() => selectedPrompt?.id, [selectedPrompt?.id]); // Write the selected system prompt to the conversation config const setSelectedSystemPrompt = useCallback( - (prompt: PromptResponse | undefined) => { + (promptId?: string) => { if (conversation && conversation.apiConfig) { setApiConfig({ conversation, apiConfig: { ...conversation.apiConfig, - defaultSystemPromptId: prompt?.id, + defaultSystemPromptId: promptId, }, }); } @@ -134,14 +132,11 @@ const SelectSystemPromptComponent: React.FC = ({ // Note: if callback is provided, this component does not persist. Extract to separate component if (onSystemPromptSelectionChange != null) { onSystemPromptSelectionChange(selectedSystemPromptId); - } else { - setSelectedSystemPrompt(allSystemPrompts.find((sp) => sp.id === selectedSystemPromptId)); } - setValueOfSelected(selectedSystemPromptId); + setSelectedSystemPrompt(selectedSystemPromptId); setIsEditing?.(false); }, [ - allSystemPrompts, onSystemPromptSelectionChange, setIsEditing, setIsSettingsModalVisible, @@ -154,7 +149,6 @@ const SelectSystemPromptComponent: React.FC = ({ setSelectedSystemPrompt(undefined); setIsEditing?.(false); clearSelectedSystemPrompt?.(); - setValueOfSelected(undefined); }, [clearSelectedSystemPrompt, setIsEditing, setSelectedSystemPrompt]); const onShowSelectSystemPrompt = useCallback(() => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx index e9f65160e6d29..a6df045de8017 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx @@ -140,6 +140,30 @@ export const useSettingsUpdater = ( * Save all pending settings */ const saveSettings = useCallback(async (): Promise => { + const bulkPromptsResult = hasBulkPrompts + ? await bulkUpdatePrompts(http, promptsBulkActions, toasts) + : undefined; + + // replace conversation references for created + if (bulkPromptsResult) { + bulkPromptsResult.attributes.results.created.forEach((p) => { + if (conversationsSettingsBulkActions.create) { + Object.values(conversationsSettingsBulkActions.create).forEach((c) => { + if (c.apiConfig?.defaultSystemPromptId === p.name) { + c.apiConfig.defaultSystemPromptId = p.id; + } + }); + } + if (conversationsSettingsBulkActions.update) { + Object.values(conversationsSettingsBulkActions.update).forEach((c) => { + if (c.apiConfig?.defaultSystemPromptId === p.name) { + c.apiConfig.defaultSystemPromptId = p.id; + } + }); + } + }); + } + const bulkResult = hasBulkConversations ? await bulkUpdateConversations(http, conversationsSettingsBulkActions, toasts) : undefined; @@ -170,10 +194,6 @@ export const useSettingsUpdater = ( ? await bulkUpdateAnonymizationFields(http, anonymizationFieldsBulkActions, toasts) : undefined; - const bulkPromptsResult = hasBulkPrompts - ? await bulkUpdatePrompts(http, promptsBulkActions, toasts) - : undefined; - return ( (bulkResult?.success ?? true) && (bulkAnonymizationFieldsResult?.success ?? true) && diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts index 86e5ab3ba0a92..fde1c1d3d943c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/helpers.ts @@ -96,7 +96,7 @@ export const getDefaultSystemPrompt = ({ ); const defaultNewSystemPrompt = getDefaultNewSystemPrompt(allSystemPrompts); - return conversationSystemPrompt ?? defaultNewSystemPrompt; + return conversationSystemPrompt?.id ? conversationSystemPrompt : defaultNewSystemPrompt; }; /** diff --git a/x-pack/plugins/security_solution/public/assistant/provider.tsx b/x-pack/plugins/security_solution/public/assistant/provider.tsx index 2749e631604c8..3413549cd2a67 100644 --- a/x-pack/plugins/security_solution/public/assistant/provider.tsx +++ b/x-pack/plugins/security_solution/public/assistant/provider.tsx @@ -176,6 +176,7 @@ export const AssistantProvider: FC> = ({ children }) const createSecurityPrompts = once(async () => { const res = await getPrompts({ http, + toasts: notifications.toasts, }); if ( assistantAvailability.isAssistantEnabled && From 75af95fb6dc58d8e8859a1c9c95885b1d06f2bfe Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 17:01:40 -0700 Subject: [PATCH 19/22] fixed test and stack management page --- .../impl/schemas/index.ts | 2 +- .../system_prompt/index.test.tsx | 6 ++--- .../prompt_editor/system_prompt/index.tsx | 4 +-- .../assistant_settings_management.tsx | 22 +++++++++++++--- .../use_settings_updater.tsx | 26 +++++++------------ 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts index f337dc6deaf89..0f3805554a00c 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts @@ -51,4 +51,4 @@ export * from './knowledge_base/crud_knowledge_base_route.gen'; export * from './knowledge_base/find_knowledge_base_entries_route.gen'; export * from './prompts/find_prompts_route.gen'; -export { PromptResponse } from './prompts/bulk_crud_prompts_route.gen'; +export { PromptResponse, PromptTypeEnum } from './prompts/bulk_crud_prompts_route.gen'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx index 00ed32b7305e3..34d40852ba505 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/prompt_editor/system_prompt/index.test.tsx @@ -118,7 +118,7 @@ describe('SystemPrompt', () => { render( { { = ({ }) => { const selectedPrompt = useMemo(() => { if (editingSystemPromptId !== undefined) { - return allSystemPrompts?.find((p) => p.id === editingSystemPromptId); + return allSystemPrompts.find((p) => p.id === editingSystemPromptId); } else { - return allSystemPrompts?.find((p) => p.id === conversation?.apiConfig?.defaultSystemPromptId); + return allSystemPrompts.find((p) => p.id === conversation?.apiConfig?.defaultSystemPromptId); } }, [allSystemPrompts, conversation?.apiConfig?.defaultSystemPromptId, editingSystemPromptId]); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx index ccb1769d6e3de..3f9be4972fe7e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.tsx @@ -19,7 +19,7 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; -import { PromptResponse } from '@kbn/elastic-assistant-common'; +import { PromptResponse, PromptTypeEnum } from '@kbn/elastic-assistant-common'; import { Conversation } from '../../..'; import * as i18n from './translations'; import { useAssistantContext } from '../../assistant_context'; @@ -115,6 +115,22 @@ export const AssistantSettingsManagement: React.FC = React.memo( anonymizationFields ?? { page: 0, perPage: 0, total: 0, data: [] } ); + const quickPrompts = useMemo( + () => + quickPromptSettings.length === 0 + ? allPrompts.data.filter((p) => p.promptType === PromptTypeEnum.quick) + : quickPromptSettings, + [allPrompts.data, quickPromptSettings] + ); + + const systemPrompts = useMemo( + () => + systemPromptSettings.length === 0 + ? allPrompts.data.filter((p) => p.promptType === PromptTypeEnum.system) + : systemPromptSettings, + [allPrompts.data, systemPromptSettings] + ); + // Local state for saving previously selected items so tab switching is friendlier // Conversation Selection State const [selectedConversation, setSelectedConversation] = useState( @@ -311,7 +327,7 @@ export const AssistantSettingsManagement: React.FC = React.memo( setConversationSettings={setConversationSettings} setConversationsSettingsBulkActions={setConversationsSettingsBulkActions} setUpdatedSystemPromptSettings={setUpdatedSystemPromptSettings} - systemPromptSettings={systemPromptSettings} + systemPromptSettings={systemPrompts} promptsBulkActions={promptsBulkActions} setPromptsBulkActions={setPromptsBulkActions} /> @@ -321,7 +337,7 @@ export const AssistantSettingsManagement: React.FC = React.memo( handleSave={handleSave} onCancelClick={onCancelClick} onSelectedQuickPromptChange={onHandleSelectedQuickPromptChange} - quickPromptSettings={quickPromptSettings} + quickPromptSettings={quickPrompts} resetSettings={resetSettings} selectedQuickPrompt={selectedQuickPrompt} setUpdatedQuickPromptSettings={setUpdatedQuickPromptSettings} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx index a6df045de8017..1ae1c9e5b1b73 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.tsx @@ -55,7 +55,7 @@ interface UseSettingsUpdater { export const useSettingsUpdater = ( conversations: Record, - allSystemPrompts: FindPromptsResponse, + allPrompts: FindPromptsResponse, conversationsLoaded: boolean, anonymizationFields: FindAnonymizationFieldsResponse ): UseSettingsUpdater => { @@ -79,12 +79,12 @@ export const useSettingsUpdater = ( const [conversationsSettingsBulkActions, setConversationsSettingsBulkActions] = useState({}); // Quick Prompts - const [updatedQuickPromptSettings, setUpdatedQuickPromptSettings] = useState( - allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.quick) + const [quickPromptSettings, setUpdatedQuickPromptSettings] = useState( + allPrompts.data.filter((p) => p.promptType === PromptTypeEnum.quick) ); // System Prompts - const [updatedSystemPromptSettings, setUpdatedSystemPromptSettings] = useState( - allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.system) + const [systemPromptSettings, setUpdatedSystemPromptSettings] = useState( + allPrompts.data.filter((p) => p.promptType === PromptTypeEnum.system) ); // Anonymization const [anonymizationFieldsBulkActions, setAnonymizationFieldsBulkActions] = @@ -108,21 +108,15 @@ export const useSettingsUpdater = ( setConversationSettings(conversations); setConversationsSettingsBulkActions({}); setUpdatedQuickPromptSettings( - allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.quick) + allPrompts.data.filter((p) => p.promptType === PromptTypeEnum.quick) ); setUpdatedKnowledgeBaseSettings(knowledgeBase); setUpdatedAssistantStreamingEnabled(assistantStreamingEnabled); setUpdatedSystemPromptSettings( - allSystemPrompts.data.filter((p) => p.promptType === PromptTypeEnum.system) + allPrompts.data.filter((p) => p.promptType === PromptTypeEnum.system) ); setUpdatedAnonymizationData(anonymizationFields); - }, [ - allSystemPrompts, - anonymizationFields, - assistantStreamingEnabled, - conversations, - knowledgeBase, - ]); + }, [allPrompts, anonymizationFields, assistantStreamingEnabled, conversations, knowledgeBase]); const hasBulkConversations = conversationsSettingsBulkActions.create || @@ -246,9 +240,9 @@ export const useSettingsUpdater = ( conversationsSettingsBulkActions, knowledgeBase: updatedKnowledgeBaseSettings, assistantStreamingEnabled: updatedAssistantStreamingEnabled, - quickPromptSettings: updatedQuickPromptSettings, + quickPromptSettings, resetSettings, - systemPromptSettings: updatedSystemPromptSettings, + systemPromptSettings, saveSettings, updatedAnonymizationData, setUpdatedAnonymizationData, From e26b0c5b1d0f9f6bb649484cc74244bb8b3c7ceb Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Tue, 2 Jul 2024 19:07:14 -0700 Subject: [PATCH 20/22] fixed test --- .../assistant/settings/assistant_settings_management.test.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx index 3b34b3467aa84..15fb05ca1c807 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/assistant_settings_management.test.tsx @@ -23,6 +23,7 @@ import { QUICK_PROMPTS_TAB, SYSTEM_PROMPTS_TAB, } from './const'; +import { mockSystemPrompts } from '../../mock/system_prompt'; const mockConversations = { [alertConvo.title]: alertConvo, @@ -33,6 +34,8 @@ const saveSettings = jest.fn(); const mockValues = { conversationSettings: mockConversations, saveSettings, + systemPromptSettings: mockSystemPrompts, + quickPromptSettings: [], }; const setSelectedSettingsTab = jest.fn(); From e87383ee6ed5bf9d3bf422d1d24397a660efe0c9 Mon Sep 17 00:00:00 2001 From: Patryk Kopycinski Date: Wed, 3 Jul 2024 16:42:08 +0200 Subject: [PATCH 21/22] fix Error fetching prompts toast --- .../public/assistant/provider.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/public/assistant/provider.tsx b/x-pack/plugins/security_solution/public/assistant/provider.tsx index 3413549cd2a67..9b0b9db40fbf7 100644 --- a/x-pack/plugins/security_solution/public/assistant/provider.tsx +++ b/x-pack/plugins/security_solution/public/assistant/provider.tsx @@ -174,16 +174,15 @@ export const AssistantProvider: FC> = ({ children }) useEffect(() => { const createSecurityPrompts = once(async () => { - const res = await getPrompts({ - http, - toasts: notifications.toasts, - }); - if ( - assistantAvailability.isAssistantEnabled && - assistantAvailability.hasAssistantPrivilege && - res.total === 0 - ) { - await createBasePrompts(notifications, http); + if (assistantAvailability.isAssistantEnabled && assistantAvailability.hasAssistantPrivilege) { + const res = await getPrompts({ + http, + toasts: notifications.toasts, + }); + + if (res.total === 0) { + await createBasePrompts(notifications, http); + } } }); createSecurityPrompts(); From 05d97d4aeb3aac5a1dcfec035cb9cae34223d567 Mon Sep 17 00:00:00 2001 From: YulNaumenko Date: Wed, 3 Jul 2024 07:52:43 -0700 Subject: [PATCH 22/22] added license check --- .../public/assistant/provider.tsx | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/public/assistant/provider.tsx b/x-pack/plugins/security_solution/public/assistant/provider.tsx index 9b0b9db40fbf7..134bfb25c15ac 100644 --- a/x-pack/plugins/security_solution/public/assistant/provider.tsx +++ b/x-pack/plugins/security_solution/public/assistant/provider.tsx @@ -36,6 +36,7 @@ import { PROMPT_CONTEXTS } from './content/prompt_contexts'; import { useAssistantAvailability } from './use_assistant_availability'; import { useAppToasts } from '../common/hooks/use_app_toasts'; import { useSignalIndex } from '../detections/containers/detection_engine/alerts/use_signal_index'; +import { licenseService } from '../common/hooks/use_license'; const ASSISTANT_TITLE = i18n.translate('xpack.securitySolution.assistant.title', { defaultMessage: 'Elastic AI Assistant', @@ -149,24 +150,27 @@ export const AssistantProvider: FC> = ({ children }) const assistantAvailability = useAssistantAvailability(); const assistantTelemetry = useAssistantTelemetry(); const currentAppId = useObservable(currentAppId$, ''); - + const hasEnterpriseLicence = licenseService.isEnterprise(); useEffect(() => { const migrateConversationsFromLocalStorage = once(async () => { - const res = await getUserConversations({ - http, - }); if ( + hasEnterpriseLicence && assistantAvailability.isAssistantEnabled && - assistantAvailability.hasAssistantPrivilege && - res.total === 0 + assistantAvailability.hasAssistantPrivilege ) { - await createConversations(notifications, http, storage); + const res = await getUserConversations({ + http, + }); + if (res.total === 0) { + await createConversations(notifications, http, storage); + } } }); migrateConversationsFromLocalStorage(); }, [ assistantAvailability.hasAssistantPrivilege, assistantAvailability.isAssistantEnabled, + hasEnterpriseLicence, http, notifications, storage, @@ -174,7 +178,11 @@ export const AssistantProvider: FC> = ({ children }) useEffect(() => { const createSecurityPrompts = once(async () => { - if (assistantAvailability.isAssistantEnabled && assistantAvailability.hasAssistantPrivilege) { + if ( + hasEnterpriseLicence && + assistantAvailability.isAssistantEnabled && + assistantAvailability.hasAssistantPrivilege + ) { const res = await getPrompts({ http, toasts: notifications.toasts, @@ -189,6 +197,7 @@ export const AssistantProvider: FC> = ({ children }) }, [ assistantAvailability.hasAssistantPrivilege, assistantAvailability.isAssistantEnabled, + hasEnterpriseLicence, http, notifications, ]);