mirror of https://github.com/buster-so/buster.git
Merge branch 'big-nate/bus-939-create-new-structure-for-chats' into evals
This commit is contained in:
commit
4ba639ecc5
|
@ -8,25 +8,26 @@ import {
|
|||
updateChat,
|
||||
deleteChat
|
||||
} from './requests';
|
||||
import type { BusterChatListItem, IBusterChat } from '@/api/asset_interfaces/chat';
|
||||
import type { IBusterChat } from '@/api/asset_interfaces/chat';
|
||||
import { queryKeys } from '@/api/query_keys';
|
||||
import { updateChatToIChat } from '@/lib/chat';
|
||||
import { RustApiError } from '@/api/buster_rest/errors';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useGetListChats = (params?: Parameters<typeof getListChats>[0]) => {
|
||||
const queryFn = useMemoizedFn((): Promise<BusterChatListItem[]> => {
|
||||
return getListChats(params);
|
||||
});
|
||||
export const useGetListChats = (
|
||||
filters?: Omit<Parameters<typeof getListChats>[0], 'page_token' | 'page_size'>
|
||||
) => {
|
||||
const filtersCompiled: Parameters<typeof getListChats>[0] = useMemo(
|
||||
() => ({ admin_view: false, page_token: 0, page_size: 3000, ...filters }),
|
||||
[filters]
|
||||
);
|
||||
|
||||
const res = useQuery({
|
||||
...queryKeys.chatsGetList(params),
|
||||
const queryFn = useMemoizedFn(() => getListChats(filtersCompiled));
|
||||
|
||||
return useQuery({
|
||||
...queryKeys.chatsGetList(filtersCompiled),
|
||||
queryFn
|
||||
});
|
||||
|
||||
return {
|
||||
...res,
|
||||
data: res.data || []
|
||||
};
|
||||
};
|
||||
|
||||
export const prefetchGetListChats = async (
|
||||
|
|
|
@ -13,7 +13,7 @@ const CHATS_BASE = '/chats';
|
|||
export const getListChats = async (params?: GetChatListParams): Promise<BusterChatListItem[]> => {
|
||||
const { page_token = 0, page_size = 1000, admin_view = false } = params || {};
|
||||
return mainApi
|
||||
.get<BusterChatListItem[]>(`${CHATS_BASE}/list`, {
|
||||
.get<BusterChatListItem[]>(`${CHATS_BASE}`, {
|
||||
params: { page_token, page_size, admin_view }
|
||||
})
|
||||
.then((res) => res.data);
|
||||
|
@ -24,7 +24,7 @@ export const getListChats_server = async (
|
|||
params?: GetChatListParams
|
||||
): Promise<BusterChatListItem[]> => {
|
||||
const { page_token = 0, page_size = 1000, admin_view = false } = params || {};
|
||||
return await serverFetch<BusterChatListItem[]>(`${CHATS_BASE}/list`, {
|
||||
return await serverFetch<BusterChatListItem[]>(`${CHATS_BASE}`, {
|
||||
params: { page_token, page_size, admin_view }
|
||||
});
|
||||
};
|
||||
|
|
|
@ -29,26 +29,24 @@ export const listMetrics_server = async (params: ListMetricsParams) => {
|
|||
return await serverFetch<BusterMetricListItem[]>('/metrics/list', { params });
|
||||
};
|
||||
|
||||
export const getMetricData = async (params: { id: string }) => {
|
||||
return mainApi.get<BusterMetricData>(`/metrics/data`, { params }).then((res) => res.data);
|
||||
export const getMetricData = async ({ id }: { id: string }) => {
|
||||
return mainApi.get<BusterMetricData>(`/metrics/data/${id}`).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const updateMetric = async (params: UpdateMetricParams) => {
|
||||
return mainApi.put<BusterMetric>(`/metrics/update`, { params }).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const deleteMetrics = async (params: { ids: string[] }) => {
|
||||
return mainApi
|
||||
.delete<BusterMetricListItem[]>(`/metrics/delete`, { params })
|
||||
.put<BusterMetric>(`/metrics/update/${params.id}`, { params })
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
export const duplicateMetrics = async (params: {
|
||||
export const deleteMetrics = async (params: { ids: string[] }) => {
|
||||
return mainApi.delete<null>(`/metrics/delete`, { params }).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const duplicateMetric = async (params: {
|
||||
id: string;
|
||||
message_id: string;
|
||||
share_with_same_people: boolean;
|
||||
}) => {
|
||||
return mainApi
|
||||
.post<BusterMetricListItem[]>(`/metrics/duplicate`, { params })
|
||||
.then((res) => res.data);
|
||||
return mainApi.post<BusterMetric>(`/metrics/duplicate`, { params }).then((res) => res.data);
|
||||
};
|
||||
|
|
|
@ -16,8 +16,7 @@ export const useGetOrganizationUsers = (organizationId: string) => {
|
|||
queryKey,
|
||||
staleTime: 10 * 1000,
|
||||
queryFn,
|
||||
enabled: !!organizationId,
|
||||
initialData: []
|
||||
enabled: !!organizationId
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@ const chatsMessagesFetchingData = (messageId: string) =>
|
|||
const chatsGetList = (filters?: GetChatListParams) =>
|
||||
queryOptions<BusterChatListItem[]>({
|
||||
queryKey: ['chats', 'list', filters] as const,
|
||||
staleTime: 10 * 1000
|
||||
staleTime: 0,
|
||||
initialData: []
|
||||
});
|
||||
|
||||
const chatsBlackBoxMessages = (messageId: string) =>
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { useBusterChatListByFilter } from '@/context/Chats';
|
||||
import { ChatItemsContainer } from './ChatItemsContainer';
|
||||
import { useGetListChats } from '@/api/buster_rest/chats';
|
||||
import { GetChatListParams } from '@/api/request_interfaces/chats';
|
||||
|
||||
export const ChatListContainer: React.FC<{}> = ({}) => {
|
||||
const [filters, setFilters] = useState<Parameters<typeof useBusterChatListByFilter>[0]>({
|
||||
const [filters, setFilters] = useState<Partial<GetChatListParams>>({
|
||||
admin_view: false
|
||||
});
|
||||
|
||||
const { list, isFetched } = useBusterChatListByFilter(filters);
|
||||
const { data: list, isFetched } = useGetListChats(filters);
|
||||
|
||||
return <ChatItemsContainer chats={list} loading={!isFetched} />;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { Toaster } from '@/components/ui/toaster/Toaster';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { toast, type ExternalToast } from 'sonner';
|
||||
import { useContextSelector, createContext } from 'use-context-selector';
|
||||
|
@ -167,7 +168,7 @@ export const BusterNotificationsProvider: React.FC<PropsWithChildren> = ({ child
|
|||
return (
|
||||
<BusterNotifications.Provider value={value}>
|
||||
{children}
|
||||
{/* <Toaster /> */}
|
||||
<Toaster />
|
||||
</BusterNotifications.Provider>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -21,8 +21,8 @@ function makeQueryClient(params?: {
|
|||
enabled: (params?.enabled ?? true) && baseEnabled,
|
||||
queryFn: () => Promise.resolve(),
|
||||
retry: (failureCount, error) => {
|
||||
if (params?.openErrorNotification && failureCount > 0) {
|
||||
params.openErrorNotification(error);
|
||||
if (params?.openErrorNotification) {
|
||||
// params.openErrorNotification(error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export * from './useBusterChatListByFilter';
|
|
@ -1,21 +0,0 @@
|
|||
import { useGetListChats } from '@/api/buster_rest/chats';
|
||||
import { GetChatListParams } from '@/api/request_interfaces/chats';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useBusterChatListByFilter = (
|
||||
filtersProp: Omit<GetChatListParams, 'page_token' | 'page_size'>
|
||||
) => {
|
||||
const filters = useMemo(
|
||||
() => ({ ...filtersProp, page_token: 0, page_size: 3000 }),
|
||||
[filtersProp]
|
||||
);
|
||||
|
||||
const { data: chatsList, isFetched: isFetchedChatsList } = useGetListChats(filters);
|
||||
|
||||
//ACTIONS
|
||||
|
||||
return {
|
||||
list: chatsList || [],
|
||||
isFetched: isFetchedChatsList
|
||||
};
|
||||
};
|
|
@ -1,12 +1,6 @@
|
|||
import { useBusterNewChatContextSelector } from './NewChatProvider';
|
||||
import { useBusterChatContextSelector, useMessageIndividual } from './ChatProvider';
|
||||
import { useBusterChatListByFilter } from './ChatListProvider';
|
||||
|
||||
export * from './BusterChatProvider';
|
||||
|
||||
export {
|
||||
useBusterNewChatContextSelector,
|
||||
useBusterChatContextSelector,
|
||||
useBusterChatListByFilter,
|
||||
useMessageIndividual
|
||||
};
|
||||
export { useBusterNewChatContextSelector, useBusterChatContextSelector, useMessageIndividual };
|
||||
|
|
|
@ -13,10 +13,14 @@ export const BarContainer: React.FC<{
|
|||
children?: React.ReactNode;
|
||||
title: string;
|
||||
secondaryTitle?: string;
|
||||
}> = React.memo(({ showBar, status, children, title, secondaryTitle }) => {
|
||||
}> = React.memo(({ showBar, isCompletedStream, status, children, title, secondaryTitle }) => {
|
||||
return (
|
||||
<div className={'relative flex space-x-1.5 overflow-hidden'}>
|
||||
<VerticalBarContainer showBar={showBar} status={status} />
|
||||
<VerticalBarContainer
|
||||
showBar={showBar}
|
||||
status={status}
|
||||
isCompletedStream={isCompletedStream}
|
||||
/>
|
||||
|
||||
<div className={`mb-2 flex w-full flex-col space-y-2 overflow-hidden`}>
|
||||
<TitleContainer title={title} secondaryTitle={secondaryTitle} />
|
||||
|
@ -31,37 +35,44 @@ BarContainer.displayName = 'BarContainer';
|
|||
const VerticalBarContainer: React.FC<{
|
||||
showBar: boolean;
|
||||
status: BusterChatMessageReasoning_status;
|
||||
}> = React.memo(({ showBar, status }) => {
|
||||
isCompletedStream: boolean;
|
||||
}> = React.memo(({ showBar, isCompletedStream, status }) => {
|
||||
return (
|
||||
<div className="ml-2 flex w-5 min-w-5 flex-col items-center">
|
||||
<StatusIndicator status={status} />
|
||||
<VerticalBar show={showBar} />
|
||||
<VerticalBar show={showBar} isCompletedStream={isCompletedStream} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
VerticalBarContainer.displayName = 'BarContainer';
|
||||
|
||||
const VerticalBar: React.FC<{ show?: boolean }> = ({ show }) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex w-full flex-1 justify-center overflow-hidden',
|
||||
'opacity-0 transition-opacity duration-300',
|
||||
show && 'opacity-100!'
|
||||
)}>
|
||||
<motion.div
|
||||
className={cn('bg-text-tertiary w-[0.5px]', 'mt-1 overflow-hidden')}
|
||||
initial={{ height: 0 }}
|
||||
animate={{ height: 'auto' }}
|
||||
transition={{
|
||||
duration: 0.3,
|
||||
ease: 'easeInOut'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const VerticalBar: React.FC<{ show?: boolean; isCompletedStream: boolean }> = React.memo(
|
||||
({ show, isCompletedStream }) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex w-full flex-1 justify-center overflow-hidden',
|
||||
'opacity-0 transition-opacity duration-300',
|
||||
show && 'opacity-100!'
|
||||
)}>
|
||||
<AnimatePresence initial={!isCompletedStream}>
|
||||
<motion.div
|
||||
className={cn('bg-text-tertiary w-[0.5px]', 'mt-1 overflow-hidden')}
|
||||
initial={{ height: 0 }}
|
||||
animate={{ height: 'auto' }}
|
||||
transition={{
|
||||
duration: 0.3,
|
||||
ease: 'easeInOut'
|
||||
}}
|
||||
/>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
VerticalBar.displayName = 'VerticalBar';
|
||||
|
||||
const TitleContainer: React.FC<{
|
||||
title: string;
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import React from 'react';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
|
||||
export const AIWarning = React.memo(() => {
|
||||
return (
|
||||
<div className="w-full truncate overflow-hidden text-center">
|
||||
<Text size="xs" variant="tertiary" truncate>
|
||||
Our AI may make mistakes. Check important info.
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
export const AIWarning = React.memo(
|
||||
() => {
|
||||
return (
|
||||
<div className="w-full truncate overflow-hidden text-center">
|
||||
<Text size="xs" variant="tertiary" truncate>
|
||||
Our AI may make mistakes. Check important info.
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
() => true
|
||||
);
|
||||
|
||||
AIWarning.displayName = 'AIWarning';
|
||||
|
|
|
@ -18,7 +18,7 @@ export const ChatInput: React.FC<{}> = React.memo(({}) => {
|
|||
return !inputHasText(inputValue);
|
||||
}, [inputValue]);
|
||||
|
||||
const { onSubmitPreflight } = useChatInputFlow({
|
||||
const { onSubmitPreflight, onStopChat } = useChatInputFlow({
|
||||
disableSubmit,
|
||||
inputValue,
|
||||
setInputValue,
|
||||
|
@ -30,10 +30,6 @@ export const ChatInput: React.FC<{}> = React.memo(({}) => {
|
|||
setInputValue(e.target.value);
|
||||
});
|
||||
|
||||
const onStop = useMemoizedFn(() => {
|
||||
// setInputValue('');
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
@ -45,7 +41,7 @@ export const ChatInput: React.FC<{}> = React.memo(({}) => {
|
|||
autoResize={autoResizeConfig}
|
||||
onSubmit={onSubmitPreflight}
|
||||
onChange={onChange}
|
||||
onStop={onStop}
|
||||
onStop={onStopChat}
|
||||
loading={loading}
|
||||
disabledSubmit={disableSubmit}
|
||||
autoFocus
|
||||
|
|
|
@ -25,7 +25,7 @@ export const useChatInputFlow = ({
|
|||
const onStartNewChat = useBusterNewChatContextSelector((state) => state.onStartNewChat);
|
||||
const onFollowUpChat = useBusterNewChatContextSelector((state) => state.onFollowUpChat);
|
||||
const onStartChatFromFile = useBusterNewChatContextSelector((state) => state.onStartChatFromFile);
|
||||
const onStopChat = useBusterNewChatContextSelector((state) => state.onStopChat);
|
||||
const onStopChatContext = useBusterNewChatContextSelector((state) => state.onStopChat);
|
||||
const currentMessageId = useChatIndividualContextSelector((x) => x.currentMessageId);
|
||||
|
||||
const flow: FlowType = useMemo(() => {
|
||||
|
@ -39,7 +39,7 @@ export const useChatInputFlow = ({
|
|||
if (disableSubmit || !chatId || !currentMessageId) return;
|
||||
|
||||
if (loading) {
|
||||
onStopChat({ chatId: chatId!, messageId: currentMessageId });
|
||||
onStopChat();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -79,5 +79,11 @@ export const useChatInputFlow = ({
|
|||
}, 50);
|
||||
});
|
||||
|
||||
return { onSubmitPreflight };
|
||||
const onStopChat = useMemoizedFn(() => {
|
||||
onStopChatContext({ chatId: chatId!, messageId: currentMessageId });
|
||||
textAreaRef.current?.focus();
|
||||
textAreaRef.current?.select();
|
||||
});
|
||||
|
||||
return { onSubmitPreflight, onStopChat };
|
||||
};
|
||||
|
|
|
@ -3,7 +3,9 @@ import { createContext, useContextSelector } from 'use-context-selector';
|
|||
import type { SelectedFile } from '../interfaces';
|
||||
import { useAutoChangeLayout } from './useAutoChangeLayout';
|
||||
import { useGetChat } from '@/api/buster_rest/chats';
|
||||
import { useMessageIndividual } from '@/context/Chats';
|
||||
import { useQueries } from '@tanstack/react-query';
|
||||
import { queryKeys } from '@/api/query_keys';
|
||||
import { IBusterChatMessage } from '@/api/asset_interfaces/chat';
|
||||
|
||||
const useChatIndividualContext = ({
|
||||
chatId,
|
||||
|
@ -28,7 +30,18 @@ const useChatIndividualContext = ({
|
|||
|
||||
//MESSAGES
|
||||
const currentMessageId = chatMessageIds[chatMessageIds.length - 1];
|
||||
const isStreamingMessage = useMessageIndividual(currentMessageId, (x) => !x?.isCompletedStream);
|
||||
|
||||
const isStreamingMessage = useQueries({
|
||||
queries: chatMessageIds.map((messageId) => {
|
||||
const queryKey = queryKeys.chatsMessages(messageId);
|
||||
return {
|
||||
...queryKey,
|
||||
select: (data: IBusterChatMessage | undefined) => !data?.isCompletedStream,
|
||||
enabled: false
|
||||
};
|
||||
}),
|
||||
combine: (result) => result.some((res) => res.data)
|
||||
});
|
||||
|
||||
useAutoChangeLayout({
|
||||
lastMessageId: currentMessageId,
|
||||
|
|
Loading…
Reference in New Issue