|
@@ -4,11 +4,8 @@ import React, { useEffect, useRef, useState } from "react"
|
|
|
import * as R from 'ramda'
|
|
|
import markdownit from 'markdown-it'
|
|
|
import { v4 as uuid4 } from 'uuid'
|
|
|
-import TextareaAutosize from 'react-textarea-autosize';
|
|
|
-import { BsCapslockFill, BsFillStopFill } from "react-icons/bs";
|
|
|
-
|
|
|
-
|
|
|
import Chater from './Chater'
|
|
|
+import Sender from '@/components/ChatSender'
|
|
|
import { useReducerAtom } from "jotai/utils"
|
|
|
import { getChatResponse, template } from "@/lib/utils"
|
|
|
import { useSession } from "next-auth/react"
|
|
@@ -37,13 +34,13 @@ const Agent = ({ node, asideInstantAtom }) => {
|
|
|
|
|
|
const onSend = async ({ text, ignoreQuestionMessage = false }: { text: string, ignoreQuestionMessage?: boolean }) => {
|
|
|
const assistantId = R.path(['properties', 'item', 'assistant_id'], node)
|
|
|
- const newMessages = messages
|
|
|
+ const newMessages = []
|
|
|
if (!ignoreQuestionMessage) {
|
|
|
newMessages.push({ type: 'md', role: 'user', content: text })
|
|
|
}
|
|
|
const message = { type: 'md', role: 'assistant', content: '', isLoading: true }
|
|
|
newMessages.push(message)
|
|
|
- setMessages(() => [...newMessages])
|
|
|
+ setMessages((prev) => [...prev, ...newMessages])
|
|
|
// messageItem.current = message
|
|
|
const [chunks, ctrl] = getChatResponse({
|
|
|
text,
|
|
@@ -56,10 +53,9 @@ const Agent = ({ node, asideInstantAtom }) => {
|
|
|
ctrlRef.current = ctrl
|
|
|
for await (const chunk of chunks) {
|
|
|
message.content += chunk;
|
|
|
- setMessages(() => [...newMessages])
|
|
|
+ setMessages((prev) => [...prev])
|
|
|
}
|
|
|
message.isLoading = false
|
|
|
- setMessages(() => [...newMessages])
|
|
|
setIsSending(false)
|
|
|
return message
|
|
|
}
|
|
@@ -92,10 +88,8 @@ const Agent = ({ node, asideInstantAtom }) => {
|
|
|
dispatchCardInstantData({ content: markdownit().render(message.content) })
|
|
|
}
|
|
|
|
|
|
- let firstMark = true
|
|
|
useEffect(() => {
|
|
|
- if (!messages?.length && firstMark) {
|
|
|
- firstMark = false
|
|
|
+ if (!messages?.length) {
|
|
|
onFirstSend()
|
|
|
}
|
|
|
}, [])
|
|
@@ -123,32 +117,22 @@ const Agent = ({ node, asideInstantAtom }) => {
|
|
|
const onStop = async () => {
|
|
|
ctrlRef.current?.abort()
|
|
|
}
|
|
|
- const onKeyDown = (e) => {
|
|
|
- if (e.key === 'Enter' && R.none(R.equals(true), R.props(['altKey', 'shiftKey', 'ctrlKey', 'metaKey'], e))) {
|
|
|
- onCommit()
|
|
|
- e.preventDefault()
|
|
|
- }
|
|
|
+
|
|
|
+ const effectButtons = []
|
|
|
+ if (!isSending) {
|
|
|
+ effectButtons.push(
|
|
|
+ <button key="rerun" className='btn btn-xs' onClick={() => {
|
|
|
+ setMessages([])
|
|
|
+ onFirstSend()
|
|
|
+ }}>重新运行</button>,
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
<div className="w-full h-full flex relative">
|
|
|
<Chater messages={messages} node={node} onAccept={onAccept}></Chater>
|
|
|
- <div className="absolute flex inset-x-2.5 bottom-2.5 w-auto">
|
|
|
- <TextareaAutosize className="textarea textarea-bordered pr-12 w-full resize-none" value={input} onChange={ev => setInput(ev.target.value)} maxRows={4} onKeyDown={onKeyDown} />
|
|
|
- {
|
|
|
- isSending
|
|
|
- ? (
|
|
|
- <button className="btn btn-secondary btn-sm absolute right-[8px] bottom-[8px] w-[2rem] px-0" onClick={onStop}>
|
|
|
- <BsFillStopFill size={18} />
|
|
|
- </button>
|
|
|
- )
|
|
|
- : (
|
|
|
- <button className="btn btn-primary btn-sm absolute right-[8px] bottom-[8px] w-[2rem] px-0" disabled={!input} onClick={onCommit}>
|
|
|
- <BsCapslockFill size={18} />
|
|
|
- </button>
|
|
|
- )
|
|
|
- }
|
|
|
- </div>
|
|
|
+
|
|
|
+ <Sender input={input} onInput={setInput} isSending={isSending} onStop={onStop} onCommit={onCommit} effectButtons={effectButtons} />
|
|
|
</div>
|
|
|
)
|
|
|
}
|