Skip to content

Commit

Permalink
Support creating alert in the chat window
Browse files Browse the repository at this point in the history
Signed-off-by: Heng Qian <[email protected]>
  • Loading branch information
qianheng-aws committed Jul 16, 2024
1 parent deadef0 commit 8b29989
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 42 deletions.
15 changes: 12 additions & 3 deletions common/types/chat_saved_object_attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,22 @@ export interface IOutput {
toolsUsed?: string[];
contentType: 'error' | 'markdown' | 'visualization' | string;
content: string;
additionalActions?: IAdditionalAction[];
suggestedActions?: ISuggestedAction[];
messageId?: string;
fullWidth?: boolean;
}
export type IMessage = IInput | IOutput;

interface ISuggestedActionBase {
interface IActionBase {
actionType: string;
message: string;
}
export type ISuggestedAction = ISuggestedActionBase &
export type ISuggestedAction = IActionBase &
(
| { actionType: 'send_as_input' | 'copy' | 'view_in_dashboards' }
| {
actionType: 'send_as_input' | 'copy' | 'view_in_dashboards' | 'create_monitor_in_dashboard';
}
| {
actionType: 'view_ppl_visualization';
metadata: { query: string; question: string };
Expand All @@ -74,6 +77,12 @@ export type ISuggestedAction = ISuggestedActionBase &
metadata: { interactionId: string };
}
);

export type IAdditionalAction = IActionBase & {
actionType: 'create_monitor_grid';
content: string;
};

export interface SendFeedbackBody {
satisfaction: boolean;
}
Expand Down
74 changes: 39 additions & 35 deletions public/chat_flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ChatWindowHeader } from './tabs/chat_window_header';
import { ChatHistoryPage } from './tabs/history/chat_history_page';
import { AgentFrameworkTracesFlyoutBody } from './components/agent_framework_traces_flyout_body';
import { TAB_ID } from './utils/constants';
import { ChatOverrideHeader } from './tabs/chat_override_header';

