human input in workflow apps

This commit is contained in:
JzoNg 2026-01-08 14:45:05 +08:00
parent d3299db915
commit 1cdbfa2539
6 changed files with 270 additions and 369 deletions

View File

@ -18,10 +18,12 @@ import { useBoolean } from 'ahooks'
import copy from 'copy-to-clipboard'
import { useParams } from 'next/navigation'
import * as React from 'react'
import { useEffect, useState } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useStore as useAppStore } from '@/app/components/app/store'
import ActionButton, { ActionButtonState } from '@/app/components/base/action-button'
import HumanInputFilledFormList from '@/app/components/base/chat/chat/answer/human-input-filled-form-list'
import HumanInputFormList from '@/app/components/base/chat/chat/answer/human-input-form-list'
import WorkflowProcessItem from '@/app/components/base/chat/chat/answer/workflow-process'
import { useChatContext } from '@/app/components/base/chat/chat/context'
import Loading from '@/app/components/base/loading'
@ -29,7 +31,8 @@ import { Markdown } from '@/app/components/base/markdown'
import NewAudioButton from '@/app/components/base/new-audio-button'
import Toast from '@/app/components/base/toast'
import { fetchTextGenerationMessage } from '@/service/debug'
import { fetchMoreLikeThis, updateFeedback } from '@/service/share'
import { fetchMoreLikeThis, submitHumanInputForm, updateFeedback } from '@/service/share'
import { submitHumanInputForm as submitHumanInputFormService } from '@/service/workflow'
import { cn } from '@/utils/classnames'
import ResultTab from './result-tab'
@ -201,16 +204,22 @@ const GenerationItem: FC<IGenerationItemProps> = ({
}
const [currentTab, setCurrentTab] = useState<string>('DETAIL')
const showResultTabs = !!workflowProcessData?.resultText || !!workflowProcessData?.files?.length
const showResultTabs = !!workflowProcessData?.resultText || !!workflowProcessData?.files?.length || (workflowProcessData?.humanInputFormDataList && workflowProcessData?.humanInputFormDataList.length > 0) || (workflowProcessData?.humanInputFilledFormDataList && workflowProcessData?.humanInputFilledFormDataList.length > 0)
const switchTab = async (tab: string) => {
setCurrentTab(tab)
}
useEffect(() => {
if (workflowProcessData?.resultText || !!workflowProcessData?.files?.length)
if (workflowProcessData?.resultText || !!workflowProcessData?.files?.length || (workflowProcessData?.humanInputFormDataList && workflowProcessData?.humanInputFormDataList.length > 0) || (workflowProcessData?.humanInputFilledFormDataList && workflowProcessData?.humanInputFilledFormDataList.length > 0))
switchTab('RESULT')
else
switchTab('DETAIL')
}, [workflowProcessData?.files?.length, workflowProcessData?.resultText])
}, [workflowProcessData?.files?.length, workflowProcessData?.resultText, workflowProcessData?.humanInputFormDataList, workflowProcessData?.humanInputFilledFormDataList])
const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: any) => {
if (isInstalledApp)
await submitHumanInputFormService(formToken, formData)
else
await submitHumanInputForm(formToken, formData)
}, [isInstalledApp])
return (
<>
@ -274,7 +283,24 @@ const GenerationItem: FC<IGenerationItemProps> = ({
)}
</div>
{!isError && (
<ResultTab data={workflowProcessData} content={content} currentTab={currentTab} />
<>
{currentTab === 'RESULT' && workflowProcessData.humanInputFormDataList && workflowProcessData.humanInputFormDataList.length > 0 && (
<div className="px-4 pt-4">
<HumanInputFormList
humanInputFormDataList={workflowProcessData.humanInputFormDataList}
onHumanInputFormSubmit={handleSubmitHumanInputForm}
/>
</div>
)}
{currentTab === 'RESULT' && workflowProcessData.humanInputFilledFormDataList && workflowProcessData.humanInputFilledFormDataList.length > 0 && (
<div className="px-4 pt-4">
<HumanInputFilledFormList
humanInputFilledFormDataList={workflowProcessData.humanInputFilledFormDataList}
/>
</div>
)}
<ResultTab data={workflowProcessData} content={content} currentTab={currentTab} />
</>
)}
</>
)}

View File

