dify/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx

117 lines
3.3 KiB
TypeScript

import {
forwardRef,
memo,
useCallback,
useImperativeHandle,
useMemo,
} from 'react'
import { useNodes } from 'reactflow'
import { BlockEnum } from '../../types'
import {
useStore,
useWorkflowStore,
} from '../../store'
import { useWorkflowRun } from '../../hooks'
import type { StartNodeType } from '../../nodes/start/types'
import UserInput from './user-input'
import { useChat } from './hooks'
import type { ChatWrapperRefType } from './index'
import Chat from '@/app/components/base/chat/chat'
import type { OnSend } from '@/app/components/base/chat/types'
import { useFeaturesStore } from '@/app/components/base/features/hooks'
import {
fetchSuggestedQuestions,
stopChatMessageResponding,
} from '@/service/debug'
import { useStore as useAppStore } from '@/app/components/app/store'
const ChatWrapper = forwardRef<ChatWrapperRefType>((_, ref) => {
const nodes = useNodes<StartNodeType>()
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
const startVariables = startNode?.data.variables
const appDetail = useAppStore(s => s.appDetail)
const workflowStore = useWorkflowStore()
const featuresStore = useFeaturesStore()
const inputs = useStore(s => s.inputs)
const workflowRunId = useStore(s => s.workflowRunId)
const { handleStopRun } = useWorkflowRun()
const features = featuresStore!.getState().features
const config = useMemo(() => {
return {
opening_statement: features.opening.opening_statement,
suggested_questions: features.opening.suggested_questions,
suggested_questions_after_answer: features.suggested,
text_to_speech: features.text2speech,
speech_to_text: features.speech2text,
retriever_resource: features.citation,
sensitive_word_avoidance: features.moderation,
file_upload: features.file,
}
}, [features])
const {
conversationId,
chatList,
handleStop,
isResponding,
suggestedQuestions,
handleSend,
handleRestart,
} = useChat(
config,
{
inputs,
promptVariables: (startVariables as any) || [],
},
[],
taskId => stopChatMessageResponding(appDetail!.id, taskId),
)
const doSend = useCallback<OnSend>((query, files) => {
handleSend(
{
query,
files,
inputs: workflowStore.getState().inputs,
conversation_id: conversationId,
},
{
onGetSuggestedQuestions: (messageId, getAbortController) => fetchSuggestedQuestions(appDetail!.id, messageId, getAbortController),
},
)
}, [conversationId, handleSend, workflowStore, appDetail])
const doStop = useCallback(() => {
handleStop()
handleStopRun()
}, [handleStop, handleStopRun])
useImperativeHandle(ref, () => {
return {
handleRestart,
}
}, [handleRestart])
return (
<Chat
config={config as any}
chatList={chatList.map(item => ({ ...item, workflow_run_id: workflowRunId }))}
isResponding={isResponding}
chatContainerclassName='px-4'
chatContainerInnerClassName='pt-6'
chatFooterClassName='px-4 rounded-bl-2xl'
chatFooterInnerClassName='pb-4'
onSend={doSend}
onStopResponding={doStop}
chatNode={<UserInput />}
suggestedQuestions={suggestedQuestions}
showPromptLog
/>
)
})
ChatWrapper.displayName = 'ChatWrapper'
export default memo(ChatWrapper)