From 16051c1f7a04c2194feb7c7d52a2eb50f0143a5e Mon Sep 17 00:00:00 2001 From: sp mac bookpro 2605 Date: Wed, 22 Jul 2026 13:56:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=A4=96=E9=83=A8?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E9=9B=86=E5=BF=AB=E9=80=9F=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E5=B9=B6=E8=87=AA=E5=8A=A8=E8=BF=9B=E5=85=A5=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .trae/rules/rule.md | 2 +- .../components/CapabilitySettings.tsx | 3 ++ .../capability/KnowledgeSettingsPanel.tsx | 7 +++- src/pages/AgentEditor/hooks/useAgentEditor.ts | 38 +++++++++++++++++++ src/pages/AgentEditor/index.tsx | 12 ++++++ 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/.trae/rules/rule.md b/.trae/rules/rule.md index f045a48..1d820e5 100644 --- a/.trae/rules/rule.md +++ b/.trae/rules/rule.md @@ -5,7 +5,7 @@ alwaysApply: true ## 核心规则 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。 4. **语言** - 永远使用中文跟用户沟通,专有名词可以用英文。 5. **文档** - 在用户没有明确要求先提供文档时,禁止创建文档。避免生产垃圾文件。用户明确要求提供文档时,才创建文档。 diff --git a/src/pages/AgentEditor/components/CapabilitySettings.tsx b/src/pages/AgentEditor/components/CapabilitySettings.tsx index 666379e..7564f01 100644 --- a/src/pages/AgentEditor/components/CapabilitySettings.tsx +++ b/src/pages/AgentEditor/components/CapabilitySettings.tsx @@ -21,6 +21,7 @@ interface CapabilitySettingsProps { onEditSkill: (skillId: string) => void; onDeleteSkill: (skillId: string) => Promise; onCreateExternalTool: () => void; + onCopyExternalTool: (pluginId: string) => void; onEditExternalTool: (pluginId: string) => void; onDeleteExternalTool: (pluginId: string) => Promise; markDirty: () => void; @@ -42,6 +43,7 @@ export default function CapabilitySettings({ onEditSkill, onDeleteSkill, onCreateExternalTool, + onCopyExternalTool, onEditExternalTool, onDeleteExternalTool, markDirty, @@ -78,6 +80,7 @@ export default function CapabilitySettings({ onEditSkill={onEditSkill} onDeleteSkill={onDeleteSkill} onCreateExternalTool={onCreateExternalTool} + onCopyExternalTool={onCopyExternalTool} onEditExternalTool={onEditExternalTool} onDeleteExternalTool={onDeleteExternalTool} /> diff --git a/src/pages/AgentEditor/components/capability/KnowledgeSettingsPanel.tsx b/src/pages/AgentEditor/components/capability/KnowledgeSettingsPanel.tsx index a5c83a7..8f7823e 100644 --- a/src/pages/AgentEditor/components/capability/KnowledgeSettingsPanel.tsx +++ b/src/pages/AgentEditor/components/capability/KnowledgeSettingsPanel.tsx @@ -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 { Agent } from '../../../../api'; import { STATUS_TAG } from '../../constants'; @@ -11,6 +11,7 @@ interface KnowledgeSettingsPanelProps { onEditSkill: (skillId: string) => void; onDeleteSkill: (skillId: string) => Promise; onCreateExternalTool: () => void; + onCopyExternalTool: (pluginId: string) => void; onEditExternalTool: (pluginId: string) => void; onDeleteExternalTool: (pluginId: string) => Promise; } @@ -23,6 +24,7 @@ export default function KnowledgeSettingsPanel({ onEditSkill, onDeleteSkill, onCreateExternalTool, + onCopyExternalTool, onEditExternalTool, onDeleteExternalTool, }: KnowledgeSettingsPanelProps) { @@ -193,6 +195,9 @@ export default function KnowledgeSettingsPanel({ } extra={ + diff --git a/src/pages/AgentEditor/hooks/useAgentEditor.ts b/src/pages/AgentEditor/hooks/useAgentEditor.ts index 3d0c4a1..b10c3db 100644 --- a/src/pages/AgentEditor/hooks/useAgentEditor.ts +++ b/src/pages/AgentEditor/hooks/useAgentEditor.ts @@ -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) => { if (!id) { message.warning('请先保存智能体基础信息后再上传'); @@ -352,6 +389,7 @@ export function useAgentEditor({ id, isNew, form, message, navigate }: UseAgentE handleDeleteKnowledge, handleDeleteSkill, handleDeletePlugin, + handleCopyPlugin, liveAgent, currentName, markDirty, diff --git a/src/pages/AgentEditor/index.tsx b/src/pages/AgentEditor/index.tsx index 5c5e5fd..87a714a 100644 --- a/src/pages/AgentEditor/index.tsx +++ b/src/pages/AgentEditor/index.tsx @@ -57,6 +57,7 @@ export default function AgentEditor() { handleDeleteKnowledge, handleDeleteSkill, handleDeletePlugin, + handleCopyPlugin, liveAgent, currentName, markDirty, @@ -103,6 +104,17 @@ export default function AgentEditor() { setEditingPluginId(null); 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) => { setEditingPluginId(pluginId); setExternalToolEditorOpen(true);