Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coral-web: update the starter card options #73

Merged
merged 12 commits into from
May 1, 2024
4 changes: 1 addition & 3 deletions src/interfaces/coral_web/src/components/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ type Props = {

export const Avatar: React.FC<Props> = ({ message }) => {
const isUser = message.type === MessageType.USER;
const isBot = message.type === MessageType.BOT || message.type === MessageType.WELCOME;
const isWelcome = message.type === MessageType.WELCOME;
const isBot = message.type === MessageType.BOT;
const isLoading = isBot && message.state === BotState.LOADING;
const isTyping = isBot && message.state === BotState.TYPING;
const isErrored = isBot && message.state === BotState.ERROR;
Expand All @@ -37,7 +36,6 @@ export const Avatar: React.FC<Props> = ({ message }) => {
'h-7 w-7 md:h-9 md:w-9',
{
'bg-volcanic-500': isErroredOrAborted,
'bg-primary-900': isWelcome,
'bg-quartz-700': isUser,
},
isGroundingOn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ const ToolSection = () => {
})}
disabled={disabled}
/>
{(description || error_message) && <Tooltip label={description ?? error_message} />}
{(description || error_message) && (
<Tooltip label={description ?? error_message} />
)}
</div>
);
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,25 @@ import ScrollToBottom, { useScrollToBottom, useSticky } from 'react-scroll-to-bo

import { CitationPanel } from '@/components/Citations/CitationPanel';
import MessageRow from '@/components/MessageRow';
import Notification from '@/components/Messages/Notification';
import WelcomeMessage from '@/components/Messages/Welcome';
import { StartOptionKey } from '@/components/Messages/Welcome/StartOptions';
import { Button } from '@/components/Shared';
import { PromptOption, StartModes } from '@/components/StartModes';
import { ReservedClasses } from '@/constants';
import { MESSAGE_LIST_CONTAINER_ID, useCalculateCitationStyles } from '@/hooks/citations';
import { useFixCopyBug } from '@/hooks/fixCopyBug';
import { useCitationsStore } from '@/stores';
import {
ChatMessage,
MessageType,
StreamingMessage,
isFulfilledMessage,
isNotificationMessage,
} from '@/types/message';
import { ChatMessage, MessageType, StreamingMessage, isFulfilledMessage } from '@/types/message';
import { cn } from '@/utils';

type Props = {
isStreaming: boolean;
welcomeMessageEnabled: boolean;
startOptionsEnabled: boolean;
messages: ChatMessage[];
streamingMessage: StreamingMessage | null;
startOption: StartOptionKey;
onStartOptionChange: (option: StartOptionKey) => void;
onRetry: VoidFunction;
composer: ReactNode;
conversationId?: string;
scrollViewClassName?: string;
onPromptSelected?: (option: PromptOption) => void;
};

