### What problem does this PR solve? Feat: Adjust agent mcp style #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.20.0
| @@ -1306,9 +1306,10 @@ This delimiter is used to split the input text into several text pieces echo of | |||
| mcp: { | |||
| export: 'Export', | |||
| import: 'Import', | |||
| addMcp: 'Add MCP', | |||
| url: 'URL', | |||
| serverType: 'Server Type', | |||
| addMCP: 'Add MCP', | |||
| editMCP: 'Edit MCP', | |||
| }, | |||
| }, | |||
| }; | |||
| @@ -15,7 +15,7 @@ import { RAGFlowSelect } from '@/components/ui/select'; | |||
| import { Textarea } from '@/components/ui/textarea'; | |||
| import { buildOptions } from '@/utils/form'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { useMemo } from 'react'; | |||
| import { memo, useMemo } from 'react'; | |||
| import { useForm } from 'react-hook-form'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { z } from 'zod'; | |||
| @@ -68,7 +68,7 @@ const FormSchema = z.object({ | |||
| exception_goto: z.string().optional(), | |||
| }); | |||
| const AgentForm = ({ node }: INextOperatorForm) => { | |||
| function AgentForm({ node }: INextOperatorForm) { | |||
| const { t } = useTranslation(); | |||
| const { edges } = useGraphStore((state) => state); | |||
| @@ -243,6 +243,6 @@ const AgentForm = ({ node }: INextOperatorForm) => { | |||
| </form> | |||
| </Form> | |||
| ); | |||
| }; | |||
| } | |||
| export default AgentForm; | |||
| export default memo(AgentForm); | |||
| @@ -15,6 +15,7 @@ import { FormTooltip } from '@/components/ui/tooltip'; | |||
| import { buildSelectOptions } from '@/utils/component-util'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { Plus } from 'lucide-react'; | |||
| import { memo } from 'react'; | |||
| import { useForm, useWatch } from 'react-hook-form'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { z } from 'zod'; | |||
| @@ -31,7 +32,7 @@ const ModeOptions = buildSelectOptions([ | |||
| AgentDialogueMode.Task, | |||
| ]); | |||
| const BeginForm = ({ node }: INextOperatorForm) => { | |||
| function BeginForm({ node }: INextOperatorForm) { | |||
| const { t } = useTranslation(); | |||
| const values = useValues(node); | |||
| @@ -186,6 +187,6 @@ const BeginForm = ({ node }: INextOperatorForm) => { | |||
| </Form> | |||
| </section> | |||
| ); | |||
| }; | |||
| } | |||
| export default BeginForm; | |||
| export default memo(BeginForm); | |||
| @@ -4,6 +4,7 @@ import { LlmSettingSchema } from '@/components/llm-setting-items/next'; | |||
| import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item'; | |||
| import { Form } from '@/components/ui/form'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { memo } from 'react'; | |||
| import { useForm } from 'react-hook-form'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { z } from 'zod'; | |||
| @@ -13,7 +14,7 @@ import DynamicCategorize from './dynamic-categorize'; | |||
| import { useValues } from './use-values'; | |||
| import { useWatchFormChange } from './use-watch-change'; | |||
| const CategorizeForm = ({ node }: INextOperatorForm) => { | |||
| function CategorizeForm({ node }: INextOperatorForm) { | |||
| const { t } = useTranslation(); | |||
| const values = useValues(node); | |||
| @@ -64,6 +65,6 @@ const CategorizeForm = ({ node }: INextOperatorForm) => { | |||
| </form> | |||
| </Form> | |||
| ); | |||
| }; | |||
| } | |||
| export default CategorizeForm; | |||
| export default memo(CategorizeForm); | |||
| @@ -15,6 +15,7 @@ import { RAGFlowSelect } from '@/components/ui/select'; | |||
| import { ProgrammingLanguage } from '@/constants/agent'; | |||
| import { ICodeForm } from '@/interfaces/database/agent'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { memo } from 'react'; | |||
| import { useForm } from 'react-hook-form'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { buildOutputList } from '../../utils/build-output-list'; | |||
| @@ -40,7 +41,7 @@ const options = [ | |||
| const DynamicFieldName = 'outputs'; | |||
| const CodeForm = ({ node }: INextOperatorForm) => { | |||
| function CodeForm({ node }: INextOperatorForm) { | |||
| const formData = node?.data.form as ICodeForm; | |||
| const { t } = useTranslation(); | |||
| const values = useValues(node); | |||
| @@ -164,6 +165,6 @@ const CodeForm = ({ node }: INextOperatorForm) => { | |||
| </div> | |||
| </Form> | |||
| ); | |||
| }; | |||
| } | |||
| export default CodeForm; | |||
| export default memo(CodeForm); | |||
| @@ -1,7 +1,7 @@ | |||
| import { FormContainer } from '@/components/form-container'; | |||
| import { Form } from '@/components/ui/form'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { useMemo } from 'react'; | |||
| import { memo, useMemo } from 'react'; | |||
| import { useForm, useWatch } from 'react-hook-form'; | |||
| import { z } from 'zod'; | |||
| import { VariableType } from '../../constant'; | |||
| @@ -18,7 +18,7 @@ const FormSchema = z.object({ | |||
| outputs: z.array(z.object({ name: z.string(), value: z.any() })).optional(), | |||
| }); | |||
| const IterationForm = ({ node }: INextOperatorForm) => { | |||
| function IterationForm({ node }: INextOperatorForm) { | |||
| const defaultValues = useValues(node); | |||
| const form = useForm({ | |||
| @@ -56,6 +56,6 @@ const IterationForm = ({ node }: INextOperatorForm) => { | |||
| </form> | |||
| </Form> | |||
| ); | |||
| }; | |||
| } | |||
| export default IterationForm; | |||
| export default memo(IterationForm); | |||
| @@ -1,4 +1,5 @@ | |||
| import { Output, OutputType } from '@/pages/agent/form/components/output'; | |||
| import { memo } from 'react'; | |||
| import { initialIterationStartValues } from '../../constant'; | |||
| const outputs = initialIterationStartValues.outputs; | |||
| @@ -11,12 +12,12 @@ const outputList = Object.entries(outputs).reduce<OutputType[]>( | |||
| }, | |||
| [], | |||
| ); | |||
| const IterationStartForm = () => { | |||
| function IterationStartForm() { | |||
| return ( | |||
| <section className="space-y-6 p-4"> | |||
| <Output list={outputList}></Output> | |||
| </section> | |||
| ); | |||
| }; | |||
| } | |||
| export default IterationStartForm; | |||
| export default memo(IterationStartForm); | |||
| @@ -10,6 +10,7 @@ import { | |||
| } from '@/components/ui/form'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { X } from 'lucide-react'; | |||
| import { memo } from 'react'; | |||
| import { useFieldArray, useForm } from 'react-hook-form'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { z } from 'zod'; | |||
| @@ -18,7 +19,7 @@ import { PromptEditor } from '../components/prompt-editor'; | |||
| import { useValues } from './use-values'; | |||
| import { useWatchFormChange } from './use-watch-change'; | |||
| const MessageForm = ({ node }: INextOperatorForm) => { | |||
| function MessageForm({ node }: INextOperatorForm) { | |||
| const { t } = useTranslation(); | |||
| const values = useValues(node); | |||
| @@ -100,6 +101,6 @@ const MessageForm = ({ node }: INextOperatorForm) => { | |||
| </form> | |||
| </Form> | |||
| ); | |||
| }; | |||
| } | |||
| export default MessageForm; | |||
| export default memo(MessageForm); | |||
| @@ -13,7 +13,7 @@ import { | |||
| } from '@/components/ui/form'; | |||
| import { Textarea } from '@/components/ui/textarea'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { useMemo } from 'react'; | |||
| import { memo, useMemo } from 'react'; | |||
| import { useForm, useFormContext } from 'react-hook-form'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { z } from 'zod'; | |||
| @@ -67,7 +67,7 @@ export function EmptyResponseField() { | |||
| ); | |||
| } | |||
| const RetrievalForm = ({ node }: INextOperatorForm) => { | |||
| function RetrievalForm({ node }: INextOperatorForm) { | |||
| const outputList = useMemo(() => { | |||
| return [ | |||
| { | |||
| @@ -111,6 +111,6 @@ const RetrievalForm = ({ node }: INextOperatorForm) => { | |||
| </form> | |||
| </Form> | |||
| ); | |||
| }; | |||
| } | |||
| export default RetrievalForm; | |||
| export default memo(RetrievalForm); | |||
| @@ -12,7 +12,7 @@ import { RAGFlowSelect } from '@/components/ui/select'; | |||
| import { Switch } from '@/components/ui/switch'; | |||
| import { buildOptions } from '@/utils/form'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { useMemo } from 'react'; | |||
| import { memo, useMemo } from 'react'; | |||
| import { useForm } from 'react-hook-form'; | |||
| import { z } from 'zod'; | |||
| import { | |||
| @@ -27,7 +27,7 @@ import { DynamicDomain } from './dynamic-domain'; | |||
| import { useValues } from './use-values'; | |||
| import { useWatchFormChange } from './use-watch-change'; | |||
| const TavilyForm = ({ node }: INextOperatorForm) => { | |||
| function TavilyForm({ node }: INextOperatorForm) { | |||
| const values = useValues(node); | |||
| const FormSchema = z.object({ | |||
| @@ -227,6 +227,6 @@ const TavilyForm = ({ node }: INextOperatorForm) => { | |||
| </div> | |||
| </Form> | |||
| ); | |||
| }; | |||
| } | |||
| export default TavilyForm; | |||
| export default memo(TavilyForm); | |||
| @@ -1,10 +1,11 @@ | |||
| import { memo } from 'react'; | |||
| import useGraphStore from '../../store'; | |||
| import { ToolFormConfigMap } from './constant'; | |||
| import MCPForm from './mcp-form'; | |||
| const EmptyContent = () => <div></div>; | |||
| const ToolForm = () => { | |||
| function ToolForm() { | |||
| const clickedToolId = useGraphStore((state) => state.clickedToolId); | |||
| const ToolForm = | |||
| @@ -17,6 +18,6 @@ const ToolForm = () => { | |||
| <ToolForm key={clickedToolId}></ToolForm> | |||
| </section> | |||
| ); | |||
| }; | |||
| } | |||
| export default ToolForm; | |||
| export default memo(ToolForm); | |||
| @@ -1,4 +1,4 @@ | |||
| import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; | |||
| import { Card, CardContent, CardHeader } from '@/components/ui/card'; | |||
| import { Checkbox } from '@/components/ui/checkbox'; | |||
| import { | |||
| Form, | |||
| @@ -42,9 +42,9 @@ function MCPForm() { | |||
| > | |||
| <Card className="bg-background-highlight p-5"> | |||
| <CardHeader className="p-0 pb-3"> | |||
| <CardTitle>{data.name}</CardTitle> | |||
| <div>{data.name}</div> | |||
| </CardHeader> | |||
| <CardContent className="p-0"> | |||
| <CardContent className="p-0 text-sm"> | |||
| <span className="pr-2"> URL:</span> | |||
| <a href={data.url} className="text-background-checked"> | |||
| {data.url} | |||
| @@ -71,7 +71,7 @@ function MCPForm() { | |||
| <FormControl> | |||
| <MCPCard key={name} data={{ ...mcp, name }}> | |||
| <Checkbox | |||
| className="translate-y-1" | |||
| className="translate-y-0.5" | |||
| checked={field.value?.includes(name)} | |||
| onCheckedChange={(checked) => { | |||
| return checked | |||
| @@ -1,4 +1,4 @@ | |||
| import { Card, CardContent, CardTitle } from '@/components/ui/card'; | |||
| import { Card, CardContent } from '@/components/ui/card'; | |||
| import { IMCPTool } from '@/interfaces/database/mcp'; | |||
| import { PropsWithChildren } from 'react'; | |||
| @@ -11,8 +11,8 @@ export function MCPCard({ | |||
| <CardContent className="p-0 flex gap-3"> | |||
| {children} | |||
| <section> | |||
| <CardTitle className="pb-3">{data.name}</CardTitle> | |||
| <p>{data.description}</p> | |||
| <div className="pb-3 text-sm">{data.name}</div> | |||
| <p className="text-text-sub-title text-xs">{data.description}</p> | |||
| </section> | |||
| </CardContent> | |||
| </Card> | |||
| @@ -13,6 +13,7 @@ import { Textarea } from '@/components/ui/textarea'; | |||
| import { FormTooltip } from '@/components/ui/tooltip'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { Plus } from 'lucide-react'; | |||
| import { memo } from 'react'; | |||
| import { useForm, useWatch } from 'react-hook-form'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { z } from 'zod'; | |||
| @@ -23,7 +24,7 @@ import { useEditQueryRecord } from '../begin-form/use-edit-query'; | |||
| import { useValues } from './use-values'; | |||
| import { useWatchFormChange } from './use-watch-change'; | |||
| const UserFillUpForm = ({ node }: INextOperatorForm) => { | |||
| function UserFillUpForm({ node }: INextOperatorForm) { | |||
| const { t } = useTranslation(); | |||
| const values = useValues(node); | |||
| @@ -150,6 +151,6 @@ const UserFillUpForm = ({ node }: INextOperatorForm) => { | |||
| </Form> | |||
| </section> | |||
| ); | |||
| }; | |||
| } | |||
| export default UserFillUpForm; | |||
| export default memo(UserFillUpForm); | |||
| @@ -1,77 +0,0 @@ | |||
| import Editor, { loader } from '@monaco-editor/react'; | |||
| import { INextOperatorForm } from '../../interface'; | |||
| import { | |||
| Form, | |||
| FormControl, | |||
| FormField, | |||
| FormItem, | |||
| FormLabel, | |||
| FormMessage, | |||
| } from '@/components/ui/form'; | |||
| import { RAGFlowSelect } from '@/components/ui/select'; | |||
| import { ProgrammingLanguage } from '@/constants/agent'; | |||
| import { ICodeForm } from '@/interfaces/database/flow'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| loader.config({ paths: { vs: '/vs' } }); | |||
| const options = [ | |||
| ProgrammingLanguage.Python, | |||
| ProgrammingLanguage.Javascript, | |||
| ].map((x) => ({ value: x, label: x })); | |||
| const CodeForm = ({ form, node }: INextOperatorForm) => { | |||
| const formData = node?.data.form as ICodeForm; | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <Form {...form}> | |||
| <form | |||
| className="p-5 space-y-5" | |||
| onSubmit={(e) => { | |||
| e.preventDefault(); | |||
| }} | |||
| > | |||
| <FormField | |||
| control={form.control} | |||
| name="script" | |||
| render={({ field }) => ( | |||
| <FormItem> | |||
| <FormLabel className="flex items-center justify-between"> | |||
| Code | |||
| <FormField | |||
| control={form.control} | |||
| name="lang" | |||
| render={({ field }) => ( | |||
| <FormItem> | |||
| <FormControl> | |||
| <RAGFlowSelect {...field} options={options} /> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| </FormLabel> | |||
| <FormControl> | |||
| <Editor | |||
| height={300} | |||
| theme="vs-dark" | |||
| language={formData.lang} | |||
| options={{ | |||
| minimap: { enabled: false }, | |||
| automaticLayout: true, | |||
| }} | |||
| {...field} | |||
| /> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| </form> | |||
| </Form> | |||
| ); | |||
| }; | |||
| export default CodeForm; | |||
| @@ -110,7 +110,7 @@ export function EditMcpDialog({ | |||
| <Dialog open onOpenChange={hideModal}> | |||
| <DialogContent> | |||
| <DialogHeader> | |||
| <DialogTitle>{t('common.edit')}</DialogTitle> | |||
| <DialogTitle>{id ? t('mcp.editMCP') : t('mcp.addMCP')}</DialogTitle> | |||
| </DialogHeader> | |||
| <EditMcpForm | |||
| onOk={handleOk} | |||
| @@ -48,7 +48,7 @@ export default function McpServer() { | |||
| <Import /> {t('mcp.import')} | |||
| </Button> | |||
| <Button onClick={showEditModal('')}> | |||
| <Plus /> {t('mcp.addMcp')} | |||
| <Plus /> {t('mcp.addMCP')} | |||
| </Button> | |||
| </div> | |||
| </section> | |||