feat: 支持外部工具集快速复制并自动进入编辑状态

main
sp mac bookpro 2605 2026-07-22 13:56:56 +08:00
parent b5d40e876b
commit 16051c1f7a
5 changed files with 60 additions and 2 deletions

View File

@ -5,7 +5,7 @@ alwaysApply: true
## 核心规则 ## 核心规则
1. **提交每次修改** — 每次任务执行后默认提交修改代码到远程仓库或者用户说“提交代码”执行git commit 并且要把commit 信息展示出来。默认是全部本地修改都提交,包括不是本次修改的也提交, 不需要提问用户确认。commit 信息你需要总结本次修改内容,不能是代码。例如:“修复登录页面的错误提示”.最后一定要执行 git push 推送到远程仓库。默认直接提交当前分支包括main分支。 1. **提交每次修改** — 每次任务执行后默认提交修改代码到远程仓库或者用户说“提交代码”执行git commit 并且要把commit 信息展示出来。默认是全部本地修改都提交,包括不是本次修改的也提交, 不需要提问用户确认。commit 信息你需要总结本次修改内容,不能是代码。例如:“修复登录页面的错误提示”.最后一定要执行 git push 推送到远程仓库。默认直接提交当前分支包括main分支。
2. **方案性内容** - 当用户需求,如果是方案性内容,你首先要评估,有没有更好的方案,而不是执行。更好的方案,你可以搜索类似阿里、字节等大厂的方案来参考并给出建议。 2. **方案性内容** - 当用户需求,如果是方案性内容,你首先要评估,有没有更好的方案,而不是执行。更好的方案,你可以搜索类似anthropic、openai、google、meta、阿里、字节等大厂的方案来参考并给出建议。优先参考anthropic、openai、google的方案。如果当前项目方案或者设计明确不合理应该强烈建议修正方案。如果是复杂的修改可以给出短期和中期修正方案。尽可能都是短期内直接修正避免问题遗留。
3. **代码修改** - 任何时候当存在字段格式不对变量名不对表使用不对等禁止做兼容修改必须按唯一性修改。比如约定字段是string正确只能传string错误可以传int。 比如约定字段名是data正确只能传data错误可以传sourceData或者data。 3. **代码修改** - 任何时候当存在字段格式不对变量名不对表使用不对等禁止做兼容修改必须按唯一性修改。比如约定字段是string正确只能传string错误可以传int。 比如约定字段名是data正确只能传data错误可以传sourceData或者data。
4. **语言** - 永远使用中文跟用户沟通,专有名词可以用英文。 4. **语言** - 永远使用中文跟用户沟通,专有名词可以用英文。
5. **文档** - 在用户没有明确要求先提供文档时,禁止创建文档。避免生产垃圾文件。用户明确要求提供文档时,才创建文档。 5. **文档** - 在用户没有明确要求先提供文档时,禁止创建文档。避免生产垃圾文件。用户明确要求提供文档时,才创建文档。

View File

