diff --git a/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx b/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx index 0d37f9bee4..2d81691c3c 100644 --- a/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx +++ b/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx @@ -1,6 +1,6 @@ 'use client' import type { FC } from 'react' -import React from 'react' +import React, { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { RiCloseLine, @@ -21,6 +21,7 @@ import type { BlockEnum } from '@/app/components/workflow/types' import type { Emoji } from '@/app/components/tools/types' import type { SpecialResultPanelProps } from '@/app/components/workflow/run/special-result-panel' import SpecialResultPanel from '@/app/components/workflow/run/special-result-panel' +import { useWorkflowStore } from '@/app/components/workflow/store' const i18nPrefix = 'workflow.singleRun' @@ -72,6 +73,61 @@ const BeforeRunForm: FC = ({ ...restResultPanelParams }) => { const { t } = useTranslation() + console.log(forms) + + const workflowStore = useWorkflowStore() + const { + getInspectVar, + } = workflowStore.getState() + + const existVarValuesInForms = useMemo(() => { + const valuesArr = forms.map((form) => { + const values: Record = {} + form.inputs.forEach(({ variable }) => { + // #nodeId.path1?.path2?...# => [nodeId, path1] + // TODO: conversation vars and envs + const selector = variable.slice(1, -1).split('.') + const [nodeId, varName] = selector.slice(0, 2) + const inspectVarValue = getInspectVar(nodeId, varName) + if (inspectVarValue !== undefined) { + const subPathArr = selector.slice(2) + if (subPathArr.length > 0) { + let current = inspectVarValue.value + let invalid = false + subPathArr.forEach((subPath) => { + if (invalid) + return + + if (current && typeof current === 'object' && subPath in current) { + current = current[subPath] + return + } + invalid = true + }) + values[variable] = current + } + else { + values[variable] = inspectVarValue + } + } + }) + return values + }) + return valuesArr + }, [forms, getInspectVar]) + + const filteredExistVarForms = useMemo(() => { + const res = forms.map((form, i) => { + const existVarValuesInForm = existVarValuesInForms[i] + const newForm = { ...form } + const inputs = form.inputs.filter((input) => { + return !(input.variable in existVarValuesInForm) + }) + newForm.inputs = inputs + return newForm + }).filter(form => form.inputs.length > 0) + return res + }, [forms, existVarValuesInForms]) const isFinished = runningStatus === NodeRunningStatus.Succeeded || runningStatus === NodeRunningStatus.Failed || runningStatus === NodeRunningStatus.Exception const isRunning = runningStatus === NodeRunningStatus.Running @@ -89,10 +145,12 @@ const BeforeRunForm: FC = ({ })() const handleRun = () => { let errMsg = '' - forms.forEach((form) => { + forms.forEach((form, i) => { + const existVarValuesInForm = existVarValuesInForms[i] + form.inputs.forEach((input) => { const value = form.values[input.variable] as any - if (!errMsg && input.required && (value === '' || value === undefined || value === null || (input.type === InputVarType.files && value.length === 0))) + if (!errMsg && input.required && !(input.variable in existVarValuesInForm) && (value === '' || value === undefined || value === null || (input.type === InputVarType.files && value.length === 0))) errMsg = t('workflow.errorMsg.fieldRequired', { field: typeof input.label === 'object' ? input.label.variable : input.label }) if (!errMsg && (input.type === InputVarType.singleFile || input.type === InputVarType.multiFiles) && value) { @@ -117,8 +175,15 @@ const BeforeRunForm: FC = ({ const submitData: Record = {} let parseErrorJsonField = '' - forms.forEach((form) => { + forms.forEach((form, i) => { + const existVarValuesInForm = existVarValuesInForms[i] + form.inputs.forEach((input) => { + if (input.variable in existVarValuesInForm) { + // TODO: if is the big value, should fetch value from server + submitData[input.variable] = existVarValuesInForm[input.variable] + return + } try { const value = formatValue(form.values[input.variable], input.type) submitData[input.variable] = value @@ -162,7 +227,7 @@ const BeforeRunForm: FC = ({ !showSpecialResultPanel && (
- {forms.map((form, index) => ( + {filteredExistVarForms.map((form, index) => (
({ }, [doSetRunInputData]) const [isDataFromHistory, setIsDataFromHistory] = useState(true) - const [tabType, setTabType] = useState(TabType.lastRun) + const [tabType, setTabType] = useState(TabType.settings) const handleRun = async (data: Record) => { setIsDataFromHistory(false) setTabType(TabType.lastRun) diff --git a/web/app/components/workflow/store/workflow/debug/inspect-vars-slice.ts b/web/app/components/workflow/store/workflow/debug/inspect-vars-slice.ts index 93a8fe0f96..9fd185fb5d 100644 --- a/web/app/components/workflow/store/workflow/debug/inspect-vars-slice.ts +++ b/web/app/components/workflow/store/workflow/debug/inspect-vars-slice.ts @@ -1,7 +1,7 @@ import type { StateCreator } from 'zustand' import produce from 'immer' -import type { NodeWithVar, VarInInspect } from '@/types/workflow' -import type { ValueSelector } from '../../../types' +import { type NodeWithVar, type VarInInspect, VarInInspectType } from '@/types/workflow' +import { BlockEnum, VarType } from '../../../types' type InspectVarsState = { currentFocusNodeId: string | null @@ -17,8 +17,8 @@ type InspectVarsActions = { clearNodeInspectVars: (nodeId: string) => void getNodeInspectVars: (nodeId: string) => NodeWithVar | undefined hasNodeInspectVars: (nodeId: string) => boolean - setInspectVar: (nodeId: string, selector: ValueSelector, value: any) => void - getInspectVar: (nodeId: string, selector: ValueSelector) => any + setInspectVar: (nodeId: string, name: string, value: any) => void + getInspectVar: (nodeId: string, name: string) => any // The big value is null } export type InspectVarsSliceShape = InspectVarsState & InspectVarsActions @@ -26,7 +26,25 @@ export type InspectVarsSliceShape = InspectVarsState & InspectVarsActions export const createInspectVarsSlice: StateCreator = (set, get) => { return ({ currentFocusNodeId: null, - nodesWithInspectVars: [], + nodesWithInspectVars: [ + { + nodeId: '1745476079387', + nodeType: BlockEnum.LLM, + title: 'llm 2', + vars: [ + { + id: 'xxx', + type: VarInInspectType.node, + name: 'llm 2', + description: '', + selector: ['1745476079387', 'text'], + value_type: VarType.string, + value: 'text value...', + edited: false, + }, + ], + }, + ], conversationVars: [], setCurrentFocusNodeId: (nodeId) => { set(() => ({ @@ -71,13 +89,13 @@ export const createInspectVarsSlice: StateCreator = (set, hasNodeInspectVars: (nodeId) => { return !!get().getNodeInspectVars(nodeId) }, - setInspectVar: (nodeId, selector, value) => { + setInspectVar: (nodeId, name, value) => { set(produce((state: InspectVarsSliceShape) => { const nodes = state.nodesWithInspectVars.map((node) => { if (node.nodeId === nodeId) { return produce(node, (draft) => { const needChangeVarIndex = draft.vars.findIndex((varItem) => { - return varItem.selector.join('.') === selector.join('.') + return varItem.selector[1] === name }) if (needChangeVarIndex !== -1) draft.vars[needChangeVarIndex].value = value @@ -88,13 +106,13 @@ export const createInspectVarsSlice: StateCreator = (set, state.nodesWithInspectVars = nodes })) }, - getInspectVar(nodeId, key) { + getInspectVar(nodeId, name) { const node = get().getNodeInspectVars(nodeId) if (!node) return undefined const variable = node.vars.find((varItem) => { - return varItem.selector.join('.') === key.join('.') + return varItem.selector[1] === name })?.value return variable },