Feat: Allow users to enter text in the middle of a chat #3221 (#8569)

### What problem does this PR solve?

Feat: Allow users to enter text in the middle of a chat #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-06-30 10:36:52 +08:00
committed by GitHub
parent aafeffa292
commit 356d1f3485
12 changed files with 166 additions and 35 deletions

View File

@ -12,6 +12,7 @@ import { useClickDrawer } from '@/components/pdf-drawer/hooks';
import { useFetchAgent } from '@/hooks/use-agent-request';
import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
import { buildMessageUuidWithRole } from '@/utils/chat';
import { InputForm } from './input-form';
const AgentChatBox = () => {
const {
@ -24,6 +25,7 @@ const AgentChatBox = () => {
derivedMessages,
reference,
stopOutputMessage,
send,
} = useSendNextMessage();
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
@ -59,7 +61,9 @@ const AgentChatBox = () => {
index={i}
showLikeButton={false}
sendLoading={sendLoading}
></MessageItem>
>
<InputForm send={send} message={message}></InputForm>
</MessageItem>
);
})}
</Spin>

View File

@ -6,6 +6,7 @@ import {
import { useFetchAgent } from '@/hooks/use-agent-request';
import {
IEventList,
IInputEvent,
IMessageEvent,
MessageEventType,
useSendMessageBySSE,
@ -66,6 +67,21 @@ function findMessageFromList(eventList: IEventList) {
};
}
function findInputFromList(eventList: IEventList) {
const inputEvent = eventList.find(
(x) => x.event === MessageEventType.UserInputs,
) as IInputEvent;
if (!inputEvent) {
return {};
}
return {
id: inputEvent?.message_id,
data: inputEvent?.data,
};
}
const useGetBeginNodePrologue = () => {
const getNode = useGraphStore((state) => state.getNode);
@ -136,10 +152,12 @@ export const useSendNextMessage = () => {
useEffect(() => {
const { content, id } = findMessageFromList(answerList);
const inputAnswer = findInputFromList(answerList);
if (answerList.length > 0) {
addNewestOneAnswer({
answer: content,
id: id,
...inputAnswer,
});
}
}, [answerList, addNewestOneAnswer]);
@ -181,5 +199,6 @@ export const useSendNextMessage = () => {
ref,
removeMessageById,
stopOutputMessage,
send,
};
};

View File

@ -0,0 +1,86 @@
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Message } from '@/interfaces/database/chat';
import { get } from 'lodash';
import { useParams } from 'umi';
import { useSendNextMessage } from './hooks';
const FormSchema = z.object({
username: z.string().min(2, {
message: 'Username must be at least 2 characters.',
}),
});
type InputFormProps = Pick<ReturnType<typeof useSendNextMessage>, 'send'> & {
message: Message;
};
export function InputForm({ send, message }: InputFormProps) {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
username: '',
},
});
const { id: canvasId } = useParams();
function onSubmit(data: z.infer<typeof FormSchema>) {
const inputs = get(message, 'data.inputs', {});
const nextInputs = Object.entries(inputs).reduce((pre, [key, val]) => {
pre[key] = { ...val, value: data.username };
return pre;
}, {});
send({
inputs: nextInputs,
id: canvasId,
});
toast('You submitted the following values', {
description: (
<pre className="mt-2 w-[320px] rounded-md bg-neutral-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
});
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
);
}