From 558b252c5a6c77956de99c87ae6aef08ecec644b Mon Sep 17 00:00:00 2001 From: balibabu Date: Wed, 21 May 2025 18:22:06 +0800 Subject: [PATCH] Feat: Switching the programming language of the code operator will switch the corresponding language template #3221 (#7770) ### What problem does this PR solve? Feat: Switching the programming language of the code operator will switch the corresponding language template #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/pages/agent/canvas/node/note-node.tsx | 6 +- web/src/pages/agent/form-sheet/next.tsx | 3 +- .../agent/form-sheet/use-form-config-map.tsx | 10 +- web/src/pages/agent/form/code-form/index.tsx | 19 ++-- .../agent/form/code-form/next-variable.tsx | 12 ++- web/src/pages/agent/hooks.tsx | 10 +- .../agent/hooks/use-watch-form-change.ts | 98 +++++++++++++++++++ 7 files changed, 133 insertions(+), 25 deletions(-) create mode 100644 web/src/pages/agent/hooks/use-watch-form-change.ts diff --git a/web/src/pages/agent/canvas/node/note-node.tsx b/web/src/pages/agent/canvas/node/note-node.tsx index 1917a8150..237942133 100644 --- a/web/src/pages/agent/canvas/node/note-node.tsx +++ b/web/src/pages/agent/canvas/node/note-node.tsx @@ -8,10 +8,8 @@ import { useTheme } from '@/components/theme-provider'; import { INoteNode } from '@/interfaces/database/flow'; import { memo, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import { - useHandleFormValuesChange, - useHandleNodeNameChange, -} from '../../hooks'; +import { useHandleNodeNameChange } from '../../hooks'; +import { useHandleFormValuesChange } from '../../hooks/use-watch-form-change'; import styles from './index.less'; const { TextArea } = Input; diff --git a/web/src/pages/agent/form-sheet/next.tsx b/web/src/pages/agent/form-sheet/next.tsx index 4601ccfa5..7998f1068 100644 --- a/web/src/pages/agent/form-sheet/next.tsx +++ b/web/src/pages/agent/form-sheet/next.tsx @@ -17,7 +17,8 @@ import { useForm } from 'react-hook-form'; import { BeginId, Operator, operatorMap } from '../constant'; import { FlowFormContext } from '../context'; import { RunTooltip } from '../flow-tooltip'; -import { useHandleFormValuesChange, useHandleNodeNameChange } from '../hooks'; +import { useHandleNodeNameChange } from '../hooks'; +import { useHandleFormValuesChange } from '../hooks/use-watch-form-change'; import OperatorIcon from '../operator-icon'; import { buildCategorizeListFromObject, diff --git a/web/src/pages/agent/form-sheet/use-form-config-map.tsx b/web/src/pages/agent/form-sheet/use-form-config-map.tsx index fe2662ae5..13c1e95f9 100644 --- a/web/src/pages/agent/form-sheet/use-form-config-map.tsx +++ b/web/src/pages/agent/form-sheet/use-form-config-map.tsx @@ -133,14 +133,12 @@ export function useFormConfigMap() { }, [Operator.Code]: { component: CodeForm, - defaultValues: { - message_history_window_size: 6, - }, + defaultValues: { arguments: [] }, schema: z.object({ script: z.string(), - arguments: z - .array(z.object({ name: z.string(), component_id: z.string() })) - .optional(), + arguments: z.array( + z.object({ name: z.string(), component_id: z.string() }), + ), lang: z.string(), }), }, diff --git a/web/src/pages/agent/form/code-form/index.tsx b/web/src/pages/agent/form/code-form/index.tsx index 992e04fa5..c5282a6b1 100644 --- a/web/src/pages/agent/form/code-form/index.tsx +++ b/web/src/pages/agent/form/code-form/index.tsx @@ -10,8 +10,9 @@ import { FormMessage, } from '@/components/ui/form'; import { RAGFlowSelect } from '@/components/ui/select'; -import { ProgrammingLanguage } from '@/constants/agent'; +import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; import { ICodeForm } from '@/interfaces/database/flow'; +import { useEffect } from 'react'; import { DynamicInputVariable } from './next-variable'; loader.config({ paths: { vs: '/vs' } }); @@ -24,15 +25,13 @@ const options = [ const CodeForm = ({ form, node }: INextOperatorForm) => { const formData = node?.data.form as ICodeForm; - // useEffect(() => { - // setTimeout(() => { - // // TODO: Direct operation zustand is more elegant - // form?.setFieldValue( - // 'script', - // CodeTemplateStrMap[formData.lang as ProgrammingLanguage], - // ); - // }, 0); - // }, [form, formData.lang]); + useEffect(() => { + // TODO: Direct operation zustand is more elegant + form?.setValue( + 'script', + CodeTemplateStrMap[formData.lang as ProgrammingLanguage], + ); + }, [form, formData.lang]); return (
diff --git a/web/src/pages/agent/form/code-form/next-variable.tsx b/web/src/pages/agent/form/code-form/next-variable.tsx index d0e5790df..90b2f8099 100644 --- a/web/src/pages/agent/form/code-form/next-variable.tsx +++ b/web/src/pages/agent/form/code-form/next-variable.tsx @@ -54,7 +54,10 @@ export function DynamicVariableForm({ node, name = 'arguments' }: IProps) { - + @@ -84,7 +87,12 @@ export function DynamicVariableForm({ node, name = 'arguments' }: IProps) { ); })} - diff --git a/web/src/pages/agent/hooks.tsx b/web/src/pages/agent/hooks.tsx index ab55dbf0f..f346528a9 100644 --- a/web/src/pages/agent/hooks.tsx +++ b/web/src/pages/agent/hooks.tsx @@ -294,7 +294,13 @@ export const useHandleFormValuesChange = ( useEffect(() => { const subscription = form?.watch((value, { name, type, values }) => { if (id && name) { - console.log('🚀 ~ useEffect ~ value:', type, values); + console.log( + '🚀 ~ useEffect ~ value:', + name, + type, + values, + operatorName, + ); let nextValues: any = value; // Fixed the issue that the related form value does not change after selecting the freedom field of the model @@ -320,8 +326,8 @@ export const useHandleFormValuesChange = ( category_description: buildCategorizeObjectFromList(value.items), }; } + // Manually triggered form updates are synchronized to the canvas if (type) { - // Manually triggered form updates are synchronized to the canvas updateNodeForm(id, nextValues); } } diff --git a/web/src/pages/agent/hooks/use-watch-form-change.ts b/web/src/pages/agent/hooks/use-watch-form-change.ts new file mode 100644 index 000000000..c3e73aa8d --- /dev/null +++ b/web/src/pages/agent/hooks/use-watch-form-change.ts @@ -0,0 +1,98 @@ +import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; +import { settledModelVariableMap } from '@/constants/knowledge'; +import { omit } from 'lodash'; +import { useCallback, useEffect } from 'react'; +import { UseFormReturn } from 'react-hook-form'; +import { Operator } from '../constant'; +import useGraphStore from '../store'; +import { buildCategorizeObjectFromList } from '../utils'; + +export const useHandleFormValuesChange = ( + operatorName: Operator, + id?: string, + form?: UseFormReturn, +) => { + const updateNodeForm = useGraphStore((state) => state.updateNodeForm); + + const handleValuesChange = useCallback( + (changedValues: any, values: any) => { + let nextValues: any = values; + // Fixed the issue that the related form value does not change after selecting the freedom field of the model + if ( + Object.keys(changedValues).length === 1 && + 'parameter' in changedValues && + changedValues['parameter'] in settledModelVariableMap + ) { + nextValues = { + ...values, + ...settledModelVariableMap[ + changedValues['parameter'] as keyof typeof settledModelVariableMap + ], + }; + } + if (id) { + updateNodeForm(id, nextValues); + } + }, + [updateNodeForm, id], + ); + + useEffect(() => { + const subscription = form?.watch((value, { name, type, values }) => { + console.log('🚀 ~ subscription ~ value:', value); + if (id && name) { + console.log( + '🚀 ~ useEffect ~ value:', + name, + type, + values, + operatorName, + ); + let nextValues: any = value; + + // Fixed the issue that the related form value does not change after selecting the freedom field of the model + if ( + name === 'parameter' && + value['parameter'] in settledModelVariableMap + ) { + nextValues = { + ...value, + ...settledModelVariableMap[ + value['parameter'] as keyof typeof settledModelVariableMap + ], + }; + } + + const categoryDescriptionRegex = /items\.\d+\.name/g; + if ( + operatorName === Operator.Categorize && + categoryDescriptionRegex.test(name) + ) { + nextValues = { + ...omit(value, 'items'), + category_description: buildCategorizeObjectFromList(value.items), + }; + } + + if ( + operatorName === Operator.Code && + type === 'change' && + name === 'lang' + ) { + nextValues = { + ...value, + script: CodeTemplateStrMap[value.lang as ProgrammingLanguage], + }; + } + // Manually triggered form updates are synchronized to the canvas + if (type) { + // run(id, nextValues); + updateNodeForm(id, nextValues); + } + } + }); + return () => subscription?.unsubscribe(); + }, [form, form?.watch, id, operatorName, updateNodeForm]); + + return { handleValuesChange }; +};