Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
*/

import { HttpSetup } from '@kbn/core/public';
import { API_VERSIONS, ApiConfig, Replacements } from '@kbn/elastic-assistant-common';
import {
API_VERSIONS,
ApiConfig,
MessageMetadata,
Replacements,
} from '@kbn/elastic-assistant-common';
import { API_ERROR } from '../translations';
import { getOptionalRequestParams } from '../helpers';
import { TraceOptions } from '../types';
Expand Down Expand Up @@ -34,6 +39,7 @@ export interface FetchConnectorExecuteResponse {
transactionId: string;
traceId: string;
};
metadata?: MessageMetadata;
}

export const fetchConnectorExecuteAction = async ({
Expand Down Expand Up @@ -110,6 +116,7 @@ export const fetchConnectorExecuteAction = async ({
transaction_id: string;
trace_id: string;
};
metadata?: MessageMetadata;
}>(`/internal/elastic_assistant/actions/connector/${apiConfig?.connectorId}/_execute`, {
method: 'POST',
body: JSON.stringify(requestBody),
Expand Down Expand Up @@ -144,6 +151,7 @@ export const fetchConnectorExecuteAction = async ({

return {
response: response.data,
metadata: response.metadata,
isError: false,
isStream: false,
traceData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,11 @@ export const AssistantHeader: React.FC<Props> = ({
/>
</EuiFlexItem>
<EuiFlexItem id={AI_ASSISTANT_SETTINGS_MENU_CONTAINER_ID}>
<SettingsContextMenu isDisabled={isDisabled} onChatCleared={onChatCleared} />
<SettingsContextMenu
isDisabled={isDisabled}
onChatCleared={onChatCleared}
selectedConversation={selectedConversation}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,25 +84,6 @@ export const CHAT_OPTIONS = i18n.translate(
}
);

const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0;

export const ANONYMIZE_VALUES_TOOLTIP = i18n.translate(
'xpack.elasticAssistant.assistant.settings.anonymizeValues.tooltip',
{
values: { keyboardShortcut: isMac ? '⌥ + a' : 'Alt + a' },
defaultMessage:
'Toggle to reveal or hide field values in your chat stream. The data sent to the LLM is still anonymized based on settings in the Anonymization panel. Keyboard shortcut: {keyboardShortcut}',
}
);

export const SHOW_CITATIONS_TOOLTIP = i18n.translate(
'xpack.elasticAssistant.assistant.settings.showCitationsLabel.tooltip',
{
values: { keyboardShortcut: isMac ? '⌥ + c' : 'Alt + c' },
defaultMessage: 'Keyboard shortcut: {keyboardShortcut}',
}
);

export const CANCEL_BUTTON_TEXT = i18n.translate(
'xpack.elasticAssistant.assistant.resetConversationModal.cancelButtonText',
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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 { alertConvo, conversationWithContentReferences } from '../../../mock/conversation';
import { Conversation } from '../../../..';
import { conversationContainsContentReferences, conversationContainsAnonymizedValues } from '.';

describe('conversation utils', () => {
it.each([
[undefined, false],
[conversationWithContentReferences, true],
[alertConvo, false],
])(
'conversationContainsContentReferences',
(conversation: Conversation | undefined, expected: boolean) => {
expect(conversationContainsContentReferences(conversation)).toBe(expected);
}
);

it.each([
[undefined, false],
[conversationWithContentReferences, false],
[alertConvo, true],
])(
'conversationContainsAnonymizedValues',
(conversation: Conversation | undefined, expected: boolean) => {
expect(conversationContainsAnonymizedValues(conversation)).toBe(expected);
}
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 { isEmpty } from 'lodash';
import { Conversation } from '../../../..';

export const conversationContainsContentReferences = (conversation?: Conversation): boolean => {
return (
conversation?.messages.some((message) => !isEmpty(message.metadata?.contentReferences)) ?? false
);
};

/** Checks if the conversations has replacements, not if the replacements are actually used */
export const conversationContainsAnonymizedValues = (conversation?: Conversation): boolean => {
return !isEmpty(conversation?.replacements);
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const getMessageFromRawResponse = (
timestamp: dateTimeString,
isError,
traceData: rawResponse.traceData,
metadata: rawResponse.metadata,
};
} else {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ import { ConversationSidePanel } from './conversations/conversation_sidepanel';
import { SelectedPromptContexts } from './prompt_editor/selected_prompt_contexts';
import { AssistantHeader } from './assistant_header';
import { AnonymizedValuesAndCitationsTour } from '../tour/anonymized_values_and_citations_tour';
import {
conversationContainsAnonymizedValues,
conversationContainsContentReferences,
} from './conversations/utils';

export const CONVERSATION_SIDE_PANEL_WIDTH = 220;

Expand Down Expand Up @@ -227,10 +231,12 @@ const AssistantComponent: React.FC<Props> = ({
const onKeyDown = useCallback(
(event: KeyboardEvent) => {
if (event.altKey && event.code === 'KeyC') {
if (!conversationContainsContentReferences(currentConversation)) return;
event.preventDefault();
setContentReferencesVisible(!contentReferencesVisible);
}
if (event.altKey && event.code === 'KeyA') {
if (!conversationContainsAnonymizedValues(currentConversation)) return;
event.preventDefault();
setShowAnonymizedValues(!showAnonymizedValues);
}
Expand All @@ -240,6 +246,7 @@ const AssistantComponent: React.FC<Props> = ({
contentReferencesVisible,
setShowAnonymizedValues,
showAnonymizedValues,
currentConversation,
]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,42 @@ import {
EuiHorizontalRule,
EuiToolTip,
EuiSwitchEvent,
EuiIcon,
} from '@elastic/eui';
import { css } from '@emotion/react';
import { FormattedMessage } from '@kbn/i18n-react';
import { KnowledgeBaseTour } from '../../../tour/knowledge_base';
import { AnonymizationSettingsManagement } from '../../../data_anonymization/settings/anonymization_settings_management';
import { useAssistantContext } from '../../../..';
import { Conversation, useAssistantContext } from '../../../..';
import * as i18n from '../../assistant_header/translations';
import { AlertsSettingsModal } from '../alerts_settings/alerts_settings_modal';
import { KNOWLEDGE_BASE_TAB } from '../const';
import { AI_ASSISTANT_MENU } from './translations';
import {
conversationContainsAnonymizedValues,
conversationContainsContentReferences,
} from '../../conversations/utils';

interface Params {
isDisabled?: boolean;
onChatCleared?: () => void;
selectedConversation?: Conversation;
}

const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0;

const ConditionalWrap = ({
condition,
wrap,
children,
}: {
condition: boolean;
wrap: (children: React.ReactElement) => React.ReactElement;
children: React.ReactElement;
}) => (condition ? wrap(children) : children);

export const SettingsContextMenu: React.FC<Params> = React.memo(
({ isDisabled = false, onChatCleared }: Params) => {
({ isDisabled = false, onChatCleared, selectedConversation }: Params) => {
const { euiTheme } = useEuiTheme();
const {
navigateToApp,
Expand Down Expand Up @@ -117,6 +136,16 @@ export const SettingsContextMenu: React.FC<Params> = React.memo(
[setShowAnonymizedValues]
);

const selectedConversationHasCitations = useMemo(
() => conversationContainsContentReferences(selectedConversation),
[selectedConversation]
);

const selectedConversationHasAnonymizedValues = useMemo(
() => conversationContainsAnonymizedValues(selectedConversation),
[selectedConversation]
);

const items = useMemo(
() => [
<EuiContextMenuItem
Expand Down Expand Up @@ -174,43 +203,114 @@ export const SettingsContextMenu: React.FC<Params> = React.memo(
<h3>{i18n.CHAT_OPTIONS}</h3>
</EuiTitle>
<EuiHorizontalRule margin="none" />
<EuiToolTip
position="left"
key={'anonymize-values-tooltip'}
content={i18n.ANONYMIZE_VALUES_TOOLTIP}
<EuiContextMenuItem
aria-label={'anonymize-values'}
key={'anonymize-values'}
data-test-subj={'anonymize-values'}
>
<EuiFlexGroup direction="row" gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}>
<ConditionalWrap
condition={!selectedConversationHasAnonymizedValues}
wrap={(children) => (
<EuiToolTip
position="top"
key={'disabled-anonymize-values-tooltip'}
content={
<FormattedMessage
id="xpack.elasticAssistant.assistant.settings.anonymizeValues.disabled.tooltip"
defaultMessage="This conversation does not contain anonymized fields."
/>
}
>
{children}
</EuiToolTip>
)}
>
<EuiSwitch
label={i18n.ANONYMIZE_VALUES}
checked={showAnonymizedValues}
onChange={onChangeShowAnonymizedValues}
compressed
disabled={!selectedConversationHasAnonymizedValues}
/>
</ConditionalWrap>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
key={'anonymize-values-tooltip'}
content={
<FormattedMessage
id="xpack.elasticAssistant.assistant.settings.anonymizeValues.tooltip"
defaultMessage="Toggle to reveal or obfuscate field values in your chat stream. The data sent to the LLM is still anonymized based on settings in the Anonymization panel. Keyboard shortcut: <bold>{keyboardShortcut}</bold>"
values={{
keyboardShortcut: isMac ? '⌥ + a' : 'Alt + a',
bold: (str) => <strong>{str}</strong>,
}}
/>
}
>
<EuiIcon tabIndex={0} type="iInCircle" />
</EuiToolTip>
</EuiFlexItem>
</EuiFlexGroup>
</EuiContextMenuItem>

{contentReferencesEnabled && (
<EuiContextMenuItem
aria-label={'anonymize-values'}
key={'anonymize-values'}
data-test-subj={'anonymize-values'}
aria-label={'show-citations'}
key={'show-citations'}
data-test-subj={'show-citations'}
>
<EuiSwitch
label={i18n.ANONYMIZE_VALUES}
checked={showAnonymizedValues}
onChange={onChangeShowAnonymizedValues}
compressed
/>
<EuiFlexGroup direction="row" gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}>
<ConditionalWrap
condition={!selectedConversationHasCitations}
wrap={(children) => (
<EuiToolTip
position="top"
key={'disabled-anonymize-values-tooltip'}
content={
<FormattedMessage
id="xpack.elasticAssistant.assistant.settings.showCitationsLabel.disabled.tooltip"
defaultMessage="This conversation does not contain citations."
/>
}
>
{children}
</EuiToolTip>
)}
>
<EuiSwitch
label={i18n.SHOW_CITATIONS}
checked={contentReferencesVisible}
onChange={onChangeContentReferencesVisible}
compressed
disabled={!selectedConversationHasCitations}
/>
</ConditionalWrap>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
key={'show-citations-tooltip'}
content={
<FormattedMessage
id="xpack.elasticAssistant.assistant.settings.showCitationsLabel.tooltip"
defaultMessage="Keyboard shortcut: <bold>{keyboardShortcut}</bold>"
values={{
keyboardShortcut: isMac ? '⌥ + c' : 'Alt + c',
bold: (str) => <strong>{str}</strong>,
}}
/>
}
>
<EuiIcon tabIndex={0} type="iInCircle" />
</EuiToolTip>
</EuiFlexItem>
</EuiFlexGroup>
</EuiContextMenuItem>
</EuiToolTip>
{contentReferencesEnabled && (
<EuiToolTip
position="left"
key={'show-citations-tooltip'}
content={i18n.SHOW_CITATIONS_TOOLTIP}
>
<EuiContextMenuItem
aria-label={'show-citations'}
key={'show-citations'}
data-test-subj={'show-citations'}
>
<EuiSwitch
label={i18n.SHOW_CITATIONS}
checked={contentReferencesVisible}
onChange={onChangeContentReferencesVisible}
compressed
/>
</EuiContextMenuItem>
</EuiToolTip>
)}
<EuiHorizontalRule margin="none" />
<EuiContextMenuItem
Expand Down Expand Up @@ -242,6 +342,8 @@ export const SettingsContextMenu: React.FC<Params> = React.memo(
contentReferencesEnabled,
euiTheme.size.m,
euiTheme.size.xs,
selectedConversationHasCitations,
selectedConversationHasAnonymizedValues,
]
);

Expand Down
Loading