Cleanup SendMode

This commit is contained in:
Enrico Ros
2023-05-18 19:00:19 -07:00
parent 306a4aa2b2
commit ba2f4115ce
8 changed files with 76 additions and 71 deletions
+6 -8
View File
@@ -17,7 +17,6 @@ import { conversationToMarkdown } from '~/common/util/conversationToMarkdown';
import { createDMessage, DMessage, restoreConversationFromJson, useChatStore } from '~/common/state/store-chats';
import { extractCommands } from '~/common/util/extractCommands';
import { useApplicationBarStore } from '~/common/layouts/appbar/store-applicationbar';
import { useComposerStore } from '~/common/state/store-composer';
import { useSettingsStore } from '~/common/state/store-settings';
import { ActionItems } from './components/appbar/ActionItems';
@@ -34,6 +33,8 @@ import { runReActUpdatingState } from './editors/react-tangent';
const SPECIAL_ID_ALL_CHATS = 'all-chats';
export type SendModeId = 'immediate' | 'react';
export function Chat() {
@@ -48,9 +49,6 @@ export function Chat() {
// external state
const theme = useTheme();
const { sendModeId } = useComposerStore(state => ({
sendModeId: state.sendModeId,
}), shallow);
const { activeConversationId, isConversationEmpty, conversationsCount, importConversation, deleteAllConversations, setMessages, systemPurposeId, setAutoTitle } = useChatStore(state => {
const conversation = state.conversations.find(conversation => conversation.id === state.activeConversationId);
return {
@@ -66,7 +64,7 @@ export function Chat() {
}, shallow);
const handleExecuteConversation = async (conversationId: string, history: DMessage[]) => {
const handleExecuteConversation = async (sendModeId: SendModeId, conversationId: string, history: DMessage[]) => {
const { chatLLMId } = useModelsStore.getState();
if (!conversationId || !chatLLMId) return;
@@ -110,10 +108,10 @@ export function Chat() {
const _findConversation = (conversationId: string) =>
conversationId ? useChatStore.getState().conversations.find(c => c.id === conversationId) ?? null : null;
const handleSendUserMessage = async (conversationId: string, userText: string) => {
const handleSendUserMessage = async (sendModeId: SendModeId, conversationId: string, userText: string) => {
const conversation = _findConversation(conversationId);
if (conversation)
return await handleExecuteConversation(conversationId, [...conversation.messages, createDMessage('user', userText)]);
return await handleExecuteConversation(sendModeId, conversationId, [...conversation.messages, createDMessage('user', userText)]);
};
const handleImagineFromText = async (conversationId: string, messageText: string) => {
@@ -121,7 +119,7 @@ export function Chat() {
if (conversation) {
const prompt = await imaginePromptFromText(messageText);
if (prompt)
return await handleExecuteConversation(conversationId, [...conversation.messages, createDMessage('user', `${CmdRunProdia[0]} ${prompt}`)]);
return await handleExecuteConversation('immediate', conversationId, [...conversation.messages, createDMessage('user', `${CmdRunProdia[0]} ${prompt}`)]);
}
};
+11 -4
View File
@@ -11,13 +11,20 @@ import { useSettingsStore } from '~/common/state/store-settings';
import { ChatMessage } from './message/ChatMessage';
import { ChatMessageSelectable, MessagesSelectionHeader } from './message/ChatMessageSelectable';
import { PurposeSelector } from './PurposeSelector';
import { PurposeSelector } from './purpose-selector/PurposeSelector';
import { SendModeId } from '../Chat';
/**
* A list of ChatMessages
*/
export function ChatMessageList(props: { conversationId: string | null, isMessageSelectionMode: boolean, setIsMessageSelectionMode: (isMessageSelectionMode: boolean) => void, onExecuteConversation: (conversationId: string, history: DMessage[]) => void, onImagineFromText: (conversationId: string, userText: string) => void, sx?: SxProps }) {
export function ChatMessageList(props: {
conversationId: string | null,
isMessageSelectionMode: boolean, setIsMessageSelectionMode: (isMessageSelectionMode: boolean) => void,
onExecuteConversation: (sendModeId: SendModeId, conversationId: string, history: DMessage[]) => void,
onImagineFromText: (conversationId: string, userText: string) => void,
sx?: SxProps
}) {
// state
const [selectedMessages, setSelectedMessages] = React.useState<Set<string>>(new Set());
@@ -44,11 +51,11 @@ export function ChatMessageList(props: { conversationId: string | null, isMessag
const handleRestartFromMessage = (messageId: string, offset: number) => {
const truncatedHistory = messages.slice(0, messages.findIndex(m => m.id === messageId) + offset + 1);
props.conversationId && props.onExecuteConversation(props.conversationId, truncatedHistory);
props.conversationId && props.onExecuteConversation('immediate', props.conversationId, truncatedHistory);
};
const handleRunExample = (text: string) =>
props.conversationId && props.onExecuteConversation(props.conversationId, [...messages, createDMessage('user', text)]);
props.conversationId && props.onExecuteConversation('immediate', props.conversationId, [...messages, createDMessage('user', text)]);
// hide system messages if the user chooses so
+8 -29
View File
@@ -1,7 +1,7 @@
import * as React from 'react';
import { shallow } from 'zustand/shallow';
import { Box, Button, Card, Grid, IconButton, ListDivider, ListItemDecorator, Menu, MenuItem, Radio, Stack, Textarea, Tooltip, Typography, useTheme } from '@mui/joy';
import { Box, Button, Card, Grid, IconButton, ListDivider, ListItemDecorator, Menu, MenuItem, Stack, Textarea, Tooltip, Typography, useTheme } from '@mui/joy';
import { ColorPaletteProp, SxProps, VariantProp } from '@mui/joy/styles/types';
import ClearIcon from '@mui/icons-material/Clear';
import ContentPasteGoIcon from '@mui/icons-material/ContentPasteGo';
@@ -20,19 +20,20 @@ import { ContentReducer } from '~/modules/aifn/summarize/ContentReducer';
import { useChatLLM } from '~/modules/llms/store-llms';
import { ConfirmationModal } from '~/common/components/ConfirmationModal';
import { SendModeId, SendModes } from '../../../../data';
import { countModelTokens } from '~/common/llm-util/token-counter';
import { extractFilePathsWithCommonRadix } from '~/common/util/dropTextUtils';
import { hideOnDesktop, hideOnMobile } from '~/common/theme';
import { htmlTableToMarkdown } from '~/common/util/htmlTableToMarkdown';
import { pdfToText } from '~/common/util/pdfToText';
import { useChatStore } from '~/common/state/store-chats';
import { useComposerStore } from '~/common/state/store-composer';
import { useSettingsStore } from '~/common/state/store-settings';
import { useSpeechRecognition } from '~/common/components/useSpeechRecognition';
import { SendModeId } from '../../Chat';
import { SendModeMenu } from './SendModeMenu';
import { TokenBadge } from './TokenBadge';
import { TokenProgressbar } from './TokenProgressbar';
import { useComposerStore } from './composer.store';
/// Text template helpers
@@ -97,29 +98,6 @@ const MicButton = (props: { variant: VariantProp, color: ColorPaletteProp, onCli
</Tooltip>;
const SendModeMenu = (props: { anchorEl: HTMLAnchorElement, sendMode: SendModeId, onSetSendMode: (sendMode: SendModeId) => void, onClose: () => void, }) =>
<Menu
variant='plain' color='neutral' size='md' placement='top-end' sx={{ minWidth: 320, overflow: 'auto' }}
open anchorEl={props.anchorEl} onClose={props.onClose}>
<MenuItem color='neutral' selected>Conversation Mode</MenuItem>
<ListDivider />
{Object.entries(SendModes).map(([key, data]) =>
<MenuItem key={'send-mode-' + key} onClick={() => props.onSetSendMode(key as SendModeId)}>
<Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 2 }}>
<Radio checked={key === props.sendMode} />
<Box>
<Typography>{data.label}</Typography>
<Typography level='body2'>{data.description}</Typography>
</Box>
</Box>
</MenuItem>)}
</Menu>;
const SentMessagesMenu = (props: {
anchorEl: HTMLAnchorElement, onClose: () => void,
messages: { date: number; text: string; count: number }[],
@@ -163,11 +141,12 @@ const SentMessagesMenu = (props: {
export function Composer(props: {
conversationId: string | null; messageId: string | null;
isDeveloperMode: boolean;
onSendMessage: (conversationId: string, text: string) => void;
onSendMessage: (sendModeId: SendModeId, conversationId: string, text: string) => void;
sx?: SxProps;
}) {
// state
const [composeText, setComposeText] = React.useState('');
const [sendModeId, setSendModeId] = React.useState<SendModeId>('immediate');
const [isDragging, setIsDragging] = React.useState(false);
const [reducerText, setReducerText] = React.useState('');
const [reducerTextTokens, setReducerTextTokens] = React.useState(0);
@@ -179,7 +158,7 @@ export function Composer(props: {
// external state
const theme = useTheme();
const enterToSend = useSettingsStore(state => state.enterToSend);
const { sendModeId, setSendModeId, sentMessages, appendSentMessage, clearSentMessages } = useComposerStore();
const { sentMessages, appendSentMessage, clearSentMessages } = useComposerStore();
const { assistantTyping, tokenCount: conversationTokenCount, stopTyping } = useChatStore(state => {
const conversation = state.conversations.find(conversation => conversation.id === props.conversationId);
return {
@@ -204,7 +183,7 @@ export function Composer(props: {
const text = (composeText || '').trim();
if (text.length && props.conversationId) {
setComposeText('');
props.onSendMessage(props.conversationId, text);
props.onSendMessage(sendModeId, props.conversationId, text);
appendSentMessage(text);
}
};
@@ -0,0 +1,47 @@
import * as React from 'react';
import { Box, ListDivider, Menu, MenuItem, Radio, Typography } from '@mui/joy';
import { SendModeId } from '../../Chat';
/// SendMode(s) definition
type SendModeData = {
label: string;
description: string | React.JSX.Element;
}
const SendModeItems: { [key in SendModeId]: SendModeData } = {
'immediate': {
label: 'Chat',
description: 'AI-powered direct responses',
},
'react': {
label: 'Reason+Act',
description: 'Answer your questions with ReAct and search',
},
};
export const SendModeMenu = (props: { anchorEl: HTMLAnchorElement, sendMode: SendModeId, onSetSendMode: (sendMode: SendModeId) => void, onClose: () => void, }) =>
<Menu
variant='plain' color='neutral' size='md' placement='top-end' sx={{ minWidth: 320, overflow: 'auto' }}
open anchorEl={props.anchorEl} onClose={props.onClose}>
<MenuItem color='neutral' selected>Conversation Mode</MenuItem>
<ListDivider />
{Object.entries(SendModeItems).map(([key, data]) =>
<MenuItem key={'send-mode-' + key} onClick={() => props.onSetSendMode(key as SendModeId)}>
<Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 2 }}>
<Radio checked={key === props.sendMode} />
<Box>
<Typography>{data.label}</Typography>
<Typography level='body2'>{data.description}</Typography>
</Box>
</Box>
</MenuItem>)}
</Menu>;
@@ -1,15 +1,11 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { defaultSendModeId, SendModeId } from '../../data';
/// Composer Store
interface ComposerStore {
sendModeId: SendModeId;
setSendModeId: (sendMode: SendModeId) => void;
sentMessages: {
date: number,
text: string,
@@ -23,9 +19,6 @@ interface ComposerStore {
export const useComposerStore = create<ComposerStore>()(
persist((set, get) => ({
sendModeId: defaultSendModeId,
setSendModeId: (sendMode: SendModeId) => set({ sendModeId: sendMode }),
sentMessages: [],
appendSentMessage: (text: string) => {
const date = Date.now();
@@ -61,4 +54,4 @@ export const useComposerStore = create<ComposerStore>()(
return state as ComposerStore;
},
}),
);
);
@@ -5,11 +5,12 @@ import { Box, Button, Checkbox, Grid, IconButton, Input, Stack, Textarea, Typogr
import ClearIcon from '@mui/icons-material/Clear';
import SearchIcon from '@mui/icons-material/Search';
import { SystemPurposeId, SystemPurposes } from '../../../data';
import { useChatStore } from '~/common/state/store-chats';
import { usePurposeStore } from '~/common/state/store-purposes';
import { useSettingsStore } from '~/common/state/store-settings';
import { SystemPurposeId, SystemPurposes } from '../../../../data';
import { usePurposeStore } from './purposes.store';
// Constants for tile sizes / grid width - breakpoints need to be computed here to work around
// the "flex box cannot shrink over wrapped content" issue
-20
View File
@@ -63,23 +63,3 @@ export const SystemPurposes: { [key in SystemPurposeId]: SystemPurposeData } = {
symbol: '✨',
},
};
export type SendModeId = 'immediate' | 'react';
export const defaultSendModeId: SendModeId = 'immediate';
type SendModeData = {
label: string;
description: string | JSX.Element;
}
export const SendModes: { [key in SendModeId]: SendModeData } = {
'immediate': {
label: 'Chat',
description: 'AI-powered direct responses',
},
'react': {
label: 'Reason+Act',
description: 'Answer your questions with ReAct and search',
},
};