From 7cd4a7c1dec9da6fe7b1cb182d1deb9a19ba944a Mon Sep 17 00:00:00 2001 From: twwu Date: Tue, 27 Jan 2026 15:57:13 +0800 Subject: [PATCH] feat: implement human input form timeout handling and enhance expiration time display --- .../app/text-generate/item/index.tsx | 2 +- .../human-input-content/expiration-time.tsx | 27 +++++++++++++++--- .../human-input-content/human-input-form.tsx | 4 +-- .../chat/answer/human-input-content/type.ts | 8 ++---- .../human-input-content/unsubmitted.tsx | 10 +++---- .../chat/answer/human-input-form-list.tsx | 7 +++-- web/app/components/base/chat/chat/hooks.ts | 20 +++++++++++++ .../workflow-app/hooks/use-workflow-run.ts | 15 +++++++++- .../hooks/use-workflow-run-event/index.ts | 1 + ...-workflow-node-human-input-form-timeout.ts | 28 +++++++++++++++++++ .../use-workflow-run-event.ts | 3 ++ .../workflow/panel/debug-and-preview/hooks.ts | 20 +++++++++++++ web/eslint-suppressions.json | 19 ++----------- web/i18n/en-US/share.json | 2 +- web/i18n/zh-Hans/share.json | 2 +- web/service/base.ts | 11 ++++++++ web/service/share.ts | 2 +- web/service/use-share.ts | 2 +- web/service/workflow.ts | 2 +- web/types/workflow.ts | 14 ++++++++++ 20 files changed, 156 insertions(+), 43 deletions(-) create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-human-input-form-timeout.ts diff --git a/web/app/components/app/text-generate/item/index.tsx b/web/app/components/app/text-generate/item/index.tsx index 164f439507..22358805a7 100644 --- a/web/app/components/app/text-generate/item/index.tsx +++ b/web/app/components/app/text-generate/item/index.tsx @@ -215,7 +215,7 @@ const GenerationItem: FC = ({ else switchTab('DETAIL') }, [workflowProcessData?.files?.length, workflowProcessData?.resultText, workflowProcessData?.humanInputFormDataList, workflowProcessData?.humanInputFilledFormDataList]) - const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: any) => { + const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: { inputs: Record, action: string }) => { if (appSourceType === AppSourceType.installedApp) await submitHumanInputFormService(formToken, formData) else diff --git a/web/app/components/base/chat/chat/answer/human-input-content/expiration-time.tsx b/web/app/components/base/chat/chat/answer/human-input-content/expiration-time.tsx index 0d882df40d..3ae0b34fd7 100644 --- a/web/app/components/base/chat/chat/answer/human-input-content/expiration-time.tsx +++ b/web/app/components/base/chat/chat/answer/human-input-content/expiration-time.tsx @@ -1,6 +1,8 @@ 'use client' +import { RiAlertFill, RiTimeLine } from '@remixicon/react' import { useTranslation } from 'react-i18next' import { useLocale } from '@/context/i18n' +import { cn } from '@/utils/classnames' import { getRelativeTime, isRelativeTimeSameOrAfter } from './utils' type ExpirationTimeProps = { @@ -16,10 +18,27 @@ const ExpirationTime = ({ const isSameOrAfter = isRelativeTimeSameOrAfter(expirationTime) return ( -
- {isSameOrAfter - ? t('humanInput.expirationTimeNowOrFuture', { relativeTime, ns: 'share' }) - : t('humanInput.expirationTimePast', { relativeTime, ns: 'share' })} +
+ { + isSameOrAfter + ? ( + <> + + {t('humanInput.expirationTimeNowOrFuture', { relativeTime, ns: 'share' })} + + ) + : ( + <> + + {t('humanInput.expiredTip', { ns: 'share' })} + + ) + }
) } diff --git a/web/app/components/base/chat/chat/answer/human-input-content/human-input-form.tsx b/web/app/components/base/chat/chat/answer/human-input-content/human-input-form.tsx index 7943218048..0b5d54ab7e 100644 --- a/web/app/components/base/chat/chat/answer/human-input-content/human-input-form.tsx +++ b/web/app/components/base/chat/chat/answer/human-input-content/human-input-form.tsx @@ -18,14 +18,14 @@ const HumanInputForm = ({ const [inputs, setInputs] = useState(defaultInputs) const [isSubmitting, setIsSubmitting] = useState(false) - const handleInputsChange = useCallback((name: string, value: any) => { + const handleInputsChange = useCallback((name: string, value: string) => { setInputs(prev => ({ ...prev, [name]: value, })) }, []) - const submit = async (formToken: string, actionID: string, inputs: Record) => { + const submit = async (formToken: string, actionID: string, inputs: Record) => { setIsSubmitting(true) await onSubmit?.(formToken, { inputs, action: actionID }) setIsSubmitting(false) diff --git a/web/app/components/base/chat/chat/answer/human-input-content/type.ts b/web/app/components/base/chat/chat/answer/human-input-content/type.ts index ce3589975c..7fb4082b4a 100644 --- a/web/app/components/base/chat/chat/answer/human-input-content/type.ts +++ b/web/app/components/base/chat/chat/answer/human-input-content/type.ts @@ -11,9 +11,7 @@ export type UnsubmittedHumanInputContentProps = { showEmailTip?: boolean isEmailDebugMode?: boolean showDebugModeTip?: boolean - showTimeout?: boolean - expirationTime?: number - onSubmit?: (formToken: string, data: any) => Promise + onSubmit?: (formToken: string, data: { inputs: Record, action: string }) => Promise } export type SubmittedHumanInputContentProps = { @@ -22,12 +20,12 @@ export type SubmittedHumanInputContentProps = { export type HumanInputFormProps = { formData: HumanInputFormData - onSubmit?: (formToken: string, data: any) => Promise + onSubmit?: (formToken: string, data: { inputs: Record, action: string }) => Promise } export type ContentItemProps = { content: string formInputFields: FormInputItem[] inputs: Record - onInputChange: (name: string, value: any) => void + onInputChange: (name: string, value: string) => void } diff --git a/web/app/components/base/chat/chat/answer/human-input-content/unsubmitted.tsx b/web/app/components/base/chat/chat/answer/human-input-content/unsubmitted.tsx index e5a4cae9cb..e6d05d62c6 100644 --- a/web/app/components/base/chat/chat/answer/human-input-content/unsubmitted.tsx +++ b/web/app/components/base/chat/chat/answer/human-input-content/unsubmitted.tsx @@ -8,10 +8,10 @@ export const UnsubmittedHumanInputContent = ({ showEmailTip = false, isEmailDebugMode = false, showDebugModeTip = false, - showTimeout = false, - expirationTime, onSubmit, }: UnsubmittedHumanInputContentProps) => { + const { expiration_time } = formData + return ( <> {/* Form */} @@ -27,9 +27,9 @@ export const UnsubmittedHumanInputContent = ({ showDebugModeTip={showDebugModeTip} /> )} - {/* Timeout */} - {showTimeout && typeof expirationTime === 'number' && ( - + {/* Expiration Time */} + {typeof expiration_time === 'number' && ( + )} ) diff --git a/web/app/components/base/chat/chat/answer/human-input-form-list.tsx b/web/app/components/base/chat/chat/answer/human-input-form-list.tsx index 1f8967aaf2..1403bcb600 100644 --- a/web/app/components/base/chat/chat/answer/human-input-form-list.tsx +++ b/web/app/components/base/chat/chat/answer/human-input-form-list.tsx @@ -1,4 +1,5 @@ -import type { DeliveryMethod } from '@/app/components/workflow/nodes/human-input/types' +import type { DeliveryMethod, HumanInputNodeType } from '@/app/components/workflow/nodes/human-input/types' +import type { Node } from '@/app/components/workflow/types' import type { HumanInputFormData } from '@/types/workflow' import { useMemo } from 'react' import { DeliveryMethodType } from '@/app/components/workflow/nodes/human-input/types' @@ -7,8 +8,8 @@ import { UnsubmittedHumanInputContent } from './human-input-content/unsubmitted' type HumanInputFormListProps = { humanInputFormDataList: HumanInputFormData[] - onHumanInputFormSubmit?: (formToken: string, formData: any) => Promise - getHumanInputNodeData?: (nodeID: string) => any + onHumanInputFormSubmit?: (formToken: string, formData: { inputs: Record, action: string }) => Promise + getHumanInputNodeData?: (nodeID: string) => Node | undefined } const HumanInputFormList = ({ diff --git a/web/app/components/base/chat/chat/hooks.ts b/web/app/components/base/chat/chat/hooks.ts index 9e220d7a57..a154e58bcb 100644 --- a/web/app/components/base/chat/chat/hooks.ts +++ b/web/app/components/base/chat/chat/hooks.ts @@ -527,6 +527,14 @@ export const useChat = ( } }) }, + onHumanInputFormTimeout: ({ data: humanInputFormTimeoutData }) => { + updateChatTreeNode(messageId, (responseItem) => { + if (responseItem.humanInputFormDataList?.length) { + const currentFormIndex = responseItem.humanInputFormDataList.findIndex(item => item.node_id === humanInputFormTimeoutData.node_id) + responseItem.humanInputFormDataList[currentFormIndex].expiration_time = humanInputFormTimeoutData.expiration_time + } + }) + }, onWorkflowPaused: ({ data: workflowPausedData }) => { const resumeUrl = `/workflow/${workflowPausedData.workflow_run_id}/events` sseGet( @@ -1089,6 +1097,18 @@ export const useChat = ( parentId: data.parent_message_id, }) }, + onHumanInputFormTimeout: ({ data: humanInputFormTimeoutData }) => { + if (responseItem.humanInputFormDataList?.length) { + const currentFormIndex = responseItem.humanInputFormDataList!.findIndex(item => item.node_id === humanInputFormTimeoutData.node_id) + responseItem.humanInputFormDataList[currentFormIndex].expiration_time = humanInputFormTimeoutData.expiration_time + } + updateCurrentQAOnTree({ + placeholderQuestionId, + questionItem, + responseItem, + parentId: data.parent_message_id, + }) + }, onWorkflowPaused: ({ data: workflowPausedData }) => { const url = `/workflow/${workflowPausedData.workflow_run_id}/events` sseGet( diff --git a/web/app/components/workflow-app/hooks/use-workflow-run.ts b/web/app/components/workflow-app/hooks/use-workflow-run.ts index 9b5d342722..ef6d7731a4 100644 --- a/web/app/components/workflow-app/hooks/use-workflow-run.ts +++ b/web/app/components/workflow-app/hooks/use-workflow-run.ts @@ -81,6 +81,7 @@ export const useWorkflowRun = () => { handleWorkflowNodeFinished, handleWorkflowNodeHumanInputRequired, handleWorkflowNodeHumanInputFormFilled, + handleWorkflowNodeHumanInputFormTimeout, handleWorkflowNodeIterationStarted, handleWorkflowNodeIterationNext, handleWorkflowNodeIterationFinished, @@ -182,6 +183,7 @@ export const useWorkflowRun = () => { onWorkflowPaused, onHumanInputRequired, onHumanInputFormFilled, + onHumanInputFormTimeout, onCompleted, ...restCallback } = callback || {} @@ -513,6 +515,11 @@ export const useWorkflowRun = () => { if (onHumanInputFormFilled) onHumanInputFormFilled(params) }, + onHumanInputFormTimeout: (params) => { + handleWorkflowNodeHumanInputFormTimeout(params) + if (onHumanInputFormTimeout) + onHumanInputFormTimeout(params) + }, onError: wrappedOnError, onCompleted: wrappedOnCompleted, } @@ -627,6 +634,7 @@ export const useWorkflowRun = () => { baseSseOptions.onAgentLog, baseSseOptions.onHumanInputRequired, baseSseOptions.onHumanInputFormFilled, + baseSseOptions.onHumanInputFormTimeout, baseSseOptions.onWorkflowPaused, baseSseOptions.onDataSourceNodeProcessing, baseSseOptions.onDataSourceNodeCompleted, @@ -814,6 +822,11 @@ export const useWorkflowRun = () => { if (onHumanInputFormFilled) onHumanInputFormFilled(params) }, + onHumanInputFormTimeout: (params) => { + handleWorkflowNodeHumanInputFormTimeout(params) + if (onHumanInputFormTimeout) + onHumanInputFormTimeout(params) + }, ...restCallback, } @@ -824,7 +837,7 @@ export const useWorkflowRun = () => { }, finalCallbacks, ) - }, [store, doSyncWorkflowDraft, workflowStore, pathname, handleWorkflowFailed, flowId, handleWorkflowStarted, handleWorkflowFinished, fetchInspectVars, invalidAllLastRun, handleWorkflowNodeStarted, handleWorkflowNodeFinished, handleWorkflowNodeIterationStarted, handleWorkflowNodeIterationNext, handleWorkflowNodeIterationFinished, handleWorkflowNodeLoopStarted, handleWorkflowNodeLoopNext, handleWorkflowNodeLoopFinished, handleWorkflowNodeRetry, handleWorkflowAgentLog, handleWorkflowTextChunk, handleWorkflowTextReplace, handleWorkflowPaused, handleWorkflowNodeHumanInputRequired, handleWorkflowNodeHumanInputFormFilled]) + }, [store, doSyncWorkflowDraft, workflowStore, pathname, handleWorkflowFailed, flowId, handleWorkflowStarted, handleWorkflowFinished, fetchInspectVars, invalidAllLastRun, handleWorkflowNodeStarted, handleWorkflowNodeFinished, handleWorkflowNodeIterationStarted, handleWorkflowNodeIterationNext, handleWorkflowNodeIterationFinished, handleWorkflowNodeLoopStarted, handleWorkflowNodeLoopNext, handleWorkflowNodeLoopFinished, handleWorkflowNodeRetry, handleWorkflowAgentLog, handleWorkflowTextChunk, handleWorkflowTextReplace, handleWorkflowPaused, handleWorkflowNodeHumanInputRequired, handleWorkflowNodeHumanInputFormFilled, handleWorkflowNodeHumanInputFormTimeout]) const handleStopRun = useCallback((taskId: string) => { const setStoppedState = () => { diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/index.ts b/web/app/components/workflow/hooks/use-workflow-run-event/index.ts index 914f4ce0ab..4348687333 100644 --- a/web/app/components/workflow/hooks/use-workflow-run-event/index.ts +++ b/web/app/components/workflow/hooks/use-workflow-run-event/index.ts @@ -3,6 +3,7 @@ export * from './use-workflow-failed' export * from './use-workflow-finished' export * from './use-workflow-node-finished' export * from './use-workflow-node-human-input-form-filled' +export * from './use-workflow-node-human-input-form-timeout' export * from './use-workflow-node-human-input-required' export * from './use-workflow-node-iteration-finished' export * from './use-workflow-node-iteration-next' diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-human-input-form-timeout.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-human-input-form-timeout.ts new file mode 100644 index 0000000000..d3016eeb1d --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-human-input-form-timeout.ts @@ -0,0 +1,28 @@ +import type { HumanInputFormTimeoutResponse } from '@/types/workflow' +import { produce } from 'immer' +import { useCallback } from 'react' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowNodeHumanInputFormTimeout = () => { + const workflowStore = useWorkflowStore() + + const handleWorkflowNodeHumanInputFormTimeout = useCallback((params: HumanInputFormTimeoutResponse) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + + const newWorkflowRunningData = produce(workflowRunningData!, (draft) => { + if (draft.humanInputFormDataList?.length) { + const currentFormIndex = draft.humanInputFormDataList.findIndex(item => item.node_id === data.node_id) + draft.humanInputFormDataList[currentFormIndex].expiration_time = data.expiration_time + } + }) + setWorkflowRunningData(newWorkflowRunningData) + }, [workflowStore]) + + return { + handleWorkflowNodeHumanInputFormTimeout, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts index 7aa69c8539..bf8fd319a2 100644 --- a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts @@ -4,6 +4,7 @@ import { useWorkflowFinished, useWorkflowNodeFinished, useWorkflowNodeHumanInputFormFilled, + useWorkflowNodeHumanInputFormTimeout, useWorkflowNodeHumanInputRequired, useWorkflowNodeIterationFinished, useWorkflowNodeIterationNext, @@ -38,6 +39,7 @@ export const useWorkflowRunEvent = () => { const { handleWorkflowPaused } = useWorkflowPaused() const { handleWorkflowNodeHumanInputRequired } = useWorkflowNodeHumanInputRequired() const { handleWorkflowNodeHumanInputFormFilled } = useWorkflowNodeHumanInputFormFilled() + const { handleWorkflowNodeHumanInputFormTimeout } = useWorkflowNodeHumanInputFormTimeout() return { handleWorkflowStarted, @@ -58,5 +60,6 @@ export const useWorkflowRunEvent = () => { handleWorkflowPaused, handleWorkflowNodeHumanInputFormFilled, handleWorkflowNodeHumanInputRequired, + handleWorkflowNodeHumanInputFormTimeout, } } diff --git a/web/app/components/workflow/panel/debug-and-preview/hooks.ts b/web/app/components/workflow/panel/debug-and-preview/hooks.ts index 4242f53036..b31673ee26 100644 --- a/web/app/components/workflow/panel/debug-and-preview/hooks.ts +++ b/web/app/components/workflow/panel/debug-and-preview/hooks.ts @@ -613,6 +613,18 @@ export const useChat = ( parentId: params.parent_message_id, }) }, + onHumanInputFormTimeout: ({ data }) => { + if (responseItem.humanInputFormDataList?.length) { + const currentFormIndex = responseItem.humanInputFormDataList.findIndex(item => item.node_id === data.node_id) + responseItem.humanInputFormDataList[currentFormIndex].expiration_time = data.expiration_time + } + updateCurrentQAOnTree({ + placeholderQuestionId, + questionItem, + responseItem, + parentId: params.parent_message_id, + }) + }, onWorkflowPaused: ({ data: _data }) => { responseItem.workflowProcess!.status = WorkflowRunningStatus.Paused updateCurrentQAOnTree({ @@ -864,6 +876,14 @@ export const useChat = ( } }) }, + onHumanInputFormTimeout: ({ data: humanInputFormTimeoutData }) => { + updateChatTreeNode(messageId, (responseItem) => { + if (responseItem.humanInputFormDataList?.length) { + const currentFormIndex = responseItem.humanInputFormDataList.findIndex(item => item.node_id === humanInputFormTimeoutData.node_id) + responseItem.humanInputFormDataList[currentFormIndex].expiration_time = humanInputFormTimeoutData.expiration_time + } + }) + }, onWorkflowPaused: ({ data: workflowPausedData }) => { const resumeUrl = `/workflow/${workflowPausedData.workflow_run_id}/events` sseGet( diff --git a/web/eslint-suppressions.json b/web/eslint-suppressions.json index 697bacaffa..5c3feb53df 100644 --- a/web/eslint-suppressions.json +++ b/web/eslint-suppressions.json @@ -594,7 +594,7 @@ "count": 3 }, "ts/no-explicit-any": { - "count": 5 + "count": 4 } }, "app/components/app/text-generate/item/result-tab.tsx": { @@ -794,26 +794,11 @@ "count": 1 } }, - "app/components/base/chat/chat/answer/human-input-content/human-input-form.tsx": { - "ts/no-explicit-any": { - "count": 2 - } - }, - "app/components/base/chat/chat/answer/human-input-content/type.ts": { - "ts/no-explicit-any": { - "count": 3 - } - }, "app/components/base/chat/chat/answer/human-input-content/utils.ts": { "ts/no-explicit-any": { "count": 1 } }, - "app/components/base/chat/chat/answer/human-input-form-list.tsx": { - "ts/no-explicit-any": { - "count": 2 - } - }, "app/components/base/chat/chat/answer/index.tsx": { "react-hooks-extra/no-direct-set-state-in-use-effect": { "count": 3 @@ -4439,7 +4424,7 @@ }, "service/workflow.ts": { "ts/no-explicit-any": { - "count": 4 + "count": 3 } }, "testing/testing.md": { diff --git a/web/i18n/en-US/share.json b/web/i18n/en-US/share.json index dc9d077dbf..ec3eb28c6b 100644 --- a/web/i18n/en-US/share.json +++ b/web/i18n/en-US/share.json @@ -60,8 +60,8 @@ "generation.title": "AI Completion", "humanInput.completed": "Seems like this request was dealt with elsewhere.", "humanInput.expirationTimeNowOrFuture": "This action will expire {{relativeTime}}.", - "humanInput.expirationTimePast": "This action has expired {{relativeTime}}.", "humanInput.expired": "Seems like this request has expired.", + "humanInput.expiredTip": "This action has expired.", "humanInput.formNotFound": "Form not found.", "humanInput.recorded": "Your input has been recorded.", "humanInput.sorry": "Sorry!", diff --git a/web/i18n/zh-Hans/share.json b/web/i18n/zh-Hans/share.json index b4ece54aa0..e4fa8baf9b 100644 --- a/web/i18n/zh-Hans/share.json +++ b/web/i18n/zh-Hans/share.json @@ -60,8 +60,8 @@ "generation.title": "AI 智能书写", "humanInput.completed": "此请求似乎在其他地方得到了处理。", "humanInput.expirationTimeNowOrFuture": "此操作将在 {{relativeTime}}过期。", - "humanInput.expirationTimePast": "此操作已在 {{relativeTime}}过期。", "humanInput.expired": "此请求似乎已过期。", + "humanInput.expiredTip": "此操作已过期。", "humanInput.formNotFound": "表单不存在。", "humanInput.recorded": "您的输入已被记录。", "humanInput.sorry": "抱歉!", diff --git a/web/service/base.ts b/web/service/base.ts index 7797b43681..fb8999d7a5 100644 --- a/web/service/base.ts +++ b/web/service/base.ts @@ -9,6 +9,7 @@ import type { import type { AgentLogResponse, HumanInputFormFilledResponse, + HumanInputFormTimeoutResponse, HumanInputRequiredResponse, IterationFinishedResponse, IterationNextResponse, @@ -75,6 +76,7 @@ export type IOnAgentLog = (agentLog: AgentLogResponse) => void export type IOHumanInputRequired = (humanInputRequired: HumanInputRequiredResponse) => void export type IOnHumanInputFormFilled = (humanInputFormFilled: HumanInputFormFilledResponse) => void +export type IOnHumanInputFormTimeout = (humanInputFormTimeout: HumanInputFormTimeoutResponse) => void export type IOWorkflowPaused = (workflowPaused: WorkflowPausedResponse) => void export type IOnDataSourceNodeProcessing = (dataSourceNodeProcessing: DataSourceNodeProcessingResponse) => void export type IOnDataSourceNodeCompleted = (dataSourceNodeCompleted: DataSourceNodeCompletedResponse) => void @@ -121,6 +123,7 @@ export type IOtherOptions = { onAgentLog?: IOnAgentLog onHumanInputRequired?: IOHumanInputRequired onHumanInputFormFilled?: IOnHumanInputFormFilled + onHumanInputFormTimeout?: IOnHumanInputFormTimeout onWorkflowPaused?: IOWorkflowPaused // Pipeline data source node run @@ -206,6 +209,7 @@ export const handleStream = ( onAgentLog?: IOnAgentLog, onHumanInputRequired?: IOHumanInputRequired, onHumanInputFormFilled?: IOnHumanInputFormFilled, + onHumanInputFormTimeout?: IOnHumanInputFormTimeout, onWorkflowPaused?: IOWorkflowPaused, onDataSourceNodeProcessing?: IOnDataSourceNodeProcessing, onDataSourceNodeCompleted?: IOnDataSourceNodeCompleted, @@ -345,6 +349,9 @@ export const handleStream = ( else if (bufferObj.event === 'human_input_form_filled') { onHumanInputFormFilled?.(bufferObj as HumanInputFormFilledResponse) } + else if (bufferObj.event === 'human_input_form_timeout') { + onHumanInputFormTimeout?.(bufferObj as HumanInputFormTimeoutResponse) + } else if (bufferObj.event === 'workflow_paused') { onWorkflowPaused?.(bufferObj as WorkflowPausedResponse) } @@ -472,6 +479,7 @@ export const ssePost = async ( onLoopFinish, onHumanInputRequired, onHumanInputFormFilled, + onHumanInputFormTimeout, onWorkflowPaused, onDataSourceNodeProcessing, onDataSourceNodeCompleted, @@ -576,6 +584,7 @@ export const ssePost = async ( onAgentLog, onHumanInputRequired, onHumanInputFormFilled, + onHumanInputFormTimeout, onWorkflowPaused, onDataSourceNodeProcessing, onDataSourceNodeCompleted, @@ -624,6 +633,7 @@ export const sseGet = async ( onLoopFinish, onHumanInputRequired, onHumanInputFormFilled, + onHumanInputFormTimeout, onWorkflowPaused, onDataSourceNodeProcessing, onDataSourceNodeCompleted, @@ -721,6 +731,7 @@ export const sseGet = async ( onAgentLog, onHumanInputRequired, onHumanInputFormFilled, + onHumanInputFormTimeout, onWorkflowPaused, onDataSourceNodeProcessing, onDataSourceNodeCompleted, diff --git a/web/service/share.ts b/web/service/share.ts index c2f2e7a178..4726ded7d1 100644 --- a/web/service/share.ts +++ b/web/service/share.ts @@ -279,7 +279,7 @@ export const getHumanInputForm = (token: string) => { } export const submitHumanInputForm = (token: string, data: { - inputs: Record + inputs: Record action: string }) => { return post(`/form/human_input/${token}`, { body: data }) diff --git a/web/service/use-share.ts b/web/service/use-share.ts index b37be27904..68e9229c1b 100644 --- a/web/service/use-share.ts +++ b/web/service/use-share.ts @@ -197,7 +197,7 @@ export const useGetHumanInputForm = (token: string, options: ShareQueryOptions = export type SubmitHumanInputFormParams = { token: string data: { - inputs: Record + inputs: Record action: string } } diff --git a/web/service/workflow.ts b/web/service/workflow.ts index bffa2da088..b7db744260 100644 --- a/web/service/workflow.ts +++ b/web/service/workflow.ts @@ -99,7 +99,7 @@ export const fetchNodeInspectVars = async (flowType: FlowType, flowId: string, n } export const submitHumanInputForm = (token: string, data: { - inputs: Record + inputs: Record action: string }) => { return post(`/form/human_input/${token}`, { body: data }) diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 04397ce9d3..156a704b48 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -323,6 +323,7 @@ export type HumanInputFormData = { form_token: string resolved_default_values: Record display_in_ui: boolean + expiration_time: number } export type HumanInputRequiredResponse = { @@ -347,6 +348,19 @@ export type HumanInputFormFilledResponse = { data: HumanInputFilledFormData } +export type HumanInputFormTimeoutData = { + node_id: string + node_title: string + expiration_time: number +} + +export type HumanInputFormTimeoutResponse = { + task_id: string + workflow_run_id: string + event: string + data: HumanInputFormTimeoutData +} + export type WorkflowRunHistory = { id: string version: string