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)
This commit is contained in:
balibabu 2025-05-21 18:22:06 +08:00 committed by GitHub
parent 754a5e1cee
commit 558b252c5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 133 additions and 25 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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(),
}),
},

View File

@ -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 (
<Form {...form}>

View File

@ -54,7 +54,10 @@ export function DynamicVariableForm({ node, name = 'arguments' }: IProps) {
<FormItem className="w-2/5">
<FormDescription />
<FormControl>
<Input placeholder={t('common.pleaseInput')} {...field} />
<Input
{...field}
placeholder={t('common.pleaseInput')}
></Input>
</FormControl>
<FormMessage />
</FormItem>
@ -84,7 +87,12 @@ export function DynamicVariableForm({ node, name = 'arguments' }: IProps) {
</div>
);
})}
<Button onClick={append} className="mt-4" variant={'outline'} size={'sm'}>
<Button
onClick={() => append({ name: '', component_id: undefined })}
className="mt-4"
variant={'outline'}
size={'sm'}
>
<Plus />
{t('flow.addVariable')}
</Button>

View File

@ -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);
}
}

View File

@ -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 };
};