diff --git a/web/app/(humanInputLayout)/form/[token]/form.tsx b/web/app/(humanInputLayout)/form/[token]/form.tsx index 75cd3b6cb9..f17c7879f4 100644 --- a/web/app/(humanInputLayout)/form/[token]/form.tsx +++ b/web/app/(humanInputLayout)/form/[token]/form.tsx @@ -27,7 +27,7 @@ export type FormData = { site: any form_content: string inputs: FormInputItem[] - resolved_placeholder_values: Record + resolved_default_values: Record user_actions: UserAction[] expiration_time: number } @@ -67,10 +67,10 @@ const FormContent = () => { return const initialInputs: Record = {} formData.inputs.forEach((item) => { - initialInputs[item.output_variable_name] = item.placeholder.type === 'variable' ? formData.resolved_placeholder_values[item.output_variable_name] || '' : item.placeholder.value + initialInputs[item.output_variable_name] = item.default.type === 'variable' ? formData.resolved_default_values[item.output_variable_name] || '' : item.default.value }) setInputs(initialInputs) - }, [formData?.inputs, formData?.resolved_placeholder_values]) + }, [formData?.inputs, formData?.resolved_default_values]) // use immer const handleInputsChange = (name: string, value: string) => { diff --git a/web/app/components/app/text-generate/item/index.tsx b/web/app/components/app/text-generate/item/index.tsx index f3789efdb6..164f439507 100644 --- a/web/app/components/app/text-generate/item/index.tsx +++ b/web/app/components/app/text-generate/item/index.tsx @@ -216,11 +216,11 @@ const GenerationItem: FC = ({ switchTab('DETAIL') }, [workflowProcessData?.files?.length, workflowProcessData?.resultText, workflowProcessData?.humanInputFormDataList, workflowProcessData?.humanInputFilledFormDataList]) const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: any) => { - if (isInstalledApp) + if (appSourceType === AppSourceType.installedApp) await submitHumanInputFormService(formToken, formData) else await submitHumanInputForm(formToken, formData) - }, [isInstalledApp]) + }, [appSourceType]) return ( <> diff --git a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx index 20717eab96..304425b9a7 100644 --- a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx +++ b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx @@ -166,9 +166,9 @@ const ChatWrapper = () => { handleSwitchSibling( lastPausedNode.id, { - onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, isInstalledApp, appId), + onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, appSourceType, appId), onConversationComplete: currentConversationId ? undefined : handleNewConversationCompleted, - isPublicAPI: !isInstalledApp, + isPublicAPI: appSourceType === AppSourceType.webApp, }, ) } @@ -189,10 +189,10 @@ const ChatWrapper = () => { { onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, appSourceType, appId), onConversationComplete: isHistoryConversation ? undefined : handleNewConversationCompleted, - isPublicAPI: !isInstalledApp, + isPublicAPI: appSourceType === AppSourceType.webApp, }, ) - }, [inputsForms, currentConversationId, currentConversationInputs, newConversationInputs, chatList, handleSend, isInstalledApp, appId, handleNewConversationCompleted]) + }, [inputsForms, currentConversationId, currentConversationInputs, newConversationInputs, chatList, handleSend, appSourceType, appId, isHistoryConversation, handleNewConversationCompleted]) const doRegenerate = useCallback((chatItem: ChatItem, editedQuestion?: { message: string, files?: FileEntity[] }) => { const question = editedQuestion ? chatItem : chatList.find(item => item.id === chatItem.parentMessageId)! @@ -202,11 +202,11 @@ const ChatWrapper = () => { const doSwitchSibling = useCallback((siblingMessageId: string) => { handleSwitchSibling(siblingMessageId, { - onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, isInstalledApp, appId), + onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, appSourceType, appId), onConversationComplete: currentConversationId ? undefined : handleNewConversationCompleted, - isPublicAPI: !isInstalledApp, + isPublicAPI: appSourceType === AppSourceType.webApp, }) - }, [handleSwitchSibling, isInstalledApp, appId, currentConversationId, handleNewConversationCompleted]) + }, [handleSwitchSibling, currentConversationId, handleNewConversationCompleted, appSourceType, appId]) const messageList = useMemo(() => { if (currentConversationId || chatList.length > 1) 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 66f033a4cd..7943218048 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 @@ -13,7 +13,7 @@ const HumanInputForm = ({ onSubmit, }: HumanInputFormProps) => { const formToken = formData.form_token - const defaultInputs = initializeInputs(formData.inputs, formData.resolved_placeholder_values || {}) + const defaultInputs = initializeInputs(formData.inputs, formData.resolved_default_values || {}) const contentList = splitByOutputVar(formData.form_content) const [inputs, setInputs] = useState(defaultInputs) const [isSubmitting, setIsSubmitting] = useState(false) diff --git a/web/app/components/base/chat/chat/answer/human-input-content/utils.ts b/web/app/components/base/chat/chat/answer/human-input-content/utils.ts index 6bee958388..dd35932797 100644 --- a/web/app/components/base/chat/chat/answer/human-input-content/utils.ts +++ b/web/app/components/base/chat/chat/answer/human-input-content/utils.ts @@ -34,7 +34,7 @@ export const initializeInputs = (formInputs: FormInputItem[], defaultValues: Rec const initialInputs: Record = {} formInputs.forEach((item) => { if (item.type === 'text-input' || item.type === 'paragraph') - initialInputs[item.output_variable_name] = item.placeholder.type === 'variable' ? defaultValues[item.output_variable_name] || '' : item.placeholder.value + initialInputs[item.output_variable_name] = item.default.type === 'variable' ? defaultValues[item.output_variable_name] || '' : item.default.value else initialInputs[item.output_variable_name] = undefined }) diff --git a/web/app/components/base/prompt-editor/plugins/hitl-input-block/component-ui.tsx b/web/app/components/base/prompt-editor/plugins/hitl-input-block/component-ui.tsx index 36dd2959e3..903138aaec 100644 --- a/web/app/components/base/prompt-editor/plugins/hitl-input-block/component-ui.tsx +++ b/web/app/components/base/prompt-editor/plugins/hitl-input-block/component-ui.tsx @@ -39,7 +39,7 @@ const HITLInputComponentUI: FC = ({ formInput = { type: InputVarType.paragraph, output_variable_name: varName, - placeholder: { + default: { type: 'constant', selector: [], value: '', @@ -95,9 +95,9 @@ const HITLInputComponentUI: FC = ({ hideEditModal() }, [hideEditModal, onChange, onRename, varName]) - const isPlaceholderVariable = useMemo(() => { - return formInput.placeholder.type === 'variable' - }, [formInput.placeholder.type]) + const isDefaultValueVariable = useMemo(() => { + return formInput.default?.type === 'variable' + }, [formInput.default?.type]) return (
= ({
- {/* Placeholder Info */} - {isPlaceholderVariable && ( + {/* Default Value Info */} + {isDefaultValueVariable && ( = ({ ragVariables={ragVariables} /> )} - {!isPlaceholderVariable && ( -
{formInput.placeholder.value}
+ {!isDefaultValueVariable && ( +
{formInput.default?.value}
)}
diff --git a/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx b/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx index 657a09b890..51531d98bc 100644 --- a/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx +++ b/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx @@ -1,4 +1,5 @@ -import type { FormInputItem, FormInputItemPlaceholder } from '@/app/components/workflow/nodes/human-input/types' +import type { FormInputItem, FormInputItemDefault } from '@/app/components/workflow/nodes/human-input/types' +import type { ValueSelector } from '@/app/components/workflow/types' import { produce } from 'immer' import * as React from 'react' import { useCallback, useEffect, useMemo, useState } from 'react' @@ -6,14 +7,12 @@ import { useTranslation } from 'react-i18next' import Input from '@/app/components/base/input' import { InputVarType } from '@/app/components/workflow/types' import { getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils' -// import PromptEditor from '@/app/components/base/prompt-editor' -// import TagLabel from './tag-label' import Button from '../../../button' import PrePopulate from './pre-populate' const i18nPrefix = 'nodes.humanInput.insertInputField' -type Props = { +type InputFieldProps = { nodeId: string isEdit: boolean payload?: FormInputItem @@ -23,9 +22,9 @@ type Props = { const defaultPayload: FormInputItem = { type: InputVarType.paragraph, output_variable_name: '', - placeholder: { type: 'constant', selector: [], value: '' }, + default: { type: 'constant', selector: [], value: '' }, } -const InputField: React.FC = ({ +const InputField: React.FC = ({ nodeId, isEdit, payload, @@ -47,17 +46,23 @@ const InputField: React.FC = ({ return onChange(tempPayload) }, [nameValid, onChange, tempPayload]) - const placeholderConfig = tempPayload.placeholder - const handlePlaceholderChange = useCallback((key: keyof FormInputItemPlaceholder) => { - return (value: any) => { + const defaultValueConfig = tempPayload.default + const handleDefaultValueChange = useCallback((key: keyof FormInputItemDefault) => { + return (value: ValueSelector | string) => { const nextValue = produce(tempPayload, (draft) => { - if (!draft.placeholder) - draft.placeholder = { type: 'constant', selector: [], value: '' } - draft.placeholder[key] = value - if (key === 'selector') - draft.placeholder.type = 'variable' - else if (key === 'value') - draft.placeholder.type = 'constant' + if (!draft.default) + draft.default = { type: 'constant', selector: [], value: '' } + if (key === 'selector') { + draft.default.type = 'variable' + draft.default.selector = value as ValueSelector + } + else if (key === 'value') { + draft.default.type = 'constant' + draft.default.value = value as string + } + else if (key === 'type') { + draft.default.type = value as 'constant' | 'variable' + } }) setTempPayload(nextValue) } @@ -104,15 +109,15 @@ const InputField: React.FC = ({ {t(`${i18nPrefix}.prePopulateField`, { ns: 'workflow' })}
{ - handlePlaceholderChange('type')(isVariable ? 'variable' : 'constant') + handleDefaultValueChange('type')(isVariable ? 'variable' : 'constant') }} nodeId={nodeId} - valueSelector={placeholderConfig?.selector} - onValueSelectorChange={handlePlaceholderChange('selector')} - value={placeholderConfig?.value} - onValueChange={handlePlaceholderChange('value')} + valueSelector={defaultValueConfig?.selector} + onValueSelectorChange={handleDefaultValueChange('selector')} + value={defaultValueConfig?.value} + onValueChange={handleDefaultValueChange('value')} />
diff --git a/web/app/components/share/text-generation/result/index.tsx b/web/app/components/share/text-generation/result/index.tsx index 05c132c4b0..fe9eb018c6 100644 --- a/web/app/components/share/text-generation/result/index.tsx +++ b/web/app/components/share/text-generation/result/index.tsx @@ -5,7 +5,6 @@ import type { WorkflowProcess } from '@/app/components/base/chat/types' import type { FileEntity } from '@/app/components/base/file-uploader/types' import type { PromptConfig } from '@/models/debug' import type { SiteInfo } from '@/models/share' -import type { AppSourceType } from '@/service/share' import type { IOtherOptions, } from '@/service/base' @@ -31,7 +30,14 @@ import { TEXT_GENERATION_TIMEOUT_MS } from '@/config' import { sseGet, } from '@/service/base' -import { sendCompletionMessage, sendWorkflowMessage, stopChatMessageResponding, stopWorkflowMessage, updateFeedback } from '@/service/share' +import { + AppSourceType, + sendCompletionMessage, + sendWorkflowMessage, + stopChatMessageResponding, + stopWorkflowMessage, + updateFeedback, +} from '@/service/share' import { TransferMethod } from '@/types/app' import { sleep } from '@/utils' import { formatBooleanInputs } from '@/utils/model-config' @@ -163,7 +169,7 @@ const Result: FC = ({ finally { setIsStopping(false) } - }, [appId, currentTaskId, appSourceType, appId, isStopping, isWorkflow, notify]) + }, [appId, currentTaskId, appSourceType, isStopping, isWorkflow, notify]) useEffect(() => { if (!onRunControlChange) @@ -288,7 +294,7 @@ const Result: FC = ({ if (isWorkflow) { const otherOptions: IOtherOptions = { - isPublicAPI: !isInstalledApp, + isPublicAPI: appSourceType === AppSourceType.webApp, onWorkflowStarted: ({ workflow_run_id, task_id }) => { const workflowProcessData = getWorkflowProcessData() if (workflowProcessData && workflowProcessData.tracing.length > 0) { @@ -368,10 +374,15 @@ const Result: FC = ({ })) }, onNodeStarted: ({ data }) => { + if (data.iteration_id) + return + + if (data.loop_id) + return const workflowProcessData = getWorkflowProcessData() - if (workflowProcessData && workflowProcessData.tracing.length > 0) { - setWorkflowProcessData(produce(workflowProcessData, (draft) => { - const currentIndex = draft.tracing!.findIndex(item => item.node_id === data.node_id) + setWorkflowProcessData(produce(workflowProcessData!, (draft) => { + if (draft.tracing.length > 0) { + const currentIndex = draft.tracing.findIndex(item => item.node_id === data.node_id) if (currentIndex > -1) { draft.expand = true draft.tracing![currentIndex] = { @@ -380,24 +391,24 @@ const Result: FC = ({ expand: true, } } - })) - } - else { - if (data.iteration_id) - return - - if (data.loop_id) - return - - setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => { + else { + draft.expand = true + draft.tracing.push({ + ...data, + status: NodeRunningStatus.Running, + expand: true, + }) + } + } + else { draft.expand = true draft.tracing!.push({ ...data, status: NodeRunningStatus.Running, expand: true, }) - })) - } + } + })) }, onNodeFinished: ({ data }) => { if (data.iteration_id) @@ -496,12 +507,13 @@ const Result: FC = ({ })) }, onHumanInputRequired: ({ data: humanInputRequiredData }) => { - setWorkflowProcessData(produce(getWorkflowProcessData()!, (draft) => { + const workflowProcessData = getWorkflowProcessData() + setWorkflowProcessData(produce(workflowProcessData!, (draft) => { if (!draft.humanInputFormDataList) { draft.humanInputFormDataList = [humanInputRequiredData] } else { - const currentFormIndex = draft.humanInputFormDataList.findIndex(item => item.node_id === data.node_id) + const currentFormIndex = draft.humanInputFormDataList.findIndex(item => item.node_id === humanInputRequiredData.node_id) if (currentFormIndex > -1) { draft.humanInputFormDataList[currentFormIndex] = humanInputRequiredData } @@ -509,6 +521,10 @@ const Result: FC = ({ draft.humanInputFormDataList.push(humanInputRequiredData) } } + const currentIndex = draft.tracing!.findIndex(item => item.node_id === humanInputRequiredData.node_id) + if (currentIndex > -1) { + draft.tracing![currentIndex].status = NodeRunningStatus.Paused + } })) }, onHumanInputFormFilled: ({ data: humanInputFilledFormData }) => { diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx index 84c4bd3db1..93e15fdb29 100644 --- a/web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx +++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx @@ -91,14 +91,14 @@ const EmailSenderModal = ({ const accounts = members?.accounts || [] const generatedInputs = useMemo(() => { - const placeholderValueSelectors = (formInputs || []).reduce((acc, input) => { - if (input.placeholder.type === 'variable') { - acc.push(input.placeholder.selector) + const defaultValueSelectors = (formInputs || []).reduce((acc, input) => { + if (input.default.type === 'variable') { + acc.push(input.default.selector) } return acc }, [] as ValueSelector[]) const valueSelectors = doGetInputVars((formContent || '') + (config?.body || '')) - const variables = unionBy([...valueSelectors, ...placeholderValueSelectors], item => item.join('.')).map((item) => { + const variables = unionBy([...valueSelectors, ...defaultValueSelectors], item => item.join('.')).map((item) => { const varInfo = getNodeInfoById(availableNodes, item[0])?.data return { diff --git a/web/app/components/workflow/nodes/human-input/components/form-content-preview.tsx b/web/app/components/workflow/nodes/human-input/components/form-content-preview.tsx index 16434b093c..73529d1df4 100644 --- a/web/app/components/workflow/nodes/human-input/components/form-content-preview.tsx +++ b/web/app/components/workflow/nodes/human-input/components/form-content-preview.tsx @@ -75,9 +75,9 @@ const FormContentPreview: FC = ({
) } - const placeholder = input.placeholder + const defaultInput = input.default return ( - + ) })(), }} diff --git a/web/app/components/workflow/nodes/human-input/components/single-run-form.tsx b/web/app/components/workflow/nodes/human-input/components/single-run-form.tsx index 3484eb6d8c..ec4b4628c9 100644 --- a/web/app/components/workflow/nodes/human-input/components/single-run-form.tsx +++ b/web/app/components/workflow/nodes/human-input/components/single-run-form.tsx @@ -25,7 +25,7 @@ const FormContent = ({ onSubmit, }: Props) => { const { t } = useTranslation() - const defaultInputs = initializeInputs(data.inputs, data.resolved_placeholder_values || {}) + const defaultInputs = initializeInputs(data.inputs, data.resolved_default_values || {}) const contentList = splitByOutputVar(data.form_content) const [inputs, setInputs] = useState(defaultInputs) const [isSubmitting, setIsSubmitting] = useState(false) diff --git a/web/app/components/workflow/nodes/human-input/components/variable-in-markdown.tsx b/web/app/components/workflow/nodes/human-input/components/variable-in-markdown.tsx index b5ec9ea2fa..e159adeb9d 100644 --- a/web/app/components/workflow/nodes/human-input/components/variable-in-markdown.tsx +++ b/web/app/components/workflow/nodes/human-input/components/variable-in-markdown.tsx @@ -1,5 +1,5 @@ import type * as React from 'react' -import type { FormInputItemPlaceholder } from '../types' +import type { FormInputItemDefault } from '../types' const variableRegex = /\{\{#(.+?)#\}\}/g const noteRegex = /\{\{#\$(.+?)#\}\}/g @@ -123,11 +123,11 @@ export const Variable: React.FC<{ path: string }> = ({ path }) => { ) } -export const Note: React.FC<{ placeholder: FormInputItemPlaceholder }> = ({ placeholder }) => { - const isVariable = placeholder.type === 'variable' +export const Note: React.FC<{ defaultInput: FormInputItemDefault }> = ({ defaultInput }) => { + const isVariable = defaultInput.type === 'variable' return (
- {isVariable ? : {placeholder.value}} + {isVariable ? : {defaultInput.value}}
) } diff --git a/web/app/components/workflow/nodes/human-input/hooks/use-single-run-form-params.ts b/web/app/components/workflow/nodes/human-input/hooks/use-single-run-form-params.ts index b3450d5e66..307e7b9b0c 100644 --- a/web/app/components/workflow/nodes/human-input/hooks/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/human-input/hooks/use-single-run-form-params.ts @@ -32,15 +32,15 @@ const useSingleRunFormParams = ({ const [formData, setFormData] = useState(null) const [requiredInputs, setRequiredInputs] = useState>({}) const generatedInputs = useMemo(() => { - const placeholderInputs = inputs.inputs.reduce((acc, input) => { - if (input.placeholder.type === 'variable') { - acc.push(...getInputVars([`{{#${input.placeholder.selector.join('.')}#}}`])) + const defaultInputs = inputs.inputs.reduce((acc, input) => { + if (input.default.type === 'variable') { + acc.push(...getInputVars([`{{#${input.default.selector.join('.')}#}}`])) } return acc }, [] as InputVar[]) if (!inputs.form_content) - return placeholderInputs - return [...placeholderInputs, ...getInputVars([inputs.form_content]).filter(item => !isOutput(item.value_selector || []))] + return defaultInputs + return [...defaultInputs, ...getInputVars([inputs.form_content]).filter(item => !isOutput(item.value_selector || []))] }, [getInputVars, inputs.form_content, inputs.inputs]) const forms = useMemo(() => { diff --git a/web/app/components/workflow/nodes/human-input/types.ts b/web/app/components/workflow/nodes/human-input/types.ts index 0d7cace7b1..128cfd8b98 100644 --- a/web/app/components/workflow/nodes/human-input/types.ts +++ b/web/app/components/workflow/nodes/human-input/types.ts @@ -59,7 +59,7 @@ export type UserAction = { button_style: UserActionButtonType } -export type FormInputItemPlaceholder = { +export type FormInputItemDefault = { selector: ValueSelector type: 'variable' | 'constant' value: string @@ -68,5 +68,5 @@ export type FormInputItemPlaceholder = { export type FormInputItem = { type: InputVarType output_variable_name: string - placeholder: FormInputItemPlaceholder + default: FormInputItemDefault } diff --git a/web/eslint-suppressions.json b/web/eslint-suppressions.json index 7ed0a0a28a..adcb313e2c 100644 --- a/web/eslint-suppressions.json +++ b/web/eslint-suppressions.json @@ -104,7 +104,7 @@ "count": 1 }, "ts/no-explicit-any": { - "count": 4 + "count": 2 } }, "app/(shareLayout)/components/splash.tsx": { @@ -1392,11 +1392,6 @@ "count": 1 } }, - "app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx": { - "ts/no-explicit-any": { - "count": 1 - } - }, "app/components/base/prompt-editor/plugins/on-blur-or-focus-block.tsx": { "ts/no-explicit-any": { "count": 1 diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 4962ee6810..04397ce9d3 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -321,7 +321,7 @@ export type HumanInputFormData = { inputs: FormInputItem[] actions: UserAction[] form_token: string - resolved_placeholder_values: Record + resolved_default_values: Record display_in_ui: boolean }