### What problem does this PR solve? Feat: Remove the exception comment field from the agent form #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.20.0
| @@ -111,9 +111,7 @@ export const SelectWithSearch = forwardRef< | |||
| > | |||
| {value ? ( | |||
| <span className="flex min-w-0 options-center gap-2"> | |||
| <span className="text-lg leading-none truncate"> | |||
| {selectLabel} | |||
| </span> | |||
| <span className="leading-none truncate">{selectLabel}</span> | |||
| </span> | |||
| ) : ( | |||
| <span className="text-muted-foreground">Select value</span> | |||
| @@ -159,9 +157,7 @@ export const SelectWithSearch = forwardRef< | |||
| disabled={option.disabled} | |||
| onSelect={handleSelect} | |||
| > | |||
| <span className="text-lg leading-none"> | |||
| {option.label} | |||
| </span> | |||
| <span className="leading-none">{option.label}</span> | |||
| {value === option.value && ( | |||
| <CheckIcon size={16} className="ml-auto" /> | |||
| @@ -179,9 +175,7 @@ export const SelectWithSearch = forwardRef< | |||
| disabled={group.disabled} | |||
| onSelect={handleSelect} | |||
| > | |||
| <span className="text-lg leading-none"> | |||
| {group.label} | |||
| </span> | |||
| <span className="leading-none">{group.label}</span> | |||
| {value === group.value && ( | |||
| <CheckIcon size={16} className="ml-auto" /> | |||
| @@ -1317,6 +1317,8 @@ This delimiter is used to split the input text into several text pieces echo of | |||
| file: 'File upload', | |||
| integer: 'Number', | |||
| boolean: 'Boolean', | |||
| goto: 'Fail Branch', | |||
| comment: 'Default Value', | |||
| }, | |||
| llmTools: { | |||
| bad_calculator: { | |||
| @@ -3,6 +3,7 @@ import { IAgentNode } from '@/interfaces/database/flow'; | |||
| import { Handle, NodeProps, Position } from '@xyflow/react'; | |||
| import { get } from 'lodash'; | |||
| import { memo, useMemo } from 'react'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { AgentExceptionMethod, NodeHandleId } from '../../constant'; | |||
| import useGraphStore from '../../store'; | |||
| import { isBottomSubAgent } from '../../utils'; | |||
| @@ -20,6 +21,7 @@ function InnerAgentNode({ | |||
| selected, | |||
| }: NodeProps<IAgentNode>) { | |||
| const edges = useGraphStore((state) => state.edges); | |||
| const { t } = useTranslation(); | |||
| const isHeadAgent = useMemo(() => { | |||
| return !isBottomSubAgent(edges, id); | |||
| @@ -87,9 +89,9 @@ function InnerAgentNode({ | |||
| {(isGotoMethod || | |||
| exceptionMethod === AgentExceptionMethod.Comment) && ( | |||
| <div className="bg-background-card rounded-sm p-1 flex justify-between gap-2"> | |||
| <span className="text-text-sub-title">Abnormal</span> | |||
| <span className="truncate flex-1"> | |||
| {isGotoMethod ? 'Exception branch' : 'Output default value'} | |||
| <span className="text-text-sub-title">On Failure</span> | |||
| <span className="truncate flex-1 text-right"> | |||
| {t(`flow.${exceptionMethod}`)} | |||
| </span> | |||
| </div> | |||
| )} | |||
| @@ -645,15 +645,23 @@ export const initialAgentValues = { | |||
| ...initialLlmBaseValues, | |||
| description: '', | |||
| user_prompt: '', | |||
| sys_prompt: ``, | |||
| sys_prompt: `<role> | |||
| You are {{agent_name}}, an AI assistant specialized in {{domain_or_task}}. | |||
| </role> | |||
| <instructions> | |||
| 1. Understand the user’s request. | |||
| 2. Decompose it into logical subtasks. | |||
| 3. Execute each subtask step by step, reasoning transparently. | |||
| 4. Validate accuracy and consistency. | |||
| 5. Summarize the final result clearly. | |||
| </instructions>`, | |||
| prompts: [{ role: PromptRole.User, content: `{${AgentGlobals.SysQuery}}` }], | |||
| message_history_window_size: 12, | |||
| max_retries: 3, | |||
| delay_after_error: 1, | |||
| visual_files_var: '', | |||
| max_rounds: 5, | |||
| exception_method: null, | |||
| exception_comment: '', | |||
| exception_method: '', | |||
| exception_goto: [], | |||
| exception_default_value: '', | |||
| tools: [], | |||
| @@ -944,5 +952,4 @@ export enum VariableType { | |||
| export enum AgentExceptionMethod { | |||
| Comment = 'comment', | |||
| Goto = 'goto', | |||
| Null = 'null', | |||
| } | |||
| @@ -6,6 +6,7 @@ import { | |||
| } from '@/components/large-model-form-field'; | |||
| import { LlmSettingSchema } from '@/components/llm-setting-items/next'; | |||
| import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item'; | |||
| import { SelectWithSearch } from '@/components/originui/select-with-search'; | |||
| import { | |||
| Form, | |||
| FormControl, | |||
| @@ -14,10 +15,8 @@ import { | |||
| FormLabel, | |||
| } from '@/components/ui/form'; | |||
| import { Input, NumberInput } from '@/components/ui/input'; | |||
| import { RAGFlowSelect } from '@/components/ui/select'; | |||
| import { LlmModelType } from '@/constants/knowledge'; | |||
| import { useFindLlmByUuid } from '@/hooks/use-llm-request'; | |||
| import { buildOptions } from '@/utils/form'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { memo, useEffect, useMemo } from 'react'; | |||
| import { useForm, useWatch } from 'react-hook-form'; | |||
| @@ -42,8 +41,6 @@ import { AgentTools, Agents } from './agent-tools'; | |||
| import { useValues } from './use-values'; | |||
| import { useWatchFormChange } from './use-watch-change'; | |||
| const exceptionMethodOptions = buildOptions(AgentExceptionMethod); | |||
| const FormSchema = z.object({ | |||
| sys_prompt: z.string(), | |||
| description: z.string().optional(), | |||
| @@ -70,8 +67,7 @@ const FormSchema = z.object({ | |||
| delay_after_error: z.coerce.number().optional(), | |||
| visual_files_var: z.string().optional(), | |||
| max_rounds: z.coerce.number().optional(), | |||
| exception_method: z.string().nullable(), | |||
| exception_comment: z.string().optional(), | |||
| exception_method: z.string().optional(), | |||
| exception_goto: z.array(z.string()).optional(), | |||
| exception_default_value: z.string().optional(), | |||
| ...LargeModelFilterFormSchema, | |||
| @@ -87,6 +83,13 @@ function AgentForm({ node }: INextOperatorForm) { | |||
| const defaultValues = useValues(node); | |||
| const ExceptionMethodOptions = Object.values(AgentExceptionMethod).map( | |||
| (x) => ({ | |||
| label: t(`flow.${x}`), | |||
| value: x, | |||
| }), | |||
| ); | |||
| const isSubAgent = useMemo(() => { | |||
| return isBottomSubAgent(edges, node?.id); | |||
| }, [edges, node?.id]); | |||
| @@ -224,38 +227,29 @@ function AgentForm({ node }: INextOperatorForm) { | |||
| <FormItem className="flex-1"> | |||
| <FormLabel>Exception method</FormLabel> | |||
| <FormControl> | |||
| <RAGFlowSelect | |||
| <SelectWithSearch | |||
| {...field} | |||
| options={exceptionMethodOptions} | |||
| options={ExceptionMethodOptions} | |||
| allowClear | |||
| /> | |||
| </FormControl> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| <FormField | |||
| control={form.control} | |||
| name={`exception_default_value`} | |||
| render={({ field }) => ( | |||
| <FormItem className="flex-1"> | |||
| <FormLabel>Exception default value</FormLabel> | |||
| <FormControl> | |||
| <Input {...field} /> | |||
| </FormControl> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| <FormField | |||
| control={form.control} | |||
| name={`exception_comment`} | |||
| render={({ field }) => ( | |||
| <FormItem className="flex-1"> | |||
| <FormLabel>Exception comment</FormLabel> | |||
| <FormControl> | |||
| <Input {...field} /> | |||
| </FormControl> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| {exceptionMethod === AgentExceptionMethod.Comment && ( | |||
| <FormField | |||
| control={form.control} | |||
| name={`exception_default_value`} | |||
| render={({ field }) => ( | |||
| <FormItem className="flex-1"> | |||
| <FormLabel>Exception default value</FormLabel> | |||
| <FormControl> | |||
| <Input {...field} /> | |||
| </FormControl> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| )} | |||
| </FormContainer> | |||
| </Collapse> | |||
| <Output list={outputList}></Output> | |||
| @@ -2,7 +2,7 @@ import { useFetchModelId } from '@/hooks/logic-hooks'; | |||
| import { RAGFlowNodeType } from '@/interfaces/database/flow'; | |||
| import { get, isEmpty } from 'lodash'; | |||
| import { useMemo } from 'react'; | |||
| import { AgentExceptionMethod, initialAgentValues } from '../../constant'; | |||
| import { initialAgentValues } from '../../constant'; | |||
| export function useValues(node?: RAGFlowNodeType) { | |||
| const llmId = useFetchModelId(); | |||
| @@ -26,10 +26,6 @@ export function useValues(node?: RAGFlowNodeType) { | |||
| return { | |||
| ...formData, | |||
| prompts: get(formData, 'prompts.0.content', ''), | |||
| exception_method: | |||
| formData.exception_method === null | |||
| ? AgentExceptionMethod.Null | |||
| : formData.exception_method, | |||
| }; | |||
| }, [defaultValues, node?.data?.form]); | |||
| @@ -1,6 +1,6 @@ | |||
| import { useEffect } from 'react'; | |||
| import { UseFormReturn, useWatch } from 'react-hook-form'; | |||
| import { AgentExceptionMethod, PromptRole } from '../../constant'; | |||
| import { PromptRole } from '../../constant'; | |||
| import useGraphStore from '../../store'; | |||
| export function useWatchFormChange(id?: string, form?: UseFormReturn<any>) { | |||
| @@ -14,10 +14,6 @@ export function useWatchFormChange(id?: string, form?: UseFormReturn<any>) { | |||
| let nextValues: any = { | |||
| ...values, | |||
| prompts: [{ role: PromptRole.User, content: values.prompts }], | |||
| exception_method: | |||
| values.exception_method === AgentExceptionMethod.Null | |||
| ? null | |||
| : values.exception_method, | |||
| }; | |||
| updateNodeForm(id, nextValues); | |||