human input form display & submit in preview

This commit is contained in:
JzoNg
2025-08-25 16:17:12 +08:00
parent 2d89d59d74
commit e5a2172a85
22 changed files with 467 additions and 42 deletions

View File

@ -1,6 +1,6 @@
import { memo, useCallback, useEffect, useImperativeHandle, useMemo } from 'react'
import { useNodes } from 'reactflow'
import { BlockEnum } from '../../types'
import { BlockEnum, WorkflowRunningStatus } from '../../types'
import {
useStore,
useWorkflowStore,
@ -87,6 +87,7 @@ const ChatWrapper = (
handleSend,
handleRestart,
setTargetMessageId,
handleSubmitHumanInputForm,
} = useChat(
config,
{
@ -127,6 +128,16 @@ const ChatWrapper = (
)
}, [chatList, doSend])
const doHumanInputFormSubmit = useCallback(async (formID: string, formData: any) => {
// Handle human input form submission
await handleSubmitHumanInputForm(formID, formData)
}, [handleSubmitHumanInputForm])
const inputDisabled = useMemo(() => {
const latestMessage = chatList[chatList.length - 1]
return latestMessage.isAnswer && (latestMessage.workflowProcess?.status === WorkflowRunningStatus.Suspended)
}, [chatList])
const { eventEmitter } = useEventEmitterContextContext()
eventEmitter?.useSubscription((v: any) => {
if (v.type === EVENT_WORKFLOW_STOP)
@ -174,6 +185,7 @@ const ChatWrapper = (
inputsForm={(startVariables || []) as any}
onRegenerate={doRegenerate}
onStopResponding={handleStop}
onHumanInputFormSubmit={doHumanInputFormSubmit}
chatNode={(
<>
{showInputsFieldsPanel && <UserInput />}
@ -189,6 +201,8 @@ const ChatWrapper = (
showPromptLog
chatAnswerContainerInner='!pr-2'
switchSibling={setTargetMessageId}
inputDisabled={inputDisabled}
hideAvatar
/>
{showConversationVariableModal && (
<ConversationVariableModal

View File

@ -35,6 +35,7 @@ import type { FileEntity } from '@/app/components/base/file-uploader/types'
import { getThreadMessages } from '@/app/components/base/chat/utils'
import { useInvalidAllLastRun } from '@/service/use-workflow'
import { useParams } from 'next/navigation'
import { submitHumanInputForm } from '@/service/workflow'
type GetAbortController = (abortController: AbortController) => void
type SendCallback = {
@ -499,10 +500,34 @@ export const useChat = (
})
}
},
onHumanInputRequired: ({ data }) => {
responseItem.humanInputFormData = data
updateCurrentQAOnTree({
placeholderQuestionId,
questionItem,
responseItem,
parentId: params.parent_message_id,
})
},
onWorkflowSuspended: ({ data }) => {
console.log(data.suspended_at_node_ids)
responseItem.workflowProcess!.status = WorkflowRunningStatus.Suspended
updateCurrentQAOnTree({
placeholderQuestionId,
questionItem,
responseItem,
parentId: params.parent_message_id,
})
},
},
)
}, [threadMessages, chatTree.length, updateCurrentQAOnTree, handleResponding, formSettings?.inputsForm, handleRun, notify, t, config?.suggested_questions_after_answer?.enabled, fetchInspectVars, invalidAllLastRun])
const handleSubmitHumanInputForm = async (formID: string, formData: any) => {
await submitHumanInputForm(formID, formData)
// TODO deal with success
}
return {
conversationId: conversationId.current,
chatList,
@ -510,6 +535,7 @@ export const useChat = (
handleSend,
handleStop,
handleRestart,
handleSubmitHumanInputForm,
isResponding,
suggestedQuestions,
}

View File

@ -6,7 +6,7 @@ import {
RiAlertFill,
RiArrowRightSLine,
RiCheckboxCircleFill,
RiErrorWarningLine,
RiErrorWarningFill,
RiLoader2Line,
RiPauseCircleFill,
} from '@remixicon/react'
@ -148,7 +148,7 @@ const NodePanel: FC<Props> = ({
<RiCheckboxCircleFill className='ml-2 h-3.5 w-3.5 shrink-0 text-text-success' />
)}
{nodeInfo.status === 'failed' && (
<RiErrorWarningLine className='ml-2 h-3.5 w-3.5 shrink-0 text-text-warning' />
<RiErrorWarningFill className='ml-2 h-3.5 w-3.5 shrink-0 text-text-destructive' />
)}
{nodeInfo.status === 'stopped' && (
<RiAlertFill className={cn('ml-2 h-4 w-4 shrink-0 text-text-warning-secondary', inMessage && 'h-3.5 w-3.5')} />

View File

@ -324,6 +324,7 @@ export enum WorkflowRunningStatus {
Succeeded = 'succeeded',
Failed = 'failed',
Stopped = 'stopped',
Suspended = 'suspended',
}
export enum WorkflowVersion {