From ba10b646373980ec0b3c64a06596784562515e2f Mon Sep 17 00:00:00 2001 From: bill Date: Tue, 18 Nov 2025 16:50:46 +0800 Subject: [PATCH] Feat: Make the variable assignment form match the type of the key. --- .../node/dropdown/accordion-operators.tsx | 1 - .../structured-output-secondary-menu.tsx | 17 ++++++++++++----- web/src/pages/agent/form/message-form/index.tsx | 3 ++- .../pages/agent/form/message-form/use-values.ts | 3 +-- .../agent/hooks/use-build-structured-output.ts | 5 +++-- .../utils/filter-agent-structured-output.ts | 16 ++++++++++++---- web/src/utils/canvas-util.tsx | 14 +++++++++++++- 7 files changed, 43 insertions(+), 16 deletions(-) diff --git a/web/src/pages/agent/canvas/node/dropdown/accordion-operators.tsx b/web/src/pages/agent/canvas/node/dropdown/accordion-operators.tsx index dd458279c..6021420c5 100644 --- a/web/src/pages/agent/canvas/node/dropdown/accordion-operators.tsx +++ b/web/src/pages/agent/canvas/node/dropdown/accordion-operators.tsx @@ -81,7 +81,6 @@ export function AccordionOperators({ Operator.DataOperations, Operator.VariableAssigner, Operator.ListOperations, - Operator.VariableAssigner, Operator.VariableAggregator, ]} isCustomDropdown={isCustomDropdown} diff --git a/web/src/pages/agent/form/components/structured-output-secondary-menu.tsx b/web/src/pages/agent/form/components/structured-output-secondary-menu.tsx index 2e7a34390..5fcf6ed4e 100644 --- a/web/src/pages/agent/form/components/structured-output-secondary-menu.tsx +++ b/web/src/pages/agent/form/components/structured-output-secondary-menu.tsx @@ -4,6 +4,7 @@ import { HoverCardTrigger, } from '@/components/ui/hover-card'; import { cn } from '@/lib/utils'; +import { getStructuredDatatype } from '@/utils/canvas-util'; import { get, isEmpty, isPlainObject } from 'lodash'; import { ChevronRight } from 'lucide-react'; import { PropsWithChildren, ReactNode, useCallback } from 'react'; @@ -62,22 +63,28 @@ export function StructuredOutputSecondaryMenu({ value: option.value + `.${key}`, }; - const dataType = get(value, 'type'); + const { dataType, compositeDataType } = + getStructuredDatatype(value); if ( isEmpty(types) || (!isEmpty(types) && - (types?.some((x) => x === dataType) || + (types?.some((x) => x === compositeDataType) || hasSpecificTypeChild(value ?? {}, types))) ) { return (
  • {key} - {dataType} + + {compositeDataType} +
    {[JsonSchemaDataType.Object, JsonSchemaDataType.Array].some( (x) => x === dataType, @@ -122,7 +129,7 @@ export function StructuredOutputSecondaryMenu({ side="left" align="start" className={cn( - 'min-w-[140px] border border-border rounded-md shadow-lg p-0', + 'min-w-72 border border-border rounded-md shadow-lg p-0', )} >
    diff --git a/web/src/pages/agent/form/message-form/index.tsx b/web/src/pages/agent/form/message-form/index.tsx index 31b52659e..177fc2f45 100644 --- a/web/src/pages/agent/form/message-form/index.tsx +++ b/web/src/pages/agent/form/message-form/index.tsx @@ -81,7 +81,8 @@ function MessageForm({ node }: INextOperatorForm) { )} {...field} onValueChange={field.onChange} - placeholder={t('flow.messagePlaceholder')} + placeholder={t('common.selectPlaceholder')} + allowClear > diff --git a/web/src/pages/agent/form/message-form/use-values.ts b/web/src/pages/agent/form/message-form/use-values.ts index 0cece91fc..6a90881be 100644 --- a/web/src/pages/agent/form/message-form/use-values.ts +++ b/web/src/pages/agent/form/message-form/use-values.ts @@ -1,7 +1,7 @@ import { RAGFlowNodeType } from '@/interfaces/database/flow'; import { isEmpty } from 'lodash'; import { useMemo } from 'react'; -import { ExportFileType, initialMessageValues } from '../../constant'; +import { initialMessageValues } from '../../constant'; import { convertToObjectArray } from '../../utils'; export function useValues(node?: RAGFlowNodeType) { @@ -15,7 +15,6 @@ export function useValues(node?: RAGFlowNodeType) { return { ...formData, content: convertToObjectArray(formData.content), - output_format: formData.output_format || ExportFileType.PDF, }; }, [node]); diff --git a/web/src/pages/agent/hooks/use-build-structured-output.ts b/web/src/pages/agent/hooks/use-build-structured-output.ts index 891c2dfa9..c9d34bd43 100644 --- a/web/src/pages/agent/hooks/use-build-structured-output.ts +++ b/web/src/pages/agent/hooks/use-build-structured-output.ts @@ -1,3 +1,4 @@ +import { getStructuredDatatype } from '@/utils/canvas-util'; import { get, isPlainObject } from 'lodash'; import { ReactNode, useCallback } from 'react'; import { @@ -106,10 +107,10 @@ export function useFindAgentStructuredOutputTypeByValue() { if (isPlainObject(values) && properties) { for (const [key, value] of Object.entries(properties)) { const nextPath = path ? `${path}.${key}` : key; - const dataType = get(value, 'type'); + const { dataType, compositeDataType } = getStructuredDatatype(value); if (nextPath === target) { - return dataType; + return compositeDataType; } if ( diff --git a/web/src/pages/agent/utils/filter-agent-structured-output.ts b/web/src/pages/agent/utils/filter-agent-structured-output.ts index 40db6b4fe..c20263631 100644 --- a/web/src/pages/agent/utils/filter-agent-structured-output.ts +++ b/web/src/pages/agent/utils/filter-agent-structured-output.ts @@ -1,9 +1,13 @@ import { JSONSchema } from '@/components/jsonjoy-builder'; +import { getStructuredDatatype } from '@/utils/canvas-util'; import { get, isPlainObject, toLower } from 'lodash'; import { JsonSchemaDataType } from '../constant'; -function predicate(types: string[], type: string) { - return types.some((x) => toLower(x) === toLower(type)); +function predicate(types: string[], value: unknown) { + return types.some( + (x) => + toLower(x) === toLower(getStructuredDatatype(value).compositeDataType), + ); } export function hasSpecificTypeChild( @@ -12,7 +16,7 @@ export function hasSpecificTypeChild( ) { if (Array.isArray(data)) { for (const value of data) { - if (isPlainObject(value) && predicate(types, value.type)) { + if (isPlainObject(value) && predicate(types, value)) { return true; } if (hasSpecificTypeChild(value, types)) { @@ -23,7 +27,11 @@ export function hasSpecificTypeChild( if (isPlainObject(data)) { for (const value of Object.values(data)) { - if (isPlainObject(value) && predicate(types, value.type)) { + if ( + isPlainObject(value) && + predicate(types, value) && + get(data, 'type') !== JsonSchemaDataType.Array + ) { return true; } diff --git a/web/src/utils/canvas-util.tsx b/web/src/utils/canvas-util.tsx index f59c4c195..d55862d3e 100644 --- a/web/src/utils/canvas-util.tsx +++ b/web/src/utils/canvas-util.tsx @@ -6,7 +6,7 @@ import { import { BaseNode } from '@/interfaces/database/agent'; import { Edge } from '@xyflow/react'; -import { isEmpty } from 'lodash'; +import { get, isEmpty } from 'lodash'; import { ComponentType, ReactNode } from 'react'; export function filterAllUpstreamNodeIds(edges: Edge[], nodeIds: string[]) { @@ -87,3 +87,15 @@ export function buildNodeOutputOptions({ ), })); } + +export function getStructuredDatatype(value: Record | unknown) { + const dataType = get(value, 'type'); + const arrayItemsType = get(value, 'items.type', JsonSchemaDataType.String); + + const compositeDataType = + dataType === JsonSchemaDataType.Array + ? `${dataType}<${arrayItemsType}>` + : dataType; + + return { dataType, compositeDataType }; +}