interface ChatFlyoutProps {
flyoutVisible: boolean;
Expand Down Expand Up @@ -86,52 +87,55 @@ export const ChatFlyout = (props: ChatFlyoutProps) => {
>
<>
<div className={cs('llm-chat-flyout-header')}>
<ChatWindowHeader />
{props.overrideComponent ? <ChatOverrideHeader /> : <ChatWindowHeader />}
</div>

{props.overrideComponent}
<EuiResizableContainer style={{ height: '100%', overflow: 'hidden' }}>
{(Panel, Resizer) => (
<>
<Panel
aria-label="chat panel"
className={cs('llm-chat-horizontal-resize-panel', {
'llm-chat-hidden': leftPanelSize === 0,
})}
scrollable={false}
size={leftPanelSize}
initialSize={resizable ? 70 : undefined}
paddingSize="none"
>
<ChatPage />
</Panel>
{props.overrideComponent ? (
props.overrideComponent
) : (
<EuiResizableContainer style={{ height: '100%', overflow: 'hidden' }}>
{(Panel, Resizer) => (
<>
{resizable && <Resizer />}
<Panel
aria-label="history panel"
aria-label="chat panel"
className={cs('llm-chat-horizontal-resize-panel', {
'llm-chat-hidden': leftPanelSize === 100,
'llm-chat-hidden': leftPanelSize === 0,
})}
scrollable={false}
size={rightPanelSize}
initialSize={resizable ? 30 : undefined}
size={leftPanelSize}
initialSize={resizable ? 70 : undefined}
paddingSize="none"
>
{chatHistoryPageLoadedRef.current && (
<ChatHistoryPage
// refresh data when user switched to table from another tab
shouldRefresh={chatHistoryPageVisible}
className={cs({ 'llm-chat-hidden': !chatHistoryPageVisible })}
/>
)}
{chatTraceVisible && chatContext.interactionId && (
<AgentFrameworkTracesFlyoutBody />
)}
{<ChatPage />}
</Panel>
<>
{resizable && <Resizer />}
<Panel
aria-label="history panel"
className={cs('llm-chat-horizontal-resize-panel', {
'llm-chat-hidden': leftPanelSize === 100,
})}
scrollable={false}
size={rightPanelSize}
initialSize={resizable ? 30 : undefined}
paddingSize="none"
>
{chatHistoryPageLoadedRef.current && (
<ChatHistoryPage
// refresh data when user switched to table from another tab
shouldRefresh={chatHistoryPageVisible}
className={cs({ 'llm-chat-hidden': !chatHistoryPageVisible })}
/>
)}
{chatTraceVisible && chatContext.interactionId && (
<AgentFrameworkTracesFlyoutBody />
)}
</Panel>
</>
</>
</>
)}
</EuiResizableContainer>
)}
</EuiResizableContainer>
)}
</>
</div>
);
Expand Down
24 changes: 23 additions & 1 deletion public/chat_header_button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,20 @@ import { ChatStateProvider } from './hooks';
import './index.scss';
import { ActionExecutor, AssistantActions, MessageRenderer, TabId, UserAccount } from './types';
import {
TAB_ID,
DEFAULT_SIDECAR_DOCKED_MODE,
DEFAULT_SIDECAR_LEFT_OR_RIGHT_SIZE,
OVERRIDE_SIDECAR_LEFT_OR_RIGHT_SIZE,
TAB_ID,
} from './utils/constants';
import { useCore } from './contexts/core_context';
import { MountPointPortal } from '../../../src/plugins/opensearch_dashboards_react/public';
import { getStateFromOsdUrl } from '../../../src/plugins/opensearch_dashboards_utils/public';
import {
DiscoverRootState,
DiscoverState,
} from '../../../src/plugins/discover/public/application/utils/state_management';
import { IndexPatternAttributes } from '../../../src/plugins/data/common';
import { SavedSearch } from '../../../src/plugins/discover/public';

interface HeaderChatButtonProps {
application: ApplicationStart;
Expand All @@ -41,6 +49,7 @@ export const HeaderChatButton = (props: HeaderChatButtonProps) => {
const [conversationId, setConversationId] = useState<string>();
const [title, setTitle] = useState<string>();
const [flyoutVisible, setFlyoutVisible] = useState(false);
const [overrideName, setOverrideName] = useState<string>();
const [flyoutComponent, setFlyoutComponent] = useState<React.ReactNode | null>(null);
const [selectedTabId, setSelectedTabId] = useState<TabId>(TAB_ID.CHAT);
const [preSelectedTabId, setPreSelectedTabId] = useState<TabId | undefined>(undefined);
Expand Down Expand Up @@ -74,6 +83,8 @@ export const HeaderChatButton = (props: HeaderChatButtonProps) => {
flyoutFullScreen,
setFlyoutVisible,
setFlyoutComponent,
overrideName,
setOverrideName,
userHasAccess: props.userHasAccess,
messageRenderers: props.messageRenderers,
actionExecutors: props.actionExecutors,
Expand Down Expand Up @@ -156,6 +167,17 @@ export const HeaderChatButton = (props: HeaderChatButtonProps) => {
flyoutMountPoint.current = mountPoint;
}, []);

useEffect(() => {
if (flyoutLoaded && flyoutVisible) {
core.overlays.sidecar().setSidecarConfig({
paddingSize:
selectedTabId === TAB_ID.OVERRIDE
? OVERRIDE_SIDECAR_LEFT_OR_RIGHT_SIZE
: DEFAULT_SIDECAR_LEFT_OR_RIGHT_SIZE,
});
}
}, [selectedTabId === TAB_ID.OVERRIDE]);

useEffect(() => {
if (!props.userHasAccess) {
return;
Expand Down
4 changes: 4 additions & 0 deletions public/contexts/chat_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface IChatContext {
flyoutFullScreen: boolean;
setFlyoutVisible: React.Dispatch<React.SetStateAction<boolean>>;
setFlyoutComponent: React.Dispatch<React.SetStateAction<React.ReactNode | null>>;
overrideName?: string;
setOverrideName: React.Dispatch<React.SetStateAction<string | undefined>>;
userHasAccess: boolean;
messageRenderers: Record<string, MessageRenderer>;
actionExecutors: Record<string, ActionExecutor>;
Expand All @@ -28,6 +30,8 @@ export interface IChatContext {
setInteractionId: React.Dispatch<React.SetStateAction<string | undefined>>;
sidecarDockedMode: ISidecarConfig['dockedMode'];
setSidecarDockedMode: React.Dispatch<React.SetStateAction<ISidecarConfig['dockedMode']>>;
tabRenderer?: React.ReactNode;
setTabRenderer?: React.Dispatch<React.SetStateAction<React.ReactElement>>;
}
export const ChatContext = React.createContext<IChatContext | null>(null);

Expand Down
2 changes: 2 additions & 0 deletions public/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@

.llm-chat-flyout {
height: 100%;
display: flex;
flex-direction: column;
.euiFlyoutFooter {
background: transparent;
}
Expand Down
40 changes: 38 additions & 2 deletions public/tabs/chat/messages/message_content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiMarkdownFormat, EuiText } from '@elastic/eui';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiMarkdownFormat, EuiText } from '@elastic/eui';
import React from 'react';
import { IMessage } from '../../../../common/types/chat_saved_object_attributes';
import { CoreVisualization } from '../../../components/core_visualization';
import { useChatContext } from '../../../contexts/chat_context';
import { TAB_ID } from '../../../utils/constants';

export interface MessageContentProps {
message: IMessage;
Expand All @@ -28,7 +29,42 @@ export const MessageContent: React.FC<MessageContentProps> = React.memo((props)
);

case 'markdown':
return <EuiMarkdownFormat>{props.message.content}</EuiMarkdownFormat>;
return (
<>
<EuiMarkdownFormat>{props.message.content}</EuiMarkdownFormat>
{props.message.additionalActions &&
props.message.additionalActions.map((action, index) => (
<EuiFlexGroup key={'action' + index} justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiButton
onClick={() => {
if (chatContext) {
if (chatContext.selectedTabId !== TAB_ID.OVERRIDE) {
chatContext.setSelectedTabId(TAB_ID.OVERRIDE);
}
const actionMessage: IMessage = {
type: 'output',
contentType: action.actionType,
content: action.content,
};
const component = chatContext.messageRenderers[
action.actionType
]?.(actionMessage, { props: { message: actionMessage }, chatContext });
chatContext.setFlyoutComponent(component);
chatContext.setOverrideName('Create Alert');
}
}}
fill
isLoading={false}
disabled={false}
>
Create monitor
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
))}
</>
);

case 'visualization':
return (
Expand Down
53 changes: 53 additions & 0 deletions public/tabs/chat_override_header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiButtonEmpty, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
import React, { useCallback } from 'react';
import { IChatContext, useChatContext } from '../contexts/chat_context';
import { TAB_ID } from '../utils/constants';
import { SidecarIconMenu } from '../components/sidecar_icon_menu';

export const ChatOverrideHeader = React.memo(() => {
const chatContext = useChatContext() as IChatContext;
const { setSelectedTabId, setFlyoutComponent, setOverrideName } = chatContext;

const handleBack = useCallback(() => {
setSelectedTabId(TAB_ID.CHAT);
setFlyoutComponent(null);
setOverrideName(undefined);
}, [setSelectedTabId]);

return (
<>
<EuiFlexGroup
gutterSize="s"
justifyContent="spaceAround"
alignItems="center"
responsive={false}
>
<EuiFlexItem>
<EuiFlexGroup gutterSize="none" alignItems="center" responsive={false}>
<EuiButtonEmpty flush="left" size="xs" onClick={handleBack} iconType="arrowLeft">
{chatContext?.overrideName || 'Back'}
</EuiButtonEmpty>
</EuiFlexGroup>
</EuiFlexItem>
<SidecarIconMenu />
<EuiFlexItem grow={false}>
<EuiButtonIcon
aria-label="close"
size="xs"
color="text"
iconType="cross"
onClick={() => {
chatContext.setFlyoutVisible(false);
}}
/>
</EuiFlexItem>
<EuiFlexItem grow={false} />
</EuiFlexGroup>
</>
);
});
3 changes: 2 additions & 1 deletion public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { IMessage, ISuggestedAction } from '../common/types/chat_saved_object_at
import { IChatContext } from './contexts/chat_context';
import { MessageContentProps } from './tabs/chat/messages/message_content';
import { IncontextInsightRegistry } from './services';
import { TAB_ID } from './utils/constants';

export interface RenderProps {
props: MessageContentProps;
Expand Down Expand Up @@ -83,4 +84,4 @@ export type IncontextInsightType =
| 'chatWithSuggestions'
| 'error';

export type TabId = 'chat' | 'compose' | 'insights' | 'history' | 'trace';
export type TabId = TAB_ID;
2 changes: 2 additions & 0 deletions public/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ export enum TAB_ID {
INSIGHTS = 'insights',
HISTORY = 'history',
TRACE = 'trace',
OVERRIDE = 'override',
}

export const DEFAULT_SIDECAR_DOCKED_MODE = SIDECAR_DOCKED_MODE.RIGHT;
export const DEFAULT_SIDECAR_LEFT_OR_RIGHT_SIZE = 460;
export const OVERRIDE_SIDECAR_LEFT_OR_RIGHT_SIZE = 570;
// this is a default padding top size for sidecar when switching to takeover
export const DEFAULT_SIDECAR_TAKEOVER_PADDING_TOP_SIZE = 136;
Loading

0 comments on commit 8b29989

Please sign in to comment.