Feat: Fixed the issue where form data assigned by variables was not updated in real time. #10427 (#11333)

### What problem does this PR solve?

Feat: Fixed the issue where form data assigned by variables was not
updated in real time. #10427
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-11-18 13:07:52 +08:00
committed by GitHub
parent 2993fc666b
commit 701761d119
6 changed files with 46 additions and 49 deletions

View File

@ -169,3 +169,13 @@ export const SwitchOperatorOptions = [
icon: <CircleSlash2 className="size-4" />, icon: <CircleSlash2 className="size-4" />,
}, },
]; ];
export const AgentStructuredOutputField = 'structured';
export enum JsonSchemaDataType {
String = 'string',
Number = 'number',
Boolean = 'boolean',
Array = 'array',
Object = 'object',
}

View File

@ -5,6 +5,7 @@ import {
import { import {
AgentGlobals, AgentGlobals,
AgentGlobalsSysQueryWithBrace, AgentGlobalsSysQueryWithBrace,
AgentStructuredOutputField,
CodeTemplateStrMap, CodeTemplateStrMap,
ComparisonOperator, ComparisonOperator,
Operator, Operator,
@ -12,7 +13,11 @@ import {
SwitchOperatorOptions, SwitchOperatorOptions,
initialLlmBaseValues, initialLlmBaseValues,
} from '@/constants/agent'; } from '@/constants/agent';
export { Operator } from '@/constants/agent'; export {
AgentStructuredOutputField,
JsonSchemaDataType,
Operator,
} from '@/constants/agent';
export * from './pipeline'; export * from './pipeline';
@ -441,8 +446,6 @@ export const initialCodeValues = {
export const initialWaitingDialogueValues = {}; export const initialWaitingDialogueValues = {};
export const AgentStructuredOutputField = 'structured';
export const initialAgentValues = { export const initialAgentValues = {
...initialLlmBaseValues, ...initialLlmBaseValues,
description: '', description: '',
@ -839,14 +842,6 @@ export const DROPDOWN_HORIZONTAL_OFFSET = 28;
export const DROPDOWN_VERTICAL_OFFSET = 74; export const DROPDOWN_VERTICAL_OFFSET = 74;
export const PREVENT_CLOSE_DELAY = 300; export const PREVENT_CLOSE_DELAY = 300;
export enum JsonSchemaDataType {
String = 'string',
Number = 'number',
Boolean = 'boolean',
Array = 'array',
Object = 'object',
}
export enum VariableAssignerLogicalOperator { export enum VariableAssignerLogicalOperator {
Overwrite = 'overwrite', Overwrite = 'overwrite',
Clear = 'clear', Clear = 'clear',

View File

@ -7,7 +7,7 @@ import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { Editor } from '@monaco-editor/react'; import Editor, { loader } from '@monaco-editor/react';
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'; import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import { ReactNode, useCallback } from 'react'; import { ReactNode, useCallback } from 'react';
@ -23,6 +23,8 @@ import { DynamicFormHeader } from '../components/dynamic-fom-header';
import { QueryVariable } from '../components/query-variable'; import { QueryVariable } from '../components/query-variable';
import { useBuildLogicalOptions } from './use-build-logical-options'; import { useBuildLogicalOptions } from './use-build-logical-options';
loader.config({ paths: { vs: '/vs' } });
type SelectKeysProps = { type SelectKeysProps = {
name: string; name: string;
label: ReactNode; label: ReactNode;
@ -70,7 +72,7 @@ const EmptyValueMap = {
[JsonSchemaDataType.String]: '', [JsonSchemaDataType.String]: '',
[JsonSchemaDataType.Number]: 0, [JsonSchemaDataType.Number]: 0,
[JsonSchemaDataType.Boolean]: 'yes', [JsonSchemaDataType.Boolean]: 'yes',
[JsonSchemaDataType.Object]: {}, [JsonSchemaDataType.Object]: '{}',
[JsonSchemaDataType.Array]: [], [JsonSchemaDataType.Array]: [],
}; };
@ -86,7 +88,7 @@ export function DynamicVariables({
const { getType } = useGetVariableLabelOrTypeByValue(); const { getType } = useGetVariableLabelOrTypeByValue();
const isDarkTheme = useIsDarkTheme(); const isDarkTheme = useIsDarkTheme();
const { fields, remove, append, update } = useFieldArray({ const { fields, remove, append } = useFieldArray({
name: name, name: name,
control: form.control, control: form.control,
}); });
@ -102,15 +104,7 @@ export function DynamicVariables({
); );
const renderParameter = useCallback( const renderParameter = useCallback(
( (keyFieldName: string, operatorFieldName: string) => {
keyFieldName: string,
operatorFieldName: string,
valueFieldAlias: string,
) => {
console.log(
'🚀 ~ DynamicVariables ~ valueFieldAlias:',
form.getValues(valueFieldAlias),
);
const logicalOperator = form.getValues(operatorFieldName); const logicalOperator = form.getValues(operatorFieldName);
const type = getVariableType(keyFieldName); const type = getVariableType(keyFieldName);
@ -169,10 +163,6 @@ export function DynamicVariables({
const handleVariableChange = useCallback( const handleVariableChange = useCallback(
(operatorFieldAlias: string, valueFieldAlias: string) => { (operatorFieldAlias: string, valueFieldAlias: string) => {
console.log(
'🚀 ~ DynamicVariables ~ operatorFieldAlias:',
operatorFieldAlias,
);
return () => { return () => {
form.setValue( form.setValue(
operatorFieldAlias, operatorFieldAlias,
@ -190,14 +180,8 @@ export function DynamicVariables({
); );
const handleOperatorChange = useCallback( const handleOperatorChange = useCallback(
( (valueFieldAlias: string, keyFieldAlias: string, value: string) => {
valueFieldAlias: string,
keyFieldAlias: string,
value: string,
index: number,
) => {
const type = getVariableType(keyFieldAlias); const type = getVariableType(keyFieldAlias);
console.log('🚀 ~ DynamicVariables ~ type:', type);
let parameter = EmptyValueMap[type as keyof typeof EmptyValueMap]; let parameter = EmptyValueMap[type as keyof typeof EmptyValueMap];
@ -210,10 +194,6 @@ export function DynamicVariables({
shouldDirty: true, shouldDirty: true,
shouldValidate: true, shouldValidate: true,
}); });
// form.trigger(valueFieldAlias);
// update(index, { [valueField]: parameter });
} }
}, },
[form, getVariableType], [form, getVariableType],
@ -258,7 +238,6 @@ export function DynamicVariables({
valueFieldAlias, valueFieldAlias,
keyFieldAlias, keyFieldAlias,
val, val,
index,
); );
onChange(val); onChange(val);
}} }}
@ -270,11 +249,7 @@ export function DynamicVariables({
</RAGFlowFormItem> </RAGFlowFormItem>
</div> </div>
<RAGFlowFormItem name={valueFieldAlias} className="w-full"> <RAGFlowFormItem name={valueFieldAlias} className="w-full">
{renderParameter( {renderParameter(keyFieldAlias, operatorFieldAlias)}
keyFieldAlias,
operatorFieldAlias,
valueFieldAlias,
)}
</RAGFlowFormItem> </RAGFlowFormItem>
</div> </div>

View File

@ -33,7 +33,6 @@ function VariableAssignerForm({ node }: INextOperatorForm) {
defaultValues: defaultValues, defaultValues: defaultValues,
mode: 'onChange', mode: 'onChange',
resolver: zodResolver(FormSchema), resolver: zodResolver(FormSchema),
shouldUnregister: true,
}); });
useWatchFormChange(node?.id, form, true); useWatchFormChange(node?.id, form, true);

View File

@ -1,7 +1,7 @@
import { AgentGlobals } from '@/constants/agent'; import { AgentGlobals, AgentStructuredOutputField } from '@/constants/agent';
import { useFetchAgent } from '@/hooks/use-agent-request'; import { useFetchAgent } from '@/hooks/use-agent-request';
import { RAGFlowNodeType } from '@/interfaces/database/flow'; import { RAGFlowNodeType } from '@/interfaces/database/flow';
import { buildNodeOutputOptions } from '@/utils/canvas-util'; import { buildNodeOutputOptions, isAgentStructured } from '@/utils/canvas-util';
import { DefaultOptionType } from 'antd/es/select'; import { DefaultOptionType } from 'antd/es/select';
import { t } from 'i18next'; import { t } from 'i18next';
import { isEmpty, toLower } from 'lodash'; import { isEmpty, toLower } from 'lodash';
@ -236,7 +236,11 @@ export function useFilterQueryVariableOptionsByTypes(
toLower(x).startsWith('array') toLower(x).startsWith('array')
? toLower(y.type).includes(toLower(x)) ? toLower(y.type).includes(toLower(x))
: toLower(y.type) === toLower(x), : toLower(y.type) === toLower(x),
) || y.type === undefined, // agent structured output ) ||
isAgentStructured(
y.value,
y.value.slice(-AgentStructuredOutputField.length),
), // agent structured output
), ),
}; };
}) })

View File

@ -1,4 +1,10 @@
import {
AgentStructuredOutputField,
JsonSchemaDataType,
Operator,
} from '@/constants/agent';
import { BaseNode } from '@/interfaces/database/agent'; import { BaseNode } from '@/interfaces/database/agent';
import { Edge } from '@xyflow/react'; import { Edge } from '@xyflow/react';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { ComponentType, ReactNode } from 'react'; import { ComponentType, ReactNode } from 'react';
@ -23,6 +29,12 @@ export function filterAllUpstreamNodeIds(edges: Edge[], nodeIds: string[]) {
}, []); }, []);
} }
export function isAgentStructured(id?: string, label?: string) {
return (
label === AgentStructuredOutputField && id?.startsWith(`${Operator.Agent}:`)
);
}
export function buildOutputOptions( export function buildOutputOptions(
outputs: Record<string, any> = {}, outputs: Record<string, any> = {},
nodeId?: string, nodeId?: string,
@ -34,7 +46,9 @@ export function buildOutputOptions(
value: `${nodeId}@${x}`, value: `${nodeId}@${x}`,
parentLabel, parentLabel,
icon, icon,
type: outputs[x]?.type, type: isAgentStructured(nodeId, x)
? JsonSchemaDataType.Object
: outputs[x]?.type,
})); }));
} }