/**
Expand Down Expand Up @@ -64,8 +55,7 @@ export default memo(MessagingContainer);
* In order to access the state hooks for the scroll to bottom component, we need to wrap the content in a component.
*/
const Content: React.FC<Props> = (props) => {
const { isStreaming, messages, composer, streamingMessage, startOption, onStartOptionChange } =
props;
const { isStreaming, messages, composer, streamingMessage, onPromptSelected } = props;
const scrollToBottom = useScrollToBottom();
const {
citations: { hasCitations },
Expand Down Expand Up @@ -114,12 +104,7 @@ const Content: React.FC<Props> = (props) => {
return (
<div className="flex h-max min-h-full w-full">
<div id={MESSAGE_LIST_CONTAINER_ID} className={cn('flex h-auto min-w-0 flex-1 flex-col')}>
<Messages
{...props}
ref={messageContainerDivRef}
startOption={startOption}
onStartOptionChange={onStartOptionChange}
/>
<Messages {...props} ref={messageContainerDivRef} onPromptSelected={onPromptSelected} />
{/* Composer container */}
<div
className={cn('sticky bottom-0 px-4 pb-4', 'bg-marble-100')}
Expand Down Expand Up @@ -166,36 +151,26 @@ const Content: React.FC<Props> = (props) => {
);
};

type MessagesProps = Props & { welcomeMessageEnabled: boolean };
type MessagesProps = Props & { startOptionsEnabled: boolean };
/**
* This component is in charge of rendering the messages.
*/
const Messages = forwardRef<HTMLDivElement, MessagesProps>(function MessagesInternal(
{ welcomeMessageEnabled, onRetry, messages, streamingMessage, startOption, onStartOptionChange },
{ startOptionsEnabled, onRetry, messages, streamingMessage, onPromptSelected },
ref
) {
const lastMessage = messages[messages.length - 1];

const isConversationEmpty = messages.length === 0;
return (
<div className="mt-auto flex flex-col gap-y-4 px-4 py-6 md:gap-y-6" ref={ref}>
<WelcomeMessage
show={
welcomeMessageEnabled && messages.filter((m) => !isNotificationMessage(m)).length === 0
}
startOption={startOption}
onStartOptionChange={onStartOptionChange}
/>

{messages.map((m, i) => {
const isLastInList = i === messages.length - 1;
<div className="flex h-full flex-col gap-y-4 px-4 py-6 md:gap-y-6" ref={ref}>
{startOptionsEnabled && (
misspia-cohere marked this conversation as resolved.
Show resolved Hide resolved
<div className="flex h-full w-full flex-col justify-center p-4">
<StartModes show={isConversationEmpty} onPromptSelected={onPromptSelected} />
</div>
)}

if (isNotificationMessage(m) && isLastInList) {
// If the last message is a notification, render it after the streaming message if it exists.
// The latest status is always shown at the bottom of the chat.
return null;
} else if (isNotificationMessage(m) && !isLastInList) {
return <Notification key={i} message={m.text} show={m.show} />;
} else {
<div className="mt-auto flex flex-col gap-y-4 md:gap-y-6">
{messages.map((m, i) => {
const isLastInList = i === messages.length - 1;
return (
<MessageRow
key={i}
Expand All @@ -214,16 +189,12 @@ const Messages = forwardRef<HTMLDivElement, MessagesProps>(function MessagesInte
onRetry={onRetry}
/>
);
}
})}
})}
</div>

{streamingMessage && (
<MessageRow message={streamingMessage} isLast={true} onRetry={onRetry} />
)}

{lastMessage && isNotificationMessage(lastMessage) && messages.length > 1 && (
<Notification message={lastMessage.text} show={lastMessage.show} shouldAnimate />
)}
</div>
);
});
34 changes: 12 additions & 22 deletions src/interfaces/coral_web/src/components/Conversation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import { FILE_TOOL_CATEGORY, Tool } from '@/cohere-client';
import Composer from '@/components/Conversation/Composer';
import { Header } from '@/components/Conversation/Header';
import MessagingContainer from '@/components/Conversation/MessagingContainer';
import { StartOptionKey } from '@/components/Messages/Welcome/StartOptions';
import { DragDropFileInput, Spinner } from '@/components/Shared';
import { HotKeysProvider } from '@/components/Shared/HotKeys';
import { PromptOption } from '@/components/StartModes';
import { WelcomeGuideTooltip } from '@/components/WelcomeGuideTooltip';
import { ACCEPTED_FILE_TYPES, ReservedClasses } from '@/constants';
import { useChatHotKeys } from '@/hooks/actions';
import { useFocusComposer } from '@/hooks/actions';
import { useChat } from '@/hooks/chat';
import { useFileActions, useFilesInConversation } from '@/hooks/files';
import { WelcomeGuideStep, useWelcomeGuideState } from '@/hooks/ftux';
Expand All @@ -27,7 +28,7 @@ import { ChatMessage } from '@/types/message';
import { cn } from '@/utils';

type Props = {
welcomeMessageEnabled?: boolean;
startOptionsEnabled?: boolean;
conversationId?: string;
history?: ChatMessage[];
};
Expand All @@ -36,7 +37,7 @@ type Props = {
* @description Renders the entire conversation pane, which includes the header, messages,
* composer, and the citation panel.
*/
const Conversation: React.FC<Props> = ({ conversationId, welcomeMessageEnabled = false }) => {
const Conversation: React.FC<Props> = ({ conversationId, startOptionsEnabled = false }) => {
const [isDragDropInputActive, setIsDragDropInputActive] = useState(false);
const chatHotKeys = useChatHotKeys();

Expand Down Expand Up @@ -76,16 +77,7 @@ const Conversation: React.FC<Props> = ({ conversationId, welcomeMessageEnabled =
}
},
});
const getSelectedOption = (): StartOptionKey => {
if (tools && tools.length > 0) {
return StartOptionKey.WEB_SEARCH;
} else if (params.fileIds && params.fileIds.length > 0) {
return StartOptionKey.DOCUMENTS;
} else {
return StartOptionKey.UNGROUNDED;
}
};
const [startOption, setStartOption] = useState<StartOptionKey>(() => getSelectedOption());
const { focusComposer } = useFocusComposer();

// Returns the first visible file loader tool from tools list
const defaultFileLoaderTool = useMemo(
Expand Down Expand Up @@ -153,9 +145,6 @@ const Conversation: React.FC<Props> = ({ conversationId, welcomeMessageEnabled =
const handleUploadFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
const newFileIds = await uploadFile(e.target.files?.[0]);
if (!newFileIds) return;
if (startOption !== StartOptionKey.DOCUMENTS) {
setStartOption(StartOptionKey.DOCUMENTS);
}
enableDefaultFileLoaderTool();
};

Expand All @@ -167,15 +156,17 @@ const Conversation: React.FC<Props> = ({ conversationId, welcomeMessageEnabled =
...(enableFileLoaderTool ? [{ name: defaultFileLoaderTool.name }] : []),
];

if (startOption !== StartOptionKey.DOCUMENTS) {
setStartOption(StartOptionKey.DOCUMENTS);
}
if (filesExist) {
enableDefaultFileLoaderTool();
}
send({ suggestedMessage: msg }, { tools: chatOverrideTools });
};

const handlePromptSelected = (option: PromptOption) => {
focusComposer();
setUserMessage(option.prompt);
};

return (
<div className="flex h-full w-full flex-col">
<HotKeysProvider customHotKeys={chatHotKeys} />
Expand Down Expand Up @@ -208,13 +199,12 @@ const Conversation: React.FC<Props> = ({ conversationId, welcomeMessageEnabled =
/>
<MessagingContainer
conversationId={conversationId}
welcomeMessageEnabled={welcomeMessageEnabled}
startOptionsEnabled={startOptionsEnabled}
isStreaming={isStreaming}
onRetry={handleRetry}
messages={messages}
streamingMessage={streamingMessage}
startOption={startOption}
onStartOptionChange={setStartOption}
onPromptSelected={handlePromptSelected}
composer={
<>
<WelcomeGuideTooltip step={3} className="absolute bottom-full mb-4" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const BOT_ERROR_MESSAGE = 'Unable to generate a response since an error was enco

export const MessageContent: React.FC<Props> = ({ isLast, message, onRetry }) => {
const isUser = message.type === MessageType.USER;
const isWelcome = message.type === MessageType.WELCOME;
const isLoading = isLoadingMessage(message);
const isBotError = isErroredMessage(message);
const isUserError = isUser && message.error;
Expand Down Expand Up @@ -105,7 +104,7 @@ export const MessageContent: React.FC<Props> = ({ isLast, message, onRetry }) =>
<>
<Markdown
className={cn({
'text-volcanic-700': isWelcome || isAborted,
'text-volcanic-700': isAborted,
})}
text={message.text}
customComponents={{
Expand Down

This file was deleted.

This file was deleted.

Loading
Loading