diff --git a/web/app/components/app/configuration/config-var/config-modal/index.tsx b/web/app/components/app/configuration/config-var/config-modal/index.tsx index 50d6e9c6f6..86786b4e35 100644 --- a/web/app/components/app/configuration/config-var/config-modal/index.tsx +++ b/web/app/components/app/configuration/config-var/config-modal/index.tsx @@ -60,7 +60,7 @@ const ConfigModal: FC = ({ Toast.notify({ type: 'error', message: t('appDebug.variableConig.errorMsg.labelNameRequired') }) return } - if (isStringInput) { + if (isStringInput || type === InputVarType.number) { onConfirm(tempPayload) } else { diff --git a/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx b/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx index 6ca0c7a78f..22aaaf6a13 100644 --- a/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx +++ b/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx @@ -39,7 +39,7 @@ const Form: FC = ({ draft[key].push(RETRIEVAL_OUTPUT_STRUCT) }) onChange(newValues) - }, [values, onChange]) + }, [values, onChange, inputs]) return (
{label && ( diff --git a/web/app/components/workflow/nodes/_base/components/variable/utils.ts b/web/app/components/workflow/nodes/_base/components/variable/utils.ts index ddef0d4470..ed7af5cfc0 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/utils.ts +++ b/web/app/components/workflow/nodes/_base/components/variable/utils.ts @@ -55,6 +55,10 @@ const formatItem = (item: any, isChatMode: boolean, filterVar: (payload: Var, se return { variable: v.variable, type: inputVarTypeToVarType(v.type), + isParagraph: v.type === InputVarType.paragraph, + isSelect: v.type === InputVarType.select, + options: v.options, + required: v.required, } }) if (isChatMode) { diff --git a/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx b/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx index 7149e570e3..dbfee3130a 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx +++ b/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx @@ -93,7 +93,7 @@ const VarReferencePicker: FC = ({ const isLast = i === value.length - 2 curr = curr.find((v: any) => v.variable === key) if (isLast) { - type = curr.type + type = curr?.type } else { if (curr.type === VarType.object) diff --git a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts index 0d48f834d6..e0b6cab756 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts @@ -1,8 +1,14 @@ import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { useNodeDataUpdate } from '@/app/components/workflow/hooks' -import type { CheckValidRes, CommonNodeType, InputVar, Variable } from '@/app/components/workflow/types' -import { BlockEnum, InputVarType, NodeRunningStatus } from '@/app/components/workflow/types' +import { + useIsChatMode, + useNodeDataUpdate, + useWorkflow, +} from '@/app/components/workflow/hooks' +import { toNodeOutputVars } from '@/app/components/workflow/nodes/_base/components/variable/utils' + +import type { CheckValidRes, CommonNodeType, InputVar, ValueSelector, Var, Variable } from '@/app/components/workflow/types' +import { BlockEnum, InputVarType, NodeRunningStatus, VarType } from '@/app/components/workflow/types' import { useStore as useAppStore } from '@/app/components/app/store' import { singleNodeRun } from '@/service/workflow' import Toast from '@/app/components/base/toast' @@ -22,6 +28,27 @@ type Params = { beforeRunCheckValid?: () => CheckValidRes } +const varTypeToInputVarType = (type: VarType, { + isSelect, + isParagraph, +}: { + isSelect: boolean + isParagraph: boolean +}) => { + if (isSelect) + return InputVarType.select + if (isParagraph) + return InputVarType.paragraph + if (type === VarType.number) + return InputVarType.number + if ([VarType.object, VarType.array, VarType.arrayNumber, VarType.arrayString, VarType.arrayObject].includes(type)) + return InputVarType.json + if (type === VarType.arrayFile) + return InputVarType.files + + return InputVarType.textInput +} + const useOneStepRun = ({ id, data, @@ -29,6 +56,32 @@ const useOneStepRun = ({ beforeRunCheckValid = () => ({ isValid: true }), }: Params) => { const { t } = useTranslation() + const { getBeforeNodesInSameBranch } = useWorkflow() + const isChatMode = useIsChatMode() + + const allOutputVars = toNodeOutputVars(getBeforeNodesInSameBranch(id), isChatMode) + const getVar = (valueSelector: ValueSelector): Var | undefined => { + let res: Var | undefined + const targetVar = allOutputVars.find(v => v.nodeId === valueSelector[0]) + if (!targetVar) + return undefined + + let curr: any = targetVar.vars + valueSelector.slice(1).forEach((key, i) => { + const isLast = i === valueSelector.length - 2 + curr = curr.find((v: any) => v.variable === key) + if (isLast) { + res = curr + } + else { + if (curr.type === VarType.object) + curr = curr.children + } + }) + + return res + } + const checkValid = checkValidFns[data.type] const appId = useAppStore.getState().appDetail?.id const [runInputData, setRunInputData] = useState>(defaultRunInputData || {}) @@ -91,10 +144,6 @@ const useOneStepRun = ({ throw new Error(res.error) } catch (e: any) { - // Toast.notify({ - // type: 'error', - // message: e.toString(), - // }) handleNodeDataUpdate({ id, data: { @@ -133,14 +182,25 @@ const useOneStepRun = ({ if (!variables) return [] - const varInputs = variables.map((item, i) => { - const allVarTypes = [InputVarType.textInput, InputVarType.paragraph, InputVarType.number, InputVarType.select, InputVarType.files] + const varInputs = variables.map((item) => { + const originalVar = getVar(item.value_selector) + if (!originalVar) { + return { + label: item.variable, + variable: item.variable, + type: InputVarType.textInput, + required: true, + } + } return { label: item.variable, variable: item.variable, - type: allVarTypes[i % allVarTypes.length], // TODO: dynamic get var type - required: true, // TODO - options: ['a', 'b', 'c'], // TODO + type: varTypeToInputVarType(originalVar.type, { + isSelect: !!originalVar.isSelect, + isParagraph: !!originalVar.isParagraph, + }), + required: item.required !== false, + options: originalVar.options, } }) diff --git a/web/app/components/workflow/nodes/llm/use-config.ts b/web/app/components/workflow/nodes/llm/use-config.ts index 96ff2cc981..50306233d6 100644 --- a/web/app/components/workflow/nodes/llm/use-config.ts +++ b/web/app/components/workflow/nodes/llm/use-config.ts @@ -56,9 +56,9 @@ const useConfig = (id: string, payload: LLMNodeType) => { }) // context - const handleContextVarChange = useCallback((newVar: ValueSelector) => { + const handleContextVarChange = useCallback((newVar: ValueSelector | string) => { const newInputs = produce(inputs, (draft) => { - draft.context.variable_selector = newVar + draft.context.variable_selector = newVar as ValueSelector }) setInputs(newInputs) }, [inputs, setInputs]) diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index 22cf19f1bf..91d72a1486 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -61,6 +61,9 @@ export type Variable = { value_selector: ValueSelector variable_type?: VarKindType value?: string + options?: string[] + required?: boolean + isParagraph?: boolean } export type VariableWithValue = { @@ -75,6 +78,7 @@ export enum InputVarType { number = 'number', url = 'url', files = 'files', + json = 'json', // obj, array contexts = 'contexts', // knowledge retrieval } @@ -141,6 +145,10 @@ export type Var = { variable: string type: VarType children?: Var[] // if type is obj, has the children struct + isParagraph?: boolean + isSelect?: boolean + options?: string[] + required?: boolean } export type NodeOutPutVar = {