Feat: The agent operator and message operator can only select string variables as prompt words. #10427 (#11054)

### What problem does this PR solve?

Feat: The agent operator and message operator can only select string
variables as prompt words. #10427
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-11-06 13:58:20 +08:00
committed by GitHub
parent f581a1c4e5
commit d469ae6d50
7 changed files with 48 additions and 21 deletions

View File

@ -58,6 +58,7 @@ function InnerToolNode({
const mcp = x as unknown as IAgentForm['mcp'][number]; const mcp = x as unknown as IAgentForm['mcp'][number];
return ( return (
<ToolCard <ToolCard
key={mcp.mcp_id}
onClick={handleClick(mcp.mcp_id)} onClick={handleClick(mcp.mcp_id)}
className="cursor-pointer" className="cursor-pointer"
data-tool={x.mcp_id} data-tool={x.mcp_id}
@ -70,6 +71,7 @@ function InnerToolNode({
const tool = x as unknown as IAgentForm['tools'][number]; const tool = x as unknown as IAgentForm['tools'][number];
return ( return (
<ToolCard <ToolCard
key={tool.component_name}
onClick={handleClick(tool.component_name)} onClick={handleClick(tool.component_name)}
className="cursor-pointer" className="cursor-pointer"
data-tool={tool.component_name} data-tool={tool.component_name}

View File

@ -26,6 +26,7 @@ import { useTranslation } from 'react-i18next';
import { z } from 'zod'; import { z } from 'zod';
import { import {
AgentExceptionMethod, AgentExceptionMethod,
JsonSchemaDataType,
NodeHandleId, NodeHandleId,
VariableType, VariableType,
initialAgentValues, initialAgentValues,
@ -157,6 +158,7 @@ function AgentForm({ node }: INextOperatorForm) {
placeholder={t('flow.messagePlaceholder')} placeholder={t('flow.messagePlaceholder')}
showToolbar={true} showToolbar={true}
extraOptions={extraOptions} extraOptions={extraOptions}
types={[JsonSchemaDataType.String]}
></PromptEditor> ></PromptEditor>
</FormControl> </FormControl>
</FormItem> </FormItem>
@ -174,6 +176,7 @@ function AgentForm({ node }: INextOperatorForm) {
<PromptEditor <PromptEditor
{...field} {...field}
showToolbar={true} showToolbar={true}
types={[JsonSchemaDataType.String]}
></PromptEditor> ></PromptEditor>
</section> </section>
</FormControl> </FormControl>

View File

@ -21,6 +21,7 @@ import {
TooltipTrigger, TooltipTrigger,
} from '@/components/ui/tooltip'; } from '@/components/ui/tooltip';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { JsonSchemaDataType } from '@/pages/agent/constant';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { Variable } from 'lucide-react'; import { Variable } from 'lucide-react';
import { ReactNode, useCallback, useState } from 'react'; import { ReactNode, useCallback, useState } from 'react';
@ -54,6 +55,7 @@ type IProps = {
value?: string; value?: string;
onChange?: (value?: string) => void; onChange?: (value?: string) => void;
placeholder?: ReactNode; placeholder?: ReactNode;
types?: JsonSchemaDataType[];
} & PromptContentProps & } & PromptContentProps &
Pick<VariablePickerMenuPluginProps, 'extraOptions' | 'baseOptions'>; Pick<VariablePickerMenuPluginProps, 'extraOptions' | 'baseOptions'>;
@ -127,6 +129,7 @@ export function PromptEditor({
multiLine = true, multiLine = true,
extraOptions, extraOptions,
baseOptions, baseOptions,
types,
}: IProps) { }: IProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const initialConfig: InitialConfigType = { const initialConfig: InitialConfigType = {
@ -179,6 +182,7 @@ export function PromptEditor({
value={value} value={value}
extraOptions={extraOptions} extraOptions={extraOptions}
baseOptions={baseOptions} baseOptions={baseOptions}
types={types}
></VariablePickerMenuPlugin> ></VariablePickerMenuPlugin>
<PasteHandlerPlugin /> <PasteHandlerPlugin />
<VariableOnChangePlugin <VariableOnChangePlugin

View File

@ -30,11 +30,12 @@ import * as ReactDOM from 'react-dom';
import { $createVariableNode } from './variable-node'; import { $createVariableNode } from './variable-node';
import { JsonSchemaDataType } from '@/pages/agent/constant';
import { import {
useFindAgentStructuredOutputLabel, useFindAgentStructuredOutputLabel,
useShowSecondaryMenu, useShowSecondaryMenu,
} from '@/pages/agent/hooks/use-build-structured-output'; } from '@/pages/agent/hooks/use-build-structured-output';
import { useBuildQueryVariableOptions } from '@/pages/agent/hooks/use-get-begin-query'; import { useFilterQueryVariableOptionsByTypes } from '@/pages/agent/hooks/use-get-begin-query';
import { PromptIdentity } from '../../agent-form/use-build-prompt-options'; import { PromptIdentity } from '../../agent-form/use-build-prompt-options';
import { StructuredOutputSecondaryMenu } from '../structured-output-secondary-menu'; import { StructuredOutputSecondaryMenu } from '../structured-output-secondary-menu';
import { ProgrammaticTag } from './constant'; import { ProgrammaticTag } from './constant';
@ -80,9 +81,11 @@ function VariablePickerMenuItem({
index, index,
option, option,
selectOptionAndCleanUp, selectOptionAndCleanUp,
types,
}: { }: {
index: number; index: number;
option: VariableOption; option: VariableOption;
types?: JsonSchemaDataType[];
selectOptionAndCleanUp: ( selectOptionAndCleanUp: (
option: VariableOption | VariableInnerOption, option: VariableOption | VariableInnerOption,
) => void; ) => void;
@ -108,6 +111,7 @@ function VariablePickerMenuItem({
<StructuredOutputSecondaryMenu <StructuredOutputSecondaryMenu
key={x.value} key={x.value}
data={x} data={x}
types={types}
click={(y) => click={(y) =>
selectOptionAndCleanUp({ selectOptionAndCleanUp({
...x, ...x,
@ -149,11 +153,13 @@ export type VariablePickerMenuPluginProps = {
value?: string; value?: string;
extraOptions?: VariablePickerMenuOptionType[]; extraOptions?: VariablePickerMenuOptionType[];
baseOptions?: VariablePickerMenuOptionType[]; baseOptions?: VariablePickerMenuOptionType[];
types?: JsonSchemaDataType[];
}; };
export default function VariablePickerMenuPlugin({ export default function VariablePickerMenuPlugin({
value, value,
extraOptions, extraOptions,
baseOptions, baseOptions,
types,
}: VariablePickerMenuPluginProps): JSX.Element { }: VariablePickerMenuPluginProps): JSX.Element {
const [editor] = useLexicalComposerContext(); const [editor] = useLexicalComposerContext();
@ -180,7 +186,7 @@ export default function VariablePickerMenuPlugin({
const [queryString, setQueryString] = React.useState<string | null>(''); const [queryString, setQueryString] = React.useState<string | null>('');
let options = useBuildQueryVariableOptions(); let options = useFilterQueryVariableOptionsByTypes(types);
if (baseOptions) { if (baseOptions) {
options = baseOptions as typeof options; options = baseOptions as typeof options;
@ -379,6 +385,7 @@ export default function VariablePickerMenuPlugin({
index={i} index={i}
key={option.key} key={option.key}
option={option} option={option}
types={types}
selectOptionAndCleanUp={selectOptionAndCleanUp} selectOptionAndCleanUp={selectOptionAndCleanUp}
/> />
))} ))}

View File

@ -5,12 +5,11 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from '@/components/ui/form'; } from '@/components/ui/form';
import { isEmpty, toLower } from 'lodash'; import { ReactNode } from 'react';
import { ReactNode, useMemo } from 'react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { JsonSchemaDataType } from '../../constant'; import { JsonSchemaDataType } from '../../constant';
import { useBuildQueryVariableOptions } from '../../hooks/use-get-begin-query'; import { useFilterQueryVariableOptionsByTypes } from '../../hooks/use-get-begin-query';
import { GroupedSelectWithSecondaryMenu } from './select-with-secondary-menu'; import { GroupedSelectWithSecondaryMenu } from './select-with-secondary-menu';
type QueryVariableProps = { type QueryVariableProps = {
@ -31,22 +30,7 @@ export function QueryVariable({
const { t } = useTranslation(); const { t } = useTranslation();
const form = useFormContext(); const form = useFormContext();
const nextOptions = useBuildQueryVariableOptions(); const finalOptions = useFilterQueryVariableOptionsByTypes(types);
const finalOptions = useMemo(() => {
return !isEmpty(types)
? nextOptions.map((x) => {
return {
...x,
options: x.options.filter(
(y) =>
types?.some((x) => toLower(y.type).includes(x)) ||
y.type === undefined, // agent structured output
),
};
})
: nextOptions;
}, [nextOptions, types]);
return ( return (
<FormField <FormField

View File

@ -14,6 +14,7 @@ import { memo } from 'react';
import { useFieldArray, useForm } from 'react-hook-form'; import { useFieldArray, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { z } from 'zod'; import { z } from 'zod';
import { JsonSchemaDataType } from '../../constant';
import { INextOperatorForm } from '../../interface'; import { INextOperatorForm } from '../../interface';
import { FormWrapper } from '../components/form-wrapper'; import { FormWrapper } from '../components/form-wrapper';
import { PromptEditor } from '../components/prompt-editor'; import { PromptEditor } from '../components/prompt-editor';
@ -66,6 +67,7 @@ function MessageForm({ node }: INextOperatorForm) {
<PromptEditor <PromptEditor
{...field} {...field}
placeholder={t('flow.messagePlaceholder')} placeholder={t('flow.messagePlaceholder')}
types={[JsonSchemaDataType.String]}
></PromptEditor> ></PromptEditor>
</FormControl> </FormControl>
</FormItem> </FormItem>

View File

@ -4,12 +4,14 @@ import { RAGFlowNodeType } from '@/interfaces/database/flow';
import { buildNodeOutputOptions } from '@/utils/canvas-util'; import { buildNodeOutputOptions } 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 get from 'lodash/get'; import get from 'lodash/get';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { import {
AgentDialogueMode, AgentDialogueMode,
BeginId, BeginId,
BeginQueryType, BeginQueryType,
JsonSchemaDataType,
Operator, Operator,
VariableType, VariableType,
} from '../constant'; } from '../constant';
@ -171,6 +173,29 @@ export function useBuildQueryVariableOptions(n?: RAGFlowNodeType) {
return nextOptions; return nextOptions;
} }
export function useFilterQueryVariableOptionsByTypes(
types?: JsonSchemaDataType[],
) {
const nextOptions = useBuildQueryVariableOptions();
const filteredOptions = useMemo(() => {
return !isEmpty(types)
? nextOptions.map((x) => {
return {
...x,
options: x.options.filter(
(y) =>
types?.some((x) => toLower(y.type).includes(x)) ||
y.type === undefined, // agent structured output
),
};
})
: nextOptions;
}, [nextOptions, types]);
return filteredOptions;
}
export function useBuildComponentIdOptions(nodeId?: string, parentId?: string) { export function useBuildComponentIdOptions(nodeId?: string, parentId?: string) {
const nodes = useGraphStore((state) => state.nodes); const nodes = useGraphStore((state) => state.nodes);