change how mode is passed through

This commit is contained in:
Nate Kelley 2025-10-01 10:03:41 -06:00
parent 9e793787ef
commit afe0c68e84
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
11 changed files with 46 additions and 46 deletions

View File

@ -1,4 +1,3 @@
import type { ChatCreateRequest } from '@buster/server-shared/chats';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import type { BusterChatMessage } from '@/api/asset_interfaces/chat';
import { chatQueryKeys } from '@/api/query_keys/chat';
@ -19,11 +18,7 @@ export const useStartNewChat = () => {
};
return useMutation({
mutationFn: async (props: ChatCreateRequest) => {
// I opted to not use honoInstance to take better advantage of turbo caching
// const res = await honoInstance.api.v2.chats.$post({ json: props });
return await createNewChat(props);
},
mutationFn: createNewChat,
onSuccess: (data) => {
const { iChat, iChatMessages } = updateChatToIChat(data);
saveAllChatMessages(iChatMessages);

View File

@ -4,7 +4,7 @@ import type {
GetChatsListResponseV2,
GetChatsRequestV2,
} from '@buster/server-shared/chats';
import mainApi, { mainApiV2 } from '../instances';
import { mainApiV2 } from '../instances';
export const getListChats = async (
params?: GetChatsRequestV2

View File

@ -1,3 +1,4 @@
import type { MessageAnalysisMode } from '@buster/server-shared/chats';
import type { ListShortcutsResponse } from '@buster/server-shared/shortcuts';
import type { GetSuggestedPromptsResponse } from '@buster/server-shared/user';
import React, { useMemo, useRef, useState } from 'react';
@ -17,7 +18,7 @@ import { MentionInputSuggestions } from '@/components/ui/inputs/MentionInputSugg
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
import { useMount } from '@/hooks/useMount';
import { NewShortcutModal } from '../../modals/NewShortcutModal';
import { BusterChatInputButtons, type BusterChatInputMode } from './BusterChatInputButtons';
import { BusterChatInputButtons } from './BusterChatInputButtons';
import { useUniqueSuggestions } from './useUniqueSuggestions';
export type BusterChatInputProps = {
@ -26,7 +27,7 @@ export type BusterChatInputProps = {
transformedValue: string;
arrayValue: MentionArrayItem[];
editorText: string;
mode: BusterChatInputMode;
mode: MessageAnalysisMode;
}) => void;
onStop: () => void;
submitting: boolean;
@ -50,7 +51,7 @@ export const BusterChatInputBase: React.FC<BusterChatInputProps> = React.memo(
const mentionInputSuggestionsRef = useRef<MentionInputSuggestionsRef>(null);
const uniqueSuggestions = useUniqueSuggestions(suggestedPrompts);
const [openCreateShortcutModal, setOpenCreateShortcutModal] = useState(false);
const [mode, setMode] = useState<BusterChatInputMode>('auto');
const [mode, setMode] = useState<MessageAnalysisMode>('auto');
const shortcutsSuggestions = useShortcutsSuggestions(
shortcuts,

View File

@ -1,3 +1,4 @@
import type { MessageAnalysisMode } from '@buster/server-shared/chats';
import React, { useEffect } from 'react';
import { Button } from '@/components/ui/buttons';
import { ArrowUp, Magnifier, Sparkle2 } from '@/components/ui/icons';
@ -16,15 +17,13 @@ import { Text } from '@/components/ui/typography';
import { useSpeechRecognition } from '@/hooks/useSpeechRecognition';
import { cn } from '@/lib/utils';
export type BusterChatInputMode = 'auto' | 'research' | 'deep-research';
type BusterChatInputButtons = {
onSubmit: MentionOnChangeFn;
onStop: () => void;
submitting: boolean;
disabled: boolean;
mode: BusterChatInputMode;
onModeChange: (mode: BusterChatInputMode) => void;
mode: MessageAnalysisMode;
onModeChange: (mode: MessageAnalysisMode) => void;
onDictate?: (transcript: string) => void;
onDictateListeningChange?: (listening: boolean) => void;
};
@ -191,7 +190,7 @@ const ModePopoverContent = ({
);
};
const modesOptions: AppSegmentedProps<BusterChatInputMode>['options'] = [
const modesOptions: AppSegmentedProps<MessageAnalysisMode>['options'] = [
{
icon: (
<ModePopoverContent
@ -218,7 +217,7 @@ const modesOptions: AppSegmentedProps<BusterChatInputMode>['options'] = [
<Magnifier />
</ModePopoverContent>
),
value: 'research' as const,
value: 'standard' as const,
},
{
icon: (
@ -232,6 +231,6 @@ const modesOptions: AppSegmentedProps<BusterChatInputMode>['options'] = [
<Atom />
</ModePopoverContent>
),
value: 'deep-research' as const,
value: 'investigation' as const,
},
];

View File

@ -1,4 +1,4 @@
import type { ChatCreateRequest } from '@buster/server-shared/chats';
import type { ChatCreateRequest, MessageAnalysisMode } from '@buster/server-shared/chats';
import { useNavigate } from '@tanstack/react-router';
import { create } from 'mutative';
import type { FileType } from '@/api/asset_interfaces/chat';
@ -14,16 +14,7 @@ type StartChatParams = {
dashboardId?: string; //this is to start a NEW chat from a dashboard
messageId?: string; //this is used to replace a message in the chat
chatId?: string; //this is used to follow up a chat
mode?: 'auto' | 'research' | 'deep-research'; //ui modes
};
const chatModeToServerRecord: Record<
NonNullable<StartChatParams['mode']>,
NonNullable<ChatCreateRequest['message_analysis_mode']>
> = {
auto: 'auto',
research: 'standard',
'deep-research': 'investigation',
mode: MessageAnalysisMode; //ui modes
};
export const useChat = () => {
@ -40,7 +31,7 @@ export const useChat = () => {
metricId,
dashboardId,
messageId,
mode = 'auto',
mode,
}: StartChatParams) => {
const res = await startNewChat({
prompt,
@ -48,7 +39,7 @@ export const useChat = () => {
metric_id: metricId,
dashboard_id: dashboardId,
message_id: messageId,
message_analysis_mode: chatModeToServerRecord[mode] || 'auto',
message_analysis_mode: mode,
});
const { message_ids, id } = res;
@ -63,11 +54,8 @@ export const useChat = () => {
};
const onStartNewChat = useMemoizedFn(
async ({ prompt, mode }: { prompt: string; mode: StartChatParams['mode'] }) => {
return startChat({
prompt,
mode,
});
async (d: { prompt: string; mode: StartChatParams['mode'] }) => {
return startChat(d);
}
);
@ -76,24 +64,32 @@ export const useChat = () => {
prompt,
fileId,
fileType,
mode = 'auto',
}: {
prompt: string;
fileId: string;
fileType: FileType;
mode?: StartChatParams['mode'];
}) => {
return startChat({
prompt,
metricId: fileType === 'metric_file' ? fileId : undefined,
dashboardId: fileType === 'dashboard_file' ? fileId : undefined,
mode,
});
}
);
const onFollowUpChat = useMemoizedFn(
async ({ prompt, chatId }: Pick<NonNullable<StartChatParams>, 'prompt' | 'chatId'>) => {
async ({
prompt,
chatId,
mode = 'auto',
}: Pick<NonNullable<StartChatParams>, 'prompt' | 'chatId' | 'mode'>) => {
return startChat({
prompt,
chatId,
mode,
});
}
);
@ -107,10 +103,12 @@ export const useChat = () => {
prompt,
messageId,
chatId,
mode = 'auto',
}: {
prompt: string;
messageId: string;
chatId: string;
mode?: StartChatParams['mode'];
}) => {
const currentChat = getChatMemoized(chatId);
const currentMessage = getChatMessageMemoized(messageId);
@ -141,6 +139,7 @@ export const useChat = () => {
return startChat({
prompt,
messageId,
mode,
});
}
);

View File

@ -1,3 +1,4 @@
import type { MessageAnalysisMode } from '@buster/server-shared/chats';
import type React from 'react';
import { useMemo, useRef } from 'react';
import { useBusterNotifications } from '@/context/BusterNotifications';
@ -11,18 +12,20 @@ import { useGetCurrentMessageId } from './useGetActiveChat';
import { useGetChatId } from './useGetChatId';
import { useIsChatMode, useIsFileMode } from './useMode';
export const useChatInputFlow = ({
export const useFollowUpChatInputFlow = ({
disableSubmit,
inputValue,
setInputValue,
textAreaRef,
loading,
mode,
}: {
disableSubmit: boolean;
inputValue: string;
setInputValue: (value: string) => void;
textAreaRef: React.RefObject<HTMLTextAreaElement | null>;
loading: boolean;
mode: MessageAnalysisMode;
}) => {
const isChatMode = useIsChatMode();
const isFileMode = useIsFileMode();
@ -58,7 +61,7 @@ export const useChatInputFlow = ({
submittingCooldown.current = true;
if (isChatMode || selectedAssetType === 'chat') {
await onFollowUpChat({ prompt: trimmedInputValue, chatId });
await onFollowUpChat({ prompt: trimmedInputValue, chatId, mode });
} else if (selectedAssetType === 'collection') {
// maybe we will support this one day. Good day that'll be. Until then, we will just dream.
console.warn('collection mode is not supported yet');
@ -70,7 +73,7 @@ export const useChatInputFlow = ({
fileType: selectedAssetType,
});
} else {
await onStartNewChat({ prompt: trimmedInputValue, mode: 'auto' });
await onStartNewChat({ prompt: trimmedInputValue, mode });
}
setInputValue('');

View File

@ -7,8 +7,8 @@ import { useAutoScroll } from '@/hooks/useAutoScroll';
import { useMount } from '@/hooks/useMount';
import { cn } from '@/lib/utils';
import { CHAT_CONTAINER_ID } from '../ChatContainer';
import { ChatInput } from './ChatInput';
import { ChatMessageBlock } from './ChatMessageBlock';
import { FollowUpChatInput } from './FollowupChatInput';
const autoClass = 'mx-auto max-w-[600px] w-full';
@ -77,7 +77,7 @@ const ChatInputWrapper: React.FC<{
<div className="bg-page-background absolute bottom-0 w-full overflow-visible">
<div className="from-page-background pointer-events-none absolute -top-16 h-16 w-full bg-gradient-to-t to-transparent" />
<div className={cn(autoClass, 'relative')}>
<ChatInput />
<FollowUpChatInput />
{children}
</div>
</div>

View File

@ -1 +0,0 @@
export * from './ChatInput';

View File

@ -1,16 +1,17 @@
import type { MessageAnalysisMode } from '@buster/server-shared/chats';
import React, { type ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';
import { InputTextAreaButton } from '@/components/ui/inputs/InputTextAreaButton';
import { Text } from '@/components/ui/typography';
import { useChatPermission, useIsStreamingMessage } from '@/context/Chats';
import { useFollowUpChatInputFlow } from '@/context/Chats/useFollowUpChatInputFlow';
import { useGetChatId } from '@/context/Chats/useGetChatId';
import { useIsChatMode } from '@/context/Chats/useMode';
import { cn } from '@/lib/classMerge';
import { canEdit } from '@/lib/share';
import { inputHasText } from '@/lib/text';
import { useChatInputFlow } from '../../../../context/Chats/useChatInputFlow';
import { AIWarning } from './AIWarning';
export const ChatInput: React.FC = React.memo(() => {
export const FollowUpChatInput: React.FC = React.memo(() => {
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const isStreamingMessage = useIsStreamingMessage();
const hasChat = useIsChatMode();
@ -19,17 +20,19 @@ export const ChatInput: React.FC = React.memo(() => {
const canEditChat = canEdit(permission);
const [inputValue, setInputValue] = useState('');
const [mode, setMode] = useState<MessageAnalysisMode>('auto');
const disableSubmit = useMemo(() => {
return (!inputHasText(inputValue) && !isStreamingMessage) || !canEditChat;
}, [inputValue, isStreamingMessage, canEditChat]);
const { onSubmitPreflight, onStopChat } = useChatInputFlow({
const { onSubmitPreflight, onStopChat } = useFollowUpChatInputFlow({
disableSubmit,
inputValue,
setInputValue,
loading: isStreamingMessage,
textAreaRef,
mode,
});
const onChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
@ -81,4 +84,4 @@ export const ChatInput: React.FC = React.memo(() => {
);
});
ChatInput.displayName = 'ChatInput';
FollowUpChatInput.displayName = 'FollowUpChatInput';

View File

@ -0,0 +1 @@
export * from './FollowupChatInput';