mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
chore: adapt UI to server-side Unleash AI chat ownership (#8466)
https://linear.app/unleash/issue/2-2847/adapt-unleash-ai-chat-logic-to-new-server-side-chat-ownership-logic Adapts the Unleash AI chat logic on the UI to the new server-side chat ownership logic.
This commit is contained in:
parent
793221524c
commit
f2256423d5
@ -15,6 +15,11 @@ import { AIChatMessage } from './AIChatMessage';
|
||||
import { AIChatHeader } from './AIChatHeader';
|
||||
import { Resizable } from 'component/common/Resizable/Resizable';
|
||||
|
||||
const AI_ERROR_MESSAGE = {
|
||||
role: 'assistant',
|
||||
content: `I'm sorry, I'm having trouble understanding you right now. I've reported the issue to the team. Please try again later.`,
|
||||
} as const;
|
||||
|
||||
const StyledAIIconContainer = styled('div')(({ theme }) => ({
|
||||
position: 'fixed',
|
||||
bottom: 20,
|
||||
@ -71,13 +76,6 @@ const StyledChatContent = styled('div')(({ theme }) => ({
|
||||
overflowX: 'hidden',
|
||||
}));
|
||||
|
||||
const initialMessages: ChatMessage[] = [
|
||||
{
|
||||
role: 'system',
|
||||
content: `You are an assistant that helps users interact with Unleash. You should ask the user in case you're missing any required information.`,
|
||||
},
|
||||
];
|
||||
|
||||
export const AIChat = () => {
|
||||
const unleashAIEnabled = useUiFlag('unleashAI');
|
||||
const {
|
||||
@ -86,9 +84,9 @@ export const AIChat = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { setToastApiError } = useToast();
|
||||
const { chat } = useAIApi();
|
||||
const { chat, newChat } = useAIApi();
|
||||
|
||||
const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);
|
||||
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
||||
|
||||
const chatEndRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
@ -106,26 +104,34 @@ export const AIChat = () => {
|
||||
scrollToEnd();
|
||||
}, [open]);
|
||||
|
||||
const onSend = async (message: string) => {
|
||||
if (!message.trim() || loading) return;
|
||||
const onSend = async (content: string) => {
|
||||
if (!content.trim() || loading) return;
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
const tempMessages: ChatMessage[] = [
|
||||
...messages,
|
||||
{ role: 'user', content: message },
|
||||
{ role: 'assistant', content: '_Unleash AI is typing..._' },
|
||||
];
|
||||
setMessages(tempMessages);
|
||||
const newMessages = await chat(tempMessages.slice(0, -1));
|
||||
setMessages((currentMessages) => [
|
||||
...currentMessages,
|
||||
{ role: 'user', content },
|
||||
]);
|
||||
const { messages: newMessages } = await chat(content);
|
||||
mutate(() => true);
|
||||
setMessages(newMessages);
|
||||
setLoading(false);
|
||||
} catch (error: unknown) {
|
||||
setMessages((currentMessages) => [
|
||||
...currentMessages,
|
||||
AI_ERROR_MESSAGE,
|
||||
]);
|
||||
setToastApiError(formatUnknownError(error));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onNewChat = () => {
|
||||
setMessages([]);
|
||||
newChat();
|
||||
};
|
||||
|
||||
if (!unleashAIEnabled || !unleashAIAvailable) {
|
||||
return null;
|
||||
}
|
||||
@ -151,7 +157,7 @@ export const AIChat = () => {
|
||||
>
|
||||
<StyledChat>
|
||||
<AIChatHeader
|
||||
onNew={() => setMessages(initialMessages)}
|
||||
onNew={onNewChat}
|
||||
onClose={() => setOpen(false)}
|
||||
/>
|
||||
<StyledChatContent>
|
||||
@ -163,6 +169,11 @@ export const AIChat = () => {
|
||||
{content}
|
||||
</AIChatMessage>
|
||||
))}
|
||||
{loading && (
|
||||
<AIChatMessage from='assistant'>
|
||||
_Unleash AI is typing..._
|
||||
</AIChatMessage>
|
||||
)}
|
||||
<div ref={chatEndRef} />
|
||||
</StyledChatContent>
|
||||
<AIChatInput onSend={onSend} loading={loading} />
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import useAPI from '../useApi/useApi';
|
||||
|
||||
const ENDPOINT = 'api/admin/ai';
|
||||
@ -7,29 +8,47 @@ export type ChatMessage = {
|
||||
content: string;
|
||||
};
|
||||
|
||||
type Chat = {
|
||||
id: string;
|
||||
userId: number;
|
||||
createdAt: string;
|
||||
messages: ChatMessage[];
|
||||
};
|
||||
|
||||
export const useAIApi = () => {
|
||||
const { makeRequest, createRequest, errors, loading } = useAPI({
|
||||
propagateErrors: true,
|
||||
});
|
||||
|
||||
const chat = async (messages: ChatMessage[]): Promise<ChatMessage[]> => {
|
||||
const [chatId, setChatId] = useState<string>();
|
||||
|
||||
const chat = async (message: string): Promise<Chat> => {
|
||||
const requestId = 'chat';
|
||||
|
||||
const req = createRequest(`${ENDPOINT}/chat`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
messages,
|
||||
}),
|
||||
requestId,
|
||||
});
|
||||
const req = createRequest(
|
||||
`${ENDPOINT}/chat${chatId ? `/${chatId}` : ''}`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
message,
|
||||
}),
|
||||
requestId,
|
||||
},
|
||||
);
|
||||
|
||||
const response = await makeRequest(req.caller, req.id);
|
||||
const { messages: newMessages } = await response.json();
|
||||
return newMessages;
|
||||
const chat: Chat = await response.json();
|
||||
setChatId(chat.id);
|
||||
return chat;
|
||||
};
|
||||
|
||||
const newChat = () => {
|
||||
setChatId(undefined);
|
||||
};
|
||||
|
||||
return {
|
||||
chat,
|
||||
newChat,
|
||||
errors,
|
||||
loading,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user