Feat: Add type card to create agent dialog #9869 (#10025)

### What problem does this PR solve?

Feat: Add type card to create agent dialog #9869
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-09-10 15:56:10 +08:00
committed by GitHub
parent bbe6ed3b90
commit 7d14455fbe
8 changed files with 151 additions and 50 deletions

View File

@ -15,6 +15,7 @@ type RAGFlowFormItemProps = {
tooltip?: ReactNode;
children: ReactNode | ((field: ControllerRenderProps) => ReactNode);
horizontal?: boolean;
required?: boolean;
};
export function RAGFlowFormItem({
@ -23,6 +24,7 @@ export function RAGFlowFormItem({
tooltip,
children,
horizontal = false,
required = false,
}: RAGFlowFormItemProps) {
const form = useFormContext();
return (
@ -35,7 +37,11 @@ export function RAGFlowFormItem({
'flex items-center': horizontal,
})}
>
<FormLabel tooltip={tooltip} className={cn({ 'w-1/4': horizontal })}>
<FormLabel
required={required}
tooltip={tooltip}
className={cn({ 'w-1/4': horizontal })}
>
{label}
</FormLabel>
<FormControl>

View File

@ -38,7 +38,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-colors-background-neutral-standard p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-bg-base p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
className,
)}
{...props}

View File

@ -934,7 +934,7 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s
exceptionMethod: 'Exception method',
maxRounds: 'Max reflection rounds',
delayEfterError: 'Delay after error',
maxRetries: 'Max retries',
maxRetries: 'Max reflection rounds',
advancedSettings: 'Advanced Settings',
addTools: 'Add Tools',
sysPromptDefultValue: `

View File

@ -892,7 +892,7 @@ General实体和关系提取提示来自 GitHub - microsoft/graphrag基于
exceptionMethod: '异常处理方法',
maxRounds: '最大反思轮数',
delayEfterError: '错误后延迟',
maxRetries: '最大重试次数',
maxRetries: '最大反思轮数',
advancedSettings: '高级设置',
addTools: '添加工具',
sysPromptDefultValue: `

View File

@ -27,9 +27,11 @@ export default function AgentTemplates() {
const [selectMenuItem, setSelectMenuItem] = useState<string>(
MenuItemKey.Recommended,
);
useEffect(() => {
setTemplateList(list);
}, [list]);
const {
visible: creatingVisible,
hideModal: hideCreatingModal,

View File

@ -6,16 +6,18 @@ import {
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { IModalProps } from '@/interfaces/common';
import { TagRenameId } from '@/pages/add-knowledge/constant';
import { useTranslation } from 'react-i18next';
import { CreateAgentForm } from './create-agent-form';
import { CreateAgentForm, CreateAgentFormProps } from './create-agent-form';
type CreateAgentDialogProps = CreateAgentFormProps;
export function CreateAgentDialog({
hideModal,
onOk,
loading,
}: IModalProps<any>) {
shouldChooseAgent,
}: CreateAgentDialogProps) {
const { t } = useTranslation();
return (
@ -24,7 +26,11 @@ export function CreateAgentDialog({
<DialogHeader>
<DialogTitle>{t('flow.createGraph')}</DialogTitle>
</DialogHeader>
<CreateAgentForm hideModal={hideModal} onOk={onOk}></CreateAgentForm>
<CreateAgentForm
hideModal={hideModal}
onOk={onOk}
shouldChooseAgent={shouldChooseAgent}
></CreateAgentForm>
<DialogFooter>
<ButtonLoading type="submit" form={TagRenameId} loading={loading}>
{t('common.save')}

View File

@ -4,6 +4,8 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { RAGFlowFormItem } from '@/components/ragflow-form';
import { Card, CardContent } from '@/components/ui/card';
import {
Form,
FormControl,
@ -14,10 +16,76 @@ import {
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { IModalProps } from '@/interfaces/common';
import { cn } from '@/lib/utils';
import { TagRenameId } from '@/pages/add-knowledge/constant';
import { BrainCircuit, Check, Route } from 'lucide-react';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
export type CreateAgentFormProps = IModalProps<any> & {
shouldChooseAgent?: boolean;
};
enum FlowType {
Agent = 'agent',
Flow = 'flow',
}
type FlowTypeCardProps = {
value?: FlowType;
onChange?: (value: FlowType) => void;
};
function FlowTypeCards({ value, onChange }: FlowTypeCardProps) {
const handleChange = useCallback(
(value: FlowType) => () => {
onChange?.(value);
},
[onChange],
);
return (
<section className="flex gap-10">
{Object.values(FlowType).map((val) => {
const isActive = value === val;
return (
<Card
key={val}
className={cn('flex-1 rounded-lg border bg-transparent', {
'border-bg-base': isActive,
'border-border-default': !isActive,
})}
>
<CardContent
onClick={handleChange(val)}
className={cn(
'cursor-pointer p-5 text-text-secondary flex justify-between items-center',
{
'text-text-primary': isActive,
},
)}
>
<div className="flex gap-2">
{val === FlowType.Agent ? (
<BrainCircuit className="size-6" />
) : (
<Route className="size-6" />
)}
<p>{val}</p>
</div>
{isActive && <Check />}
</CardContent>
</Card>
);
})}
</section>
);
}
export function CreateAgentForm({
hideModal,
onOk,
shouldChooseAgent = false,
}: CreateAgentFormProps) {
const { t } = useTranslation();
const FormSchema = z.object({
name: z
@ -28,11 +96,12 @@ export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
.trim(),
tag: z.string().trim().optional(),
description: z.string().trim().optional(),
type: z.nativeEnum(FlowType).optional(),
});
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: { name: '' },
defaultValues: { name: '', type: FlowType.Agent },
});
async function onSubmit(data: z.infer<typeof FormSchema>) {
@ -49,12 +118,17 @@ export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
className="space-y-6"
id={TagRenameId}
>
{shouldChooseAgent && (
<RAGFlowFormItem required name="type" label={t('common.type')}>
<FlowTypeCards></FlowTypeCards>
</RAGFlowFormItem>
)}
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>{t('common.name')}</FormLabel>
<FormLabel required>{t('common.name')}</FormLabel>
<FormControl>
<Input
placeholder={t('common.namePlaceholder')}
@ -66,40 +140,6 @@ export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
</FormItem>
)}
/>
{/* <FormField
control={form.control}
name="tag"
render={({ field }) => (
<FormItem>
<FormLabel>{t('flow.tag')}</FormLabel>
<FormControl>
<Input
placeholder={t('flow.tagPlaceholder')}
{...field}
autoComplete="off"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>{t('flow.description')}</FormLabel>
<FormControl>
<Input
placeholder={t('flow.descriptionPlaceholder')}
{...field}
autoComplete="off"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/> */}
</form>
</Form>
);

View File

@ -1,14 +1,22 @@
import ListFilterBar from '@/components/list-filter-bar';
import { RenameDialog } from '@/components/rename-dialog';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
import { useSetModalState } from '@/hooks/common-hooks';
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { useFetchAgentListByPage } from '@/hooks/use-agent-request';
import { t } from 'i18next';
import { pick } from 'lodash';
import { Plus } from 'lucide-react';
import { Clipboard, ClipboardPlus, FileInput, Plus } from 'lucide-react';
import { useCallback } from 'react';
import { AgentCard } from './agent-card';
import { CreateAgentDialog } from './create-agent-dialog';
import { useRenameAgent } from './use-rename-agent';
export default function Agents() {
@ -25,6 +33,12 @@ export default function Agents() {
showAgentRenameModal,
} = useRenameAgent();
const {
visible: creatingVisible,
hideModal: hideCreatingModal,
showModal: showCreatingModal,
} = useSetModalState();
const handlePageChange = useCallback(
(page: number, pageSize?: number) => {
setPagination({ page, pageSize });
@ -41,10 +55,34 @@ export default function Agents() {
onSearchChange={handleInputChange}
icon="agent"
>
<Button onClick={navigateToAgentTemplates}>
<Plus className="mr-2 h-4 w-4" />
{t('flow.createGraph')}
</Button>
<DropdownMenu>
<DropdownMenuTrigger>
<Button>
<Plus className="mr-2 h-4 w-4" />
{t('flow.createGraph')}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
justifyBetween={false}
onClick={showCreatingModal}
>
<Clipboard />
Create from Blank
</DropdownMenuItem>
<DropdownMenuItem
justifyBetween={false}
onClick={navigateToAgentTemplates}
>
<ClipboardPlus />
Create from Template
</DropdownMenuItem>
<DropdownMenuItem justifyBetween={false}>
<FileInput />
Import json file
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</ListFilterBar>
</div>
<div className="flex-1 overflow-auto">
@ -75,6 +113,15 @@ export default function Agents() {
loading={agentRenameLoading}
></RenameDialog>
)}
{creatingVisible && (
<CreateAgentDialog
loading={false}
visible={creatingVisible}
hideModal={hideCreatingModal}
shouldChooseAgent
onOk={() => {}}
></CreateAgentDialog>
)}
</section>
);
}