aura-web/src/pages/AgentEditor/index.tsx

196 lines
6.1 KiB
TypeScript

import { useEffect, useRef, useState } from 'react';
import { Form, Button } from 'antd';
import { useNavigate, useParams } from 'react-router-dom';
import { App as AntApp } from 'antd';
import { FileTextOutlined, SaveOutlined } from '@ant-design/icons';
import SkillEditor from '../../components/SkillEditor';
import ExternalToolEditor from '../../components/ExternalToolEditor';
import { useAgentEditor } from './hooks/useAgentEditor';
import { useIsMobile } from '../../hooks/useIsMobile';
import Header from './components/Header';
import PromptEditor from './components/PromptEditor';
import CapabilitySettings from './components/CapabilitySettings';
import PreviewPane from './components/PreviewPane';
import InitModal from './components/InitModal';
import AvatarSelector from './components/AvatarSelector';
import './AgentEditor.css';
import './styles/agent-editor-capability.css';
import './styles/agent-editor-panels.css';
import './styles/agent-editor-modal.css';
import './styles/agent-editor-h5.css';
export default function AgentEditor() {
const { id } = useParams();
const isNew = !id;
const navigate = useNavigate();
const { message } = AntApp.useApp();
const [form] = Form.useForm();
const [externalToolEditorOpen, setExternalToolEditorOpen] = useState(false);
const [editingPluginId, setEditingPluginId] = useState<string | null>(null);
const {
agent,
saving,
teams,
models,
autoSaveStatus,
initModalOpen,
setInitModalOpen,
selectedAvatar,
setSelectedAvatar,
avatarSelectorOpen,
setAvatarSelectorOpen,
avatarUploading,
agentName,
setAgentName,
skillEditorOpen,
setSkillEditorOpen,
editingSkillId,
setEditingSkillId,
refresh,
handleInitConfirm,
handleSave,
beforeUploadKnowledge,
beforeUploadInitAvatar,
beforeUploadEditAvatar,
handleAvatarSelect,
handleDeleteKnowledge,
handleDeleteSkill,
handleDeletePlugin,
liveAgent,
currentName,
markDirty,
} = useAgentEditor({ id, isNew, form, message, navigate });
const isMobile = useIsMobile();
return (
<>
<div className="agent-editor-shell-container">
<Header
isNew={isNew}
currentName={currentName}
navigate={navigate}
autoSaveStatus={autoSaveStatus}
saving={saving}
onSave={handleSave}
isMobile={isMobile}
/>
<div className={`agent-editor-workbench-container ${isMobile ? 'is-mobile' : 'is-desktop'}`}>
<PromptEditor form={form} markDirty={markDirty} />
<CapabilitySettings
form={form}
agent={agent}
teams={teams}
models={models}
currentName={currentName}
agentName={agentName}
selectedAvatar={agent?.avatar || selectedAvatar}
setAvatarSelectorOpen={setAvatarSelectorOpen}
beforeUploadKnowledge={beforeUploadKnowledge}
onDeleteKnowledge={handleDeleteKnowledge}
onCreateSkill={() => {
setEditingSkillId(null);
setSkillEditorOpen(true);
}}
onEditSkill={(skillId) => {
setEditingSkillId(skillId);
setSkillEditorOpen(true);
}}
onDeleteSkill={handleDeleteSkill}
onCreateExternalTool={() => {
setEditingPluginId(null);
setExternalToolEditorOpen(true);
}}
onEditExternalTool={(pluginId) => {
setEditingPluginId(pluginId);
setExternalToolEditorOpen(true);
}}
onDeleteExternalTool={handleDeletePlugin}
markDirty={markDirty}
isMobile={isMobile}
/>
<PreviewPane liveAgent={liveAgent} agentId={id} />
</div>
{isMobile && (
<div className="agent-editor-mobile-footer-bar">
<span className="agent-editor-footer-status">
{autoSaveStatus === 'saving'
? '正在保存...'
: autoSaveStatus === 'dirty'
? '有未保存更改'
: autoSaveStatus === 'error'
? '保存失败'
: '已保存'}
</span>
<div className="agent-editor-footer-actions">
<Button icon={<FileTextOutlined />} size="middle">
</Button>
<Button
type="primary"
icon={<SaveOutlined />}
loading={saving}
onClick={() => handleSave()}
size="middle"
>
</Button>
</div>
</div>
)}
{!isNew && (
<>
<SkillEditor
open={skillEditorOpen}
agentId={id!}
skillId={editingSkillId}
onClose={() => {
setSkillEditorOpen(false);
setEditingSkillId(null);
}}
onSaved={refresh}
/>
<ExternalToolEditor
open={externalToolEditorOpen}
agentId={id!}
plugin={agent?.plugins?.find((plugin) => plugin.id === editingPluginId)}
onClose={() => {
setExternalToolEditorOpen(false);
setEditingPluginId(null);
}}
onSaved={refresh}
/>
</>
)}
</div>
<InitModal
isMobile={isMobile}
open={initModalOpen}
onCancel={() => navigate('/agents')}
onConfirm={handleInitConfirm}
avatarUploading={avatarUploading}
selectedAvatar={selectedAvatar}
setSelectedAvatar={setSelectedAvatar}
agentName={agentName}
setAgentName={setAgentName}
saving={saving}
beforeUploadInitAvatar={beforeUploadInitAvatar}
/>
<AvatarSelector
open={avatarSelectorOpen}
onCancel={() => setAvatarSelectorOpen(false)}
agent={agent}
avatarUploading={avatarUploading}
beforeUploadEditAvatar={beforeUploadEditAvatar}
onAvatarSelect={handleAvatarSelect}
/>
</>
);
}