@ -21,6 +21,7 @@ interface CapabilitySettingsProps {
onEditSkill: (skillId: string) => void; onEditSkill: (skillId: string) => void;
onDeleteSkill: (skillId: string) => Promise<void>; onDeleteSkill: (skillId: string) => Promise<void>;
onCreateExternalTool: () => void; onCreateExternalTool: () => void;
onCopyExternalTool: (pluginId: string) => void;
onEditExternalTool: (pluginId: string) => void; onEditExternalTool: (pluginId: string) => void;
onDeleteExternalTool: (pluginId: string) => Promise<void>; onDeleteExternalTool: (pluginId: string) => Promise<void>;
markDirty: () => void; markDirty: () => void;
@ -42,6 +43,7 @@ export default function CapabilitySettings({
onEditSkill, onEditSkill,
onDeleteSkill, onDeleteSkill,
onCreateExternalTool, onCreateExternalTool,
onCopyExternalTool,
onEditExternalTool, onEditExternalTool,
onDeleteExternalTool, onDeleteExternalTool,
markDirty, markDirty,
@ -78,6 +80,7 @@ export default function CapabilitySettings({
onEditSkill={onEditSkill} onEditSkill={onEditSkill}
onDeleteSkill={onDeleteSkill} onDeleteSkill={onDeleteSkill}
onCreateExternalTool={onCreateExternalTool} onCreateExternalTool={onCreateExternalTool}
onCopyExternalTool={onCopyExternalTool}
onEditExternalTool={onEditExternalTool} onEditExternalTool={onEditExternalTool}
onDeleteExternalTool={onDeleteExternalTool} onDeleteExternalTool={onDeleteExternalTool}
/> />

View File

@ -1,4 +1,4 @@
import { ApiOutlined, DatabaseOutlined, DeleteOutlined, EditOutlined, PlusOutlined, ToolOutlined } from '@ant-design/icons'; import { ApiOutlined, CopyOutlined, DatabaseOutlined, DeleteOutlined, EditOutlined, PlusOutlined, ToolOutlined } from '@ant-design/icons';
import { Button, Card, Collapse, Input, List, Popconfirm, Space, Tag } from 'antd'; import { Button, Card, Collapse, Input, List, Popconfirm, Space, Tag } from 'antd';
import { Agent } from '../../../../api'; import { Agent } from '../../../../api';
import { STATUS_TAG } from '../../constants'; import { STATUS_TAG } from '../../constants';
@ -11,6 +11,7 @@ interface KnowledgeSettingsPanelProps {
onEditSkill: (skillId: string) => void; onEditSkill: (skillId: string) => void;
onDeleteSkill: (skillId: string) => Promise<void>; onDeleteSkill: (skillId: string) => Promise<void>;
onCreateExternalTool: () => void; onCreateExternalTool: () => void;
onCopyExternalTool: (pluginId: string) => void;
onEditExternalTool: (pluginId: string) => void; onEditExternalTool: (pluginId: string) => void;
onDeleteExternalTool: (pluginId: string) => Promise<void>; onDeleteExternalTool: (pluginId: string) => Promise<void>;
} }
@ -23,6 +24,7 @@ export default function KnowledgeSettingsPanel({
onEditSkill, onEditSkill,
onDeleteSkill, onDeleteSkill,
onCreateExternalTool, onCreateExternalTool,
onCopyExternalTool,
onEditExternalTool, onEditExternalTool,
onDeleteExternalTool, onDeleteExternalTool,
}: KnowledgeSettingsPanelProps) { }: KnowledgeSettingsPanelProps) {
@ -193,6 +195,9 @@ export default function KnowledgeSettingsPanel({
} }
extra={ extra={
<Space> <Space>
<Button type="text" size="small" icon={<CopyOutlined />} onClick={() => onCopyExternalTool(plugin.id)}>
</Button>
<Button type="text" size="small" icon={<EditOutlined />} onClick={() => onEditExternalTool(plugin.id)}> <Button type="text" size="small" icon={<EditOutlined />} onClick={() => onEditExternalTool(plugin.id)}>
</Button> </Button>

View File

@ -245,6 +245,43 @@ export function useAgentEditor({ id, isNew, form, message, navigate }: UseAgentE
} }
}; };
const handleCopyPlugin = async (pluginId: string) => {
if (!id || !agent) return;
const plugin = agent.plugins?.find((p) => p.id === pluginId);
if (!plugin) return;
try {
const copyPayload = {
name: `${plugin.name}-copy`,
description: plugin.description,
baseUrl: plugin.baseUrl,
authType: plugin.authType,
authConfig: plugin.authConfig,
apis: plugin.apis.map((api) => ({
name: `${api.name}-copy`,
description: api.description,
method: api.method,
path: api.path,
headers: api.headers,
parametersSchema: api.parametersSchema,
})),
};
const newPlugin = await AgentAPI.bindPlugin(id, copyPayload as any);
setAgent((prev) => {
if (!prev) return prev;
return {
...prev,
plugins: [...(prev.plugins || []), newPlugin],
};
});
message.success('外部工具复制成功');
return newPlugin;
} catch (e: any) {
message.error('外部工具复制失败:' + (e?.message ?? e));
throw e;
}
};
const beforeUploadKnowledge = async (file: any) => { const beforeUploadKnowledge = async (file: any) => {
if (!id) { if (!id) {
message.warning('请先保存智能体基础信息后再上传'); message.warning('请先保存智能体基础信息后再上传');
@ -352,6 +389,7 @@ export function useAgentEditor({ id, isNew, form, message, navigate }: UseAgentE
handleDeleteKnowledge, handleDeleteKnowledge,
handleDeleteSkill, handleDeleteSkill,
handleDeletePlugin, handleDeletePlugin,
handleCopyPlugin,
liveAgent, liveAgent,
currentName, currentName,
markDirty, markDirty,

View File

@ -57,6 +57,7 @@ export default function AgentEditor() {
handleDeleteKnowledge, handleDeleteKnowledge,
handleDeleteSkill, handleDeleteSkill,
handleDeletePlugin, handleDeletePlugin,
handleCopyPlugin,
liveAgent, liveAgent,
currentName, currentName,
markDirty, markDirty,
@ -103,6 +104,17 @@ export default function AgentEditor() {
setEditingPluginId(null); setEditingPluginId(null);
setExternalToolEditorOpen(true); setExternalToolEditorOpen(true);
}} }}
onCopyExternalTool={async (pluginId) => {
try {
const newPlugin = await handleCopyPlugin(pluginId);
if (newPlugin) {
setEditingPluginId(newPlugin.id);
setExternalToolEditorOpen(true);
}
} catch (e) {
// error handled in hook
}
}}
onEditExternalTool={(pluginId) => { onEditExternalTool={(pluginId) => {
setEditingPluginId(pluginId); setEditingPluginId(pluginId);
setExternalToolEditorOpen(true); setExternalToolEditorOpen(true);