@ -5,7 +5,7 @@ import type {
ModelConfig,
VisionSettings,
} from '@/types/app'
import type { NodeTracing } from '@/types/workflow'
import type { HumanInputFilledFormData, HumanInputFormData, NodeTracing } from '@/types/workflow'
export type {
Inputs,
@ -67,6 +67,8 @@ export type WorkflowProcess = {
expand?: boolean // for UI
resultText?: string
files?: FileEntity[]
humanInputFormDataList?: HumanInputFormData[]
humanInputFilledFormDataList?: HumanInputFilledFormData[]
}
export type ChatItem = IChatItem & {

View File

@ -1,35 +0,0 @@
import type { FC } from 'react'
import type { FeedbackType } from '@/app/components/base/chat/chat/type'
import * as React from 'react'
import { format } from '@/service/base'
import Header from './header'
export type IResultProps = {
content: string
showFeedback: boolean
feedback: FeedbackType
onFeedback: (feedback: FeedbackType) => void
}
const Result: FC<IResultProps> = ({
content,
showFeedback,
feedback,
onFeedback,
}) => {
return (
<div className="h-max basis-3/4">
<Header result={content} showFeedback={showFeedback} feedback={feedback} onFeedback={onFeedback} />
<div
className="mt-4 flex w-full overflow-scroll text-sm font-normal leading-5 text-gray-900"
style={{
maxHeight: '70vh',
}}
dangerouslySetInnerHTML={{
__html: format(content),
}}
>
</div>
</div>
)
}
export default React.memo(Result)

View File

@ -1,117 +0,0 @@
'use client'
import type { FC } from 'react'
import type { FeedbackType } from '@/app/components/base/chat/chat/type'
import { ClipboardDocumentIcon, HandThumbDownIcon, HandThumbUpIcon } from '@heroicons/react/24/outline'
import copy from 'copy-to-clipboard'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import Toast from '@/app/components/base/toast'
import Tooltip from '@/app/components/base/tooltip'
type IResultHeaderProps = {
result: string
showFeedback: boolean
feedback: FeedbackType
onFeedback: (feedback: FeedbackType) => void
}
const Header: FC<IResultHeaderProps> = ({
feedback,
showFeedback,
onFeedback,
result,
}) => {
const { t } = useTranslation()
return (
<div className="flex w-full items-center justify-between ">
<div className="text-2xl font-normal leading-4 text-gray-800">{t('generation.resultTitle', { ns: 'share' })}</div>
<div className="flex items-center space-x-2">
<Button
className="h-7 p-[2px] pr-2"
onClick={() => {
copy(result)
Toast.notify({ type: 'success', message: 'copied' })
}}
>
<>
<ClipboardDocumentIcon className="mr-1 h-3 w-4 text-gray-500" />
<span className="text-xs leading-3 text-gray-500">{t('generation.copy', { ns: 'share' })}</span>
</>
</Button>
{showFeedback && feedback.rating && feedback.rating === 'like' && (
<Tooltip
popupContent="Undo Great Rating"
>
<div
onClick={() => {
onFeedback({
rating: null,
})
}}
className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md border border-primary-200 bg-primary-100 !text-primary-600 hover:border-primary-300 hover:bg-primary-200"
>
<HandThumbUpIcon width={16} height={16} />
</div>
</Tooltip>
)}
{showFeedback && feedback.rating && feedback.rating === 'dislike' && (
<Tooltip
popupContent="Undo Undesirable Response"
>
<div
onClick={() => {
onFeedback({
rating: null,
})
}}
className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md border border-red-200 bg-red-100 !text-red-600 hover:border-red-300 hover:bg-red-200"
>
<HandThumbDownIcon width={16} height={16} />
</div>
</Tooltip>
)}
{showFeedback && !feedback.rating && (
<div className="flex space-x-1 rounded-lg border border-gray-200 p-[1px]">
<Tooltip
popupContent="Great Rating"
needsDelay={false}
>
<div
onClick={() => {
onFeedback({
rating: 'like',
})
}}
className="flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-gray-100"
>
<HandThumbUpIcon width={16} height={16} />
</div>
</Tooltip>
<Tooltip
popupContent="Undesirable Response"
needsDelay={false}
>
<div
onClick={() => {
onFeedback({
rating: 'dislike',
})
}}
className="flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-gray-100"
>
<HandThumbDownIcon width={16} height={16} />
</div>
</Tooltip>
</div>
)}
</div>
</div>
)
}
export default React.memo(Header)

View File

@ -6,6 +6,9 @@ import type { FileEntity } from '@/app/components/base/file-uploader/types'
import type { PromptConfig } from '@/models/debug'
import type { InstalledApp } from '@/models/explore'
import type { SiteInfo } from '@/models/share'
import type {
IOtherOptions,
} from '@/service/base'
import type { VisionFile, VisionSettings } from '@/types/app'
import { RiLoader2Line } from '@remixicon/react'
import { useBoolean } from 'ahooks'
@ -25,6 +28,9 @@ import Toast from '@/app/components/base/toast'
import NoData from '@/app/components/share/text-generation/no-data'
import { NodeRunningStatus, WorkflowRunningStatus } from '@/app/components/workflow/types'
import { TEXT_GENERATION_TIMEOUT_MS } from '@/config'
import {
sseGet,
} from '@/service/base'
import { sendCompletionMessage, sendWorkflowMessage, stopChatMessageResponding, stopWorkflowMessage, updateFeedback } from '@/service/share'
import { TransferMethod } from '@/types/app'
import { sleep } from '@/utils'
@ -283,10 +289,16 @@ const Result: FC<IResultProps> = ({
})()
if (isWorkflow) {
sendWorkflowMessage(
data,
{
onWorkflowStarted: ({ workflow_run_id, task_id }) => {
const otherOptions: IOtherOptions = {
isPublicAPI: !isInstalledApp,
onWorkflowStarted: ({ workflow_run_id, task_id, data }) => {
if (data.is_resumption) {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
draft.status = WorkflowRunningStatus.Running
}))
}
else {
tempMessageId = workflow_run_id
setCurrentTaskId(task_id || null)
setIsStopping(false)
@ -296,178 +308,239 @@ const Result: FC<IResultProps> = ({
expand: false,
resultText: '',
})
},
onIterationStart: ({ data }) => {
}
},
onIterationStart: ({ data }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
draft.tracing!.push({
...data,
status: NodeRunningStatus.Running,
expand: true,
})
}))
},
onIterationNext: () => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const iterations = draft.tracing.find(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
iterations?.details!.push([])
}))
},
onIterationFinish: ({ data }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const iterationsIndex = draft.tracing.findIndex(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
draft.tracing[iterationsIndex] = {
...data,
expand: !!data.error,
}
}))
},
onLoopStart: ({ data }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
draft.tracing!.push({
...data,
status: NodeRunningStatus.Running,
expand: true,
})
}))
},
onLoopNext: () => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const loops = draft.tracing.find(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
loops?.details!.push([])
}))
},
onLoopFinish: ({ data }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const loopsIndex = draft.tracing.findIndex(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
draft.tracing[loopsIndex] = {
...data,
expand: !!data.error,
}
}))
},
onNodeStarted: ({ data }) => {
if (data.is_resumption) {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
draft.tracing!.push({
...data,
status: NodeRunningStatus.Running,
expand: true,
})
}))
},
onIterationNext: () => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const iterations = draft.tracing.find(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
iterations?.details!.push([])
}))
},
onIterationFinish: ({ data }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const iterationsIndex = draft.tracing.findIndex(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
draft.tracing[iterationsIndex] = {
...data,
expand: !!data.error,
}
}))
},
onLoopStart: ({ data }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
draft.tracing!.push({
...data,
status: NodeRunningStatus.Running,
expand: true,
})
}))
},
onLoopNext: () => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const loops = draft.tracing.find(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
loops?.details!.push([])
}))
},
onLoopFinish: ({ data }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
const loopsIndex = draft.tracing.findIndex(item => item.node_id === data.node_id
&& (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))!
draft.tracing[loopsIndex] = {
...data,
expand: !!data.error,
}
}))
},
onNodeStarted: ({ data }) => {
if (data.iteration_id)
return
if (data.loop_id)
return
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = true
draft.tracing!.push({
...data,
status: NodeRunningStatus.Running,
expand: true,
})
}))
},
onNodeFinished: ({ data }) => {
if (data.iteration_id)
return
if (data.loop_id)
return
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
const currentIndex = draft.tracing!.findIndex(trace => trace.node_id === data.node_id
&& (trace.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || trace.parallel_id === data.execution_metadata?.parallel_id))
if (currentIndex > -1 && draft.tracing) {
draft.tracing[currentIndex] = {
...(draft.tracing[currentIndex].extras
? { extras: draft.tracing[currentIndex].extras }
: {}),
const currentIndex = draft.tracing!.findIndex(item => item.node_id === data.node_id)
if (currentIndex > -1) {
draft.expand = true
draft.tracing![currentIndex] = {
...data,
expand: !!data.error,
status: NodeRunningStatus.Running,
expand: true,
}
}
}))
},
onWorkflowFinished: ({ data }) => {
if (isTimeout) {
notify({ type: 'warning', message: t('warningMessage.timeoutExceeded', { ns: 'appDebug' }) })
}
else {
if (data.iteration_id)
return
}
const workflowStatus = data.status as WorkflowRunningStatus | undefined
const markNodesStopped = (traces?: WorkflowProcess['tracing']) => {
if (!traces)
return
const markTrace = (trace: WorkflowProcess['tracing'][number]) => {
if ([NodeRunningStatus.Running, NodeRunningStatus.Waiting].includes(trace.status as NodeRunningStatus))
trace.status = NodeRunningStatus.Stopped
trace.details?.forEach(detailGroup => detailGroup.forEach(markTrace))
trace.retryDetail?.forEach(markTrace)
trace.parallelDetail?.children?.forEach(markTrace)
}
traces.forEach(markTrace)
}
if (workflowStatus === WorkflowRunningStatus.Stopped) {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.status = WorkflowRunningStatus.Stopped
markNodesStopped(draft.tracing)
}))
setRespondingFalse()
resetRunState()
onCompleted(getCompletionRes(), taskId, false)
isEnd = true
if (data.loop_id)
return
}
if (data.error) {
notify({ type: 'error', message: data.error })
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.status = WorkflowRunningStatus.Failed
markNodesStopped(draft.tracing)
}))
setRespondingFalse()
resetRunState()
onCompleted(getCompletionRes(), taskId, false)
isEnd = true
return
}
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.status = WorkflowRunningStatus.Succeeded
draft.files = getFilesInLogs(data.outputs || []) as any[]
draft.expand = true
draft.tracing!.push({
...data,
status: NodeRunningStatus.Running,
expand: true,
})
}))
if (!data.outputs) {
setCompletionRes('')
}
else {
setCompletionRes(data.outputs)
const isStringOutput = Object.keys(data.outputs).length === 1 && typeof data.outputs[Object.keys(data.outputs)[0]] === 'string'
if (isStringOutput) {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.resultText = data.outputs[Object.keys(data.outputs)[0]]
}))
}
},
onNodeFinished: ({ data }) => {
if (data.iteration_id)
return
if (data.loop_id)
return
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
const currentIndex = draft.tracing!.findIndex(trace => trace.node_id === data.node_id
&& (trace.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || trace.parallel_id === data.execution_metadata?.parallel_id))
if (currentIndex > -1 && draft.tracing) {
draft.tracing[currentIndex] = {
...(draft.tracing[currentIndex].extras
? { extras: draft.tracing[currentIndex].extras }
: {}),
...data,
expand: !!data.error,
}
}
}))
},
onWorkflowFinished: ({ data }) => {
if (isTimeout) {
notify({ type: 'warning', message: t('warningMessage.timeoutExceeded', { ns: 'appDebug' }) })
return
}
const workflowStatus = data.status as WorkflowRunningStatus | undefined
const markNodesStopped = (traces?: WorkflowProcess['tracing']) => {
if (!traces)
return
const markTrace = (trace: WorkflowProcess['tracing'][number]) => {
if ([NodeRunningStatus.Running, NodeRunningStatus.Waiting].includes(trace.status as NodeRunningStatus))
trace.status = NodeRunningStatus.Stopped
trace.details?.forEach(detailGroup => detailGroup.forEach(markTrace))
trace.retryDetail?.forEach(markTrace)
trace.parallelDetail?.children?.forEach(markTrace)
}
traces.forEach(markTrace)
}
if (workflowStatus === WorkflowRunningStatus.Stopped) {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.status = WorkflowRunningStatus.Stopped
markNodesStopped(draft.tracing)
}))
setRespondingFalse()
resetRunState()
setMessageId(tempMessageId)
onCompleted(getCompletionRes(), taskId, true)
onCompleted(getCompletionRes(), taskId, false)
isEnd = true
},
onTextChunk: (params) => {
const { data: { text } } = params
return
}
if (data.error) {
notify({ type: 'error', message: data.error })
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.resultText += text
draft.status = WorkflowRunningStatus.Failed
markNodesStopped(draft.tracing)
}))
},
onTextReplace: (params) => {
const { data: { text } } = params
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.resultText = text
}))
},
setRespondingFalse()
resetRunState()
onCompleted(getCompletionRes(), taskId, false)
isEnd = true
return
}
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.status = WorkflowRunningStatus.Succeeded
draft.files = getFilesInLogs(data.outputs || []) as any[]
}))
if (!data.outputs) {
setCompletionRes('')
}
else {
setCompletionRes(data.outputs)
const isStringOutput = Object.keys(data.outputs).length === 1 && typeof data.outputs[Object.keys(data.outputs)[0]] === 'string'
if (isStringOutput) {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.resultText = data.outputs[Object.keys(data.outputs)[0]]
}))
}
}
setRespondingFalse()
resetRunState()
setMessageId(tempMessageId)
onCompleted(getCompletionRes(), taskId, true)
isEnd = true
},
onTextChunk: (params) => {
const { data: { text } } = params
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.resultText += text
}))
},
onTextReplace: (params) => {
const { data: { text } } = params
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.resultText = text
}))
},
onHumanInputRequired: ({ data: humanInputRequiredData }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
if (!draft.humanInputFormDataList) {
draft.humanInputFormDataList = [humanInputRequiredData]
}
else {
const currentFormIndex = draft.humanInputFormDataList.findIndex(item => item.node_id === data.node_id)
if (currentFormIndex > -1) {
draft.humanInputFormDataList[currentFormIndex] = humanInputRequiredData
}
else {
draft.humanInputFormDataList.push(humanInputRequiredData)
}
}
}))
},
onHumanInputFormFilled: ({ data: humanInputFilledFormData }) => {
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
if (draft.humanInputFormDataList?.length) {
const currentFormIndex = draft.humanInputFormDataList.findIndex(item => item.node_id === humanInputFilledFormData.node_id)
draft.humanInputFormDataList.splice(currentFormIndex, 1)
}
if (!draft.humanInputFilledFormDataList) {
draft.humanInputFilledFormDataList = [humanInputFilledFormData]
}
else {
draft.humanInputFilledFormDataList.push(humanInputFilledFormData)
}
}))
},
onWorkflowPaused: ({ data: workflowPausedData }) => {
const url = `/workflow/${workflowPausedData.workflow_run_id}/events`
sseGet(
url,
{},
otherOptions,
)
setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => {
draft.expand = false
draft.status = WorkflowRunningStatus.Paused
}))
},
}
sendWorkflowMessage(
data,
otherOptions,
isInstalledApp,
installedAppInfo?.id,
).catch((error) => {

View File

@ -3,23 +3,12 @@ import type {
IOnData,
IOnError,
IOnFile,
IOnIterationFinished,
IOnIterationNext,
IOnIterationStarted,
IOnLoopFinished,
IOnLoopNext,
IOnLoopStarted,
IOnMessageEnd,
IOnMessageReplace,
IOnNodeFinished,
IOnNodeStarted,
IOnTextChunk,
IOnTextReplace,
IOnThought,
IOnTTSChunk,
IOnTTSEnd,
IOnWorkflowFinished,
IOnWorkflowStarted,
IOtherOptions,
} from './base'
import type { FeedbackType } from '@/app/components/base/chat/chat/type'
import type { ChatConfig } from '@/app/components/base/chat/types'
@ -103,33 +92,7 @@ export const sendCompletionMessage = async (body: Record<string, any>, { onData,
export const sendWorkflowMessage = async (
body: Record<string, any>,
{
onWorkflowStarted,
onNodeStarted,
onNodeFinished,
onWorkflowFinished,
onIterationStart,
onIterationNext,
onIterationFinish,
onLoopStart,
onLoopNext,
onLoopFinish,
onTextChunk,
onTextReplace,
}: {
onWorkflowStarted: IOnWorkflowStarted
onNodeStarted: IOnNodeStarted
onNodeFinished: IOnNodeFinished
onWorkflowFinished: IOnWorkflowFinished
onIterationStart: IOnIterationStarted
onIterationNext: IOnIterationNext
onIterationFinish: IOnIterationFinished
onLoopStart: IOnLoopStarted
onLoopNext: IOnLoopNext
onLoopFinish: IOnLoopFinished
onTextChunk: IOnTextChunk
onTextReplace: IOnTextReplace
},
otherOptions: IOtherOptions,
isInstalledApp: boolean,
installedAppId = '',
) => {
@ -139,19 +102,8 @@ export const sendWorkflowMessage = async (
response_mode: 'streaming',
},
}, {
onNodeStarted,
onWorkflowStarted,
onWorkflowFinished,
...otherOptions,
isPublicAPI: !isInstalledApp,
onNodeFinished,
onIterationStart,
onIterationNext,
onIterationFinish,
onLoopStart,
onLoopNext,
onLoopFinish,
onTextChunk,
onTextReplace,
})
}