123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- import { addApp, apiInterceptors, getAgents, getResourceType, getTeamMode, updateApp } from '@/client/api';
- import { AgentParams, CreateAppParams, IAgent as IAgentParams, IDetail } from '@/types/app';
- import { IFlow } from '@/types/flow';
- import type { TabsProps } from 'antd';
- import { Dropdown, Form, Input, Modal, Select, Space, Spin, Tabs } from 'antd';
- import React, { useEffect, useState } from 'react';
- import { useTranslation } from 'react-i18next';
- import AddIcon from '../icons/add-icon';
- import AgentPanel from './agent-panel';
- import DagLayout from './dag-layout';
- type TargetKey = string;
- type FieldType = {
- app_name: string;
- app_describe: string;
- language: string;
- team_mode: string;
- };
- type IAgent = {
- label: string;
- children?: React.ReactNode;
- onClick?: () => void;
- key: number | string;
- };
- interface IProps {
- handleCancel: () => void;
- open: boolean;
- updateApps: () => void;
- type: string;
- app?: any;
- }
- type TeamModals = 'awel_layout' | 'singe_agent' | 'auto_plan';
- export default function AppModal(props: IProps) {
- const { handleCancel, open, updateApps, type, app } = props;
- const { t } = useTranslation();
- const [spinning, setSpinning] = useState<boolean>(false);
- const [activeKey, setActiveKey] = useState<string>();
- const [teamModal, setTeamModal] = useState<{ label: string; value: string }[]>();
- const [agents, setAgents] = useState<TabsProps['items']>([]);
- const [dropItems, setDropItems] = useState<IAgent[]>([]);
- const [details, setDetails] = useState<IDetail[]>([...(app?.details || [])]);
- const [flow, setFlow] = useState<IFlow>();
- const [resourceTypes, setResourceTypes] = useState<string[]>();
- const [curTeamModal, setCurTeamModal] = useState<TeamModals>(app.team_modal || 'auto_plan');
- const [form] = Form.useForm();
- const languageOptions = [
- { value: 'zh', label: t('Chinese') },
- { value: 'en', label: t('English') },
- ];
- const onChange = (newActiveKey: string) => {
- setActiveKey(newActiveKey);
- };
- const createApp = async (app: CreateAppParams) => {
- await apiInterceptors(type === 'add' ? addApp(app) : updateApp(app));
- await updateApps();
- };
- const initApp = async () => {
- const appDetails = app.details;
- const [_, resourceType] = await apiInterceptors(getResourceType());
- if (appDetails?.length > 0) {
- setAgents(
- appDetails?.map((item: AgentParams) => {
- return {
- label: item?.agent_name,
- children: (
- <AgentPanel
- editResources={type === 'edit' && item.resources}
- detail={{
- key: item?.agent_name,
- llm_strategy: item?.llm_strategy,
- agent_name: item?.agent_name,
- prompt_template: item?.prompt_template,
- llm_strategy_value: item?.llm_strategy_value,
- }}
- updateDetailsByAgentKey={updateDetailsByAgentKey}
- resourceTypes={resourceType}
- />
- ),
- key: item?.agent_name,
- };
- }),
- );
- }
- };
- const fetchTeamModal = async () => {
- const [_, data] = await apiInterceptors(getTeamMode());
- if (!data) return null;
- const teamModalOptions = data.map(item => {
- return { value: item, label: item };
- });
- setTeamModal(teamModalOptions);
- };
- const fetchAgent = async () => {
- const [_, data] = await apiInterceptors(getAgents());
- if (!data) {
- return null;
- }
- setDropItems(
- data
- .map(agent => {
- return {
- label: agent.name,
- key: agent.name,
- onClick: () => {
- add(agent);
- },
- agent,
- };
- })
- .filter(item => {
- if (!app.details || app.details?.length === 0) {
- return item;
- }
- return app?.details?.every((detail: AgentParams) => detail.agent_name !== item.label);
- }),
- );
- };
- const handleFlowsChange = (data: IFlow) => {
- setFlow(data);
- };
- const fetchResourceType = async () => {
- const [_, data] = await apiInterceptors(getResourceType());
- if (data) {
- setResourceTypes(data);
- }
- };
- useEffect(() => {
- fetchTeamModal();
- fetchAgent();
- fetchResourceType();
- }, []);
- useEffect(() => {
- type === 'edit' && initApp();
- }, [resourceTypes]);
- useEffect(() => {
- setCurTeamModal(app.team_mode || 'auto_plan');
- }, [app]);
- const updateDetailsByAgentKey = (key: string, data: IDetail) => {
- setDetails((details: IDetail[]) => {
- return details.map((detail: IDetail) => {
- return key === (detail.agent_name || detail.key) ? data : detail;
- });
- });
- };
- const add = async (tabBar: IAgentParams) => {
- const newActiveKey = tabBar.name;
- const [_, data] = await apiInterceptors(getResourceType());
- setActiveKey(newActiveKey);
- setDetails((details: IDetail[]) => {
- return [...details, { key: newActiveKey, name: '', llm_strategy: 'priority' }];
- });
- setAgents((items: any) => {
- return [
- ...items,
- {
- label: newActiveKey,
- children: (
- <AgentPanel
- detail={{
- key: newActiveKey,
- llm_strategy: 'default',
- agent_name: newActiveKey,
- prompt_template: '',
- llm_strategy_value: null,
- }}
- updateDetailsByAgentKey={updateDetailsByAgentKey}
- resourceTypes={data}
- />
- ),
- key: newActiveKey,
- },
- ];
- });
- setDropItems(items => {
- return items.filter(item => item.key !== tabBar.name);
- });
- };
- const remove = (targetKey: TargetKey) => {
- let newActiveKey = activeKey;
- let lastIndex = -1;
- if (!agents) {
- return null;
- }
- agents.forEach((item, i) => {
- if (item.key === targetKey) {
- lastIndex = i - 1;
- }
- });
- const newPanes = agents.filter(item => item.key !== targetKey);
- if (newPanes.length && newActiveKey === targetKey) {
- if (lastIndex >= 0) {
- newActiveKey = newPanes[lastIndex].key;
- } else {
- newActiveKey = newPanes[0].key;
- }
- }
- setDetails((details: IDetail[]) => {
- return details?.filter((detail: any) => {
- return (detail.agent_name || detail.key) !== targetKey;
- });
- });
- setAgents(newPanes);
- setActiveKey(newActiveKey);
- setDropItems((items: any) => {
- return [
- ...items,
- {
- label: targetKey,
- key: targetKey,
- onClick: () => {
- add({ name: targetKey, describe: '', system_message: '' });
- },
- },
- ];
- });
- };
- const onEdit = (targetKey: any, action: 'add' | 'remove') => {
- if (action === 'add') {
- // add();
- } else {
- remove(targetKey);
- }
- };
- const handleSubmit = async () => {
- const isValidate = await form.validateFields();
- if (!isValidate) {
- return;
- }
- setSpinning(true);
- const data = {
- ...form.getFieldsValue(),
- };
- if (type === 'edit') {
- data.app_code = app.app_code;
- }
- if (data.team_mode !== 'awel_layout') {
- data.details = details;
- } else {
- const tempFlow = { ...flow };
- delete tempFlow.flow_data;
- data.team_context = tempFlow;
- }
- try {
- await createApp(data);
- } catch {
- return;
- }
- setSpinning(false);
- handleCancel();
- };
- const handleTeamModalChange = (value: TeamModals) => {
- setCurTeamModal(value);
- };
- const renderAddIcon = () => {
- return (
- <Dropdown menu={{ items: dropItems }} trigger={['click']}>
- <a className='h-8 flex items-center' onClick={e => e.preventDefault()}>
- <Space>
- <AddIcon />
- </Space>
- </a>
- </Dropdown>
- );
- };
- return (
- <div>
- <Modal
- okText={t('Submit')}
- title={type === 'edit' ? 'edit application' : 'add application'}
- open={open}
- width={'65%'}
- onCancel={handleCancel}
- onOk={handleSubmit}
- destroyOnClose={true}
- >
- <Spin spinning={spinning}>
- <Form
- form={form}
- preserve={false}
- size='large'
- className='mt-4 max-h-[70vh] overflow-auto h-[90vh]'
- layout='horizontal'
- labelAlign='left'
- labelCol={{ span: 4 }}
- initialValues={{
- app_name: app.app_name,
- app_describe: app.app_describe,
- language: app.language || languageOptions[0].value,
- team_mode: app.team_mode || 'auto_plan',
- }}
- autoComplete='off'
- onFinish={handleSubmit}
- >
- <Form.Item<FieldType>
- label={'App Name'}
- name='app_name'
- rules={[{ required: true, message: t('Please_input_the_name') }]}
- >
- <Input placeholder={t('Please_input_the_name')} />
- </Form.Item>
- <Form.Item<FieldType>
- label={t('Description')}
- name='app_describe'
- rules={[{ required: true, message: t('Please_input_the_description') }]}
- >
- <Input.TextArea rows={3} placeholder={t('Please_input_the_description')} />
- </Form.Item>
- <div className='flex w-full'>
- <Form.Item<FieldType>
- labelCol={{ span: 7 }}
- label={t('language')}
- name='language'
- className='w-1/2'
- rules={[{ required: true }]}
- >
- <Select className='w-2/3 ml-4' placeholder={t('language_select_tips')} options={languageOptions} />
- </Form.Item>
- <Form.Item<FieldType>
- label={t('team_modal')}
- name='team_mode'
- className='w-1/2'
- labelCol={{ span: 6 }}
- rules={[{ required: true }]}
- >
- <Select
- defaultValue={app.team_mode || 'auto_plan'}
- className='ml-4 w-72'
- onChange={handleTeamModalChange}
- placeholder={t('Please_input_the_work_modal')}
- options={teamModal}
- />
- </Form.Item>
- </div>
- {curTeamModal !== 'awel_layout' ? (
- <>
- <div className='mb-5'>Agents</div>
- <Tabs
- addIcon={renderAddIcon()}
- type='editable-card'
- onChange={onChange}
- activeKey={activeKey}
- onEdit={onEdit}
- items={agents}
- />
- </>
- ) : (
- <DagLayout onFlowsChange={handleFlowsChange} teamContext={app.team_context} />
- )}
- </Form>
- </Spin>
- </Modal>
- </div>
- );
- }
|