buster/web/src/context/Chats/NewChatProvider/NewChatProvider.tsx

165 lines
3.9 KiB
TypeScript
Raw Normal View History

2025-02-09 13:41:08 +08:00
import React from 'react';
2025-02-01 06:21:50 +08:00
import {
createContext,
ContextSelector,
useContextSelector
} from '@fluentui/react-context-selector';
import { useMemoizedFn } from 'ahooks';
2025-02-11 11:15:32 +08:00
import type { BusterSearchResult, FileType } from '@/api/asset_interfaces';
2025-02-11 07:43:38 +08:00
import { useBusterWebSocket } from '@/context/BusterWebSocket';
2025-02-18 07:25:31 +08:00
import { useChatStreamMessage } from './useChatStreamMessage';
2025-02-01 06:21:50 +08:00
export const useBusterNewChat = () => {
2025-02-11 07:43:38 +08:00
const busterSocket = useBusterWebSocket();
const {
completeChatCallback,
2025-02-12 03:32:12 +08:00
stopChatCallback,
2025-02-12 07:46:22 +08:00
initializeNewChatCallback,
2025-02-12 03:32:12 +08:00
replaceMessageCallback
2025-02-18 07:25:31 +08:00
} = useChatStreamMessage();
2025-02-11 07:43:38 +08:00
2025-02-05 13:10:39 +08:00
const onSelectSearchAsset = useMemoizedFn(async (asset: BusterSearchResult) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
});
2025-02-01 06:21:50 +08:00
2025-02-12 03:32:12 +08:00
const onStartNewChat = useMemoizedFn(
async ({
prompt,
datasetId,
metricId,
dashboardId
}: {
prompt: string;
datasetId?: string;
metricId?: string;
dashboardId?: string;
}) => {
2025-03-05 00:32:47 +08:00
const res = await busterSocket.emitAndOnce({
2025-02-12 03:32:12 +08:00
emitEvent: {
route: '/chats/post',
payload: {
dataset_id: datasetId, //TODO: add selected dataset id
prompt,
metric_id: metricId,
dashboard_id: dashboardId
}
},
responseEvent: {
route: '/chats/post:initializeChat',
2025-02-12 07:46:22 +08:00
callback: initializeNewChatCallback
2025-02-12 02:22:27 +08:00
}
2025-02-12 03:32:12 +08:00
});
2025-02-18 07:25:31 +08:00
busterSocket.once({
route: '/chats/post:complete',
callback: completeChatCallback
});
2025-02-12 03:32:12 +08:00
}
);
2025-02-01 06:21:50 +08:00
2025-02-05 13:04:26 +08:00
const onStartChatFromFile = useMemoizedFn(
2025-02-12 07:46:22 +08:00
async ({
prompt,
fileId,
fileType
}: {
prompt: string;
fileId: string;
fileType: FileType;
}) => {
onStartNewChat({
prompt,
metricId: fileType === 'metric' ? fileId : undefined,
dashboardId: fileType === 'dashboard' ? fileId : undefined
});
2025-02-05 13:10:39 +08:00
}
2025-02-05 13:04:26 +08:00
);
const onReplaceMessageInChat = useMemoizedFn(
2025-02-12 03:32:12 +08:00
async ({
prompt,
messageId,
chatId
}: {
prompt: string;
messageId: string;
chatId: string;
}) => {
replaceMessageCallback({
prompt,
messageId
});
await busterSocket.emitAndOnce({
emitEvent: {
route: '/chats/post',
payload: {
prompt,
message_id: messageId,
chat_id: chatId
}
},
responseEvent: {
route: '/chats/post:complete',
callback: completeChatCallback
}
});
2025-02-05 13:10:39 +08:00
}
2025-02-05 13:04:26 +08:00
);
2025-02-11 07:43:38 +08:00
const onFollowUpChat = useMemoizedFn(
async ({ prompt, chatId }: { prompt: string; chatId: string }) => {
2025-02-12 03:32:12 +08:00
await busterSocket.emitAndOnce({
2025-02-11 07:43:38 +08:00
emitEvent: {
route: '/chats/post',
payload: {
prompt,
chat_id: chatId
}
},
responseEvent: {
route: '/chats/post:complete',
callback: completeChatCallback
}
});
}
);
const onStopChat = useMemoizedFn(
({ chatId, messageId }: { chatId: string; messageId: string }) => {
busterSocket.emit({
route: '/chats/stop',
payload: {
id: chatId,
message_id: messageId
}
});
stopChatCallback(chatId);
}
);
2025-02-01 06:21:50 +08:00
return {
onStartNewChat,
onSelectSearchAsset,
2025-02-05 13:04:26 +08:00
onFollowUpChat,
onStartChatFromFile,
2025-02-06 00:55:09 +08:00
onReplaceMessageInChat,
onStopChat
2025-02-01 06:21:50 +08:00
};
};
export const BusterNewChatContext = createContext<ReturnType<typeof useBusterNewChat>>(
{} as ReturnType<typeof useBusterNewChat>
);
export const BusterNewChatProvider: React.FC<{
children: React.ReactNode;
}> = ({ children }) => {
const value = useBusterNewChat();
return <BusterNewChatContext.Provider value={value}>{children}</BusterNewChatContext.Provider>;
};
export const useBusterNewChatContextSelector = <T,>(
selector: ContextSelector<ReturnType<typeof useBusterNewChat>, T>
) => useContextSelector(BusterNewChatContext, selector);