From 5ee8c4736f40cc79ae8d2583105ba2fabdbc24ac Mon Sep 17 00:00:00 2001 From: zhanggangyong Date: Tue, 13 Jan 2026 10:04:34 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A0=B9=E6=8D=AE=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=9B=B4=E6=96=B0=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?Agent=E5=88=9B=E5=BB=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 API Client createCustomAgent 方法,添加 model、agentRole、agentCapabilities 参数 - 更新模板接口解析,支持新格式 frameworkTemplates 和 dataTemplates - 添加数据存储模板选择器(mysql_agent、postgresql_agent 等) - 添加动态环境变量配置,根据模板的 env_info.required/optional 动态生成表单 - 添加 A2A 框架专用配置(Agent角色、Agent能力) - 更新表单验证和配置摘要 --- app/data-tools/page.tsx | 237 +++++++++++++++++++++++++++++++++------- lib/api-client.ts | 24 +++- 2 files changed, 217 insertions(+), 44 deletions(-) diff --git a/app/data-tools/page.tsx b/app/data-tools/page.tsx index 7b1319d..4cd108b 100644 --- a/app/data-tools/page.tsx +++ b/app/data-tools/page.tsx @@ -61,6 +61,13 @@ export default function DataToolsPage() { const [selectedDataTemplate, setSelectedDataTemplate] = useState("") const [dataTemplates, setDataTemplates] = useState([]) const [frameworkTemplates, setFrameworkTemplates] = useState([]) + // 新增:API返回的数据存储模板(含环境变量信息) + const [apiDataTemplates, setApiDataTemplates] = useState([]) + const [selectedApiDataTemplate, setSelectedApiDataTemplate] = useState("") + const [envConfig, setEnvConfig] = useState>({}) + // A2A 框架专用字段 + const [agentRole, setAgentRole] = useState("") + const [agentCapabilities, setAgentCapabilities] = useState("") const [availableModels, setAvailableModels] = useState([]) const [toolName, setToolName] = useState("") const [deploying, setDeploying] = useState(false) @@ -82,12 +89,11 @@ export default function DataToolsPage() { const loadFrameworkTemplates = async () => { try { const result = await TaijiAPIClient.getCustomAgentTemplates() - if (result?.success && result.data?.templates) { - // 文档返回的是字符串数组:["A2A", "langchain", "MCP"] - // 转换为对象数组以便显示 - const templates = result.data.templates.map((template: string | any) => { - if (typeof template === 'string') { - // 如果是字符串,转换为对象 + if (result?.success && result.data) { + // 新格式:{ frameworkTemplates: [...], dataTemplates: [...] } + if (result.data.frameworkTemplates) { + // 框架模板:字符串数组 ["A2A", "langchain", "MCP"] + const templates = result.data.frameworkTemplates.map((template: string) => { const displayNames: Record = { 'A2A': 'A2A框架', 'langchain': 'LangChain框架', @@ -98,11 +104,34 @@ export default function DataToolsPage() { displayName: displayNames[template] || template, description: '' } - } - // 如果已经是对象,直接返回(兼容旧格式) - return template - }) - setFrameworkTemplates(templates) + }) + setFrameworkTemplates(templates) + } + + // 数据存储模板:对象数组,包含 env_info + if (result.data.dataTemplates) { + setApiDataTemplates(result.data.dataTemplates) + } + + // 兼容旧格式:{ templates: [...] } + if (result.data.templates && !result.data.frameworkTemplates) { + const templates = result.data.templates.map((template: string | any) => { + if (typeof template === 'string') { + const displayNames: Record = { + 'A2A': 'A2A框架', + 'langchain': 'LangChain框架', + 'MCP': 'MCP框架' + } + return { + name: template, + displayName: displayNames[template] || template, + description: '' + } + } + return template + }) + setFrameworkTemplates(templates) + } } } catch (error) { console.error("Failed to load framework templates:", error) @@ -350,8 +379,9 @@ export default function DataToolsPage() { // 部署Agent(创建自定义Agent) const handleDeployAgent = async () => { - if (!selectedFramework || !toolName) { - alert(t("请填写所有必填字段", "Please fill in all required fields")) + // 校验必填字段 + if (!selectedApiDataTemplate || !toolName) { + alert(t("请选择数据存储模板并填写Agent名称", "Please select a data template and enter agent name")) return } @@ -374,22 +404,40 @@ export default function DataToolsPage() { } } - // 使用创建自定义Agent接口 POST /api/user/custom-agents - // 根据文档:template是必填的模板名称,frameworkTemplate是框架类型(可选) - const frameworkName = selectedFramework.toUpperCase() // MCP/A2A/langchain - const templateName = `${frameworkName.toLowerCase()}-agent` // 生成模板名称,如 "mcp-agent" + // 框架类型(默认MCP) + const frameworkName = selectedFramework || "MCP" - const result = await TaijiAPIClient.createCustomAgent({ + // 构建请求参数 + const requestData: any = { name: toolName, - template: templateName, // 必填:模板名称 + template: selectedApiDataTemplate, // 必填:数据存储模板(如 mysql_agent) frameworkTemplate: frameworkName, // 可选:框架类型(A2A/langchain/MCP) description: toolName, // 可选:Agent描述 - cpuRequest: cpuRequest, // 必填:CPU请求量(如"500m") + cpuRequest: cpuRequest, // 必填:CPU请求量 cpuLimit: cpuLimit, // 可选:CPU限制量 - memoryRequest: memoryRequest, // 必填:内存请求量(如"1Gi") + memoryRequest: memoryRequest, // 必填:内存请求量 memoryLimit: memoryLimit, // 可选:内存限制量 tools: selectedTools.length > 0 ? selectedTools : undefined, // 可选:工具ID列表 - }) + model: podConfig.model, // 可选:模型名称 + } + + // 添加环境变量配置(如数据库连接信息) + if (Object.keys(envConfig).length > 0) { + requestData.envConfig = envConfig + } + + // A2A 框架专用字段 + if (frameworkName === "A2A") { + if (agentRole) { + requestData.agentRole = agentRole + } + if (agentCapabilities) { + // 将逗号分隔的字符串转换为数组 + requestData.agentCapabilities = agentCapabilities.split(",").map(s => s.trim()).filter(Boolean) + } + } + + const result = await TaijiAPIClient.createCustomAgent(requestData) if (result?.success) { alert(t("自定义Agent创建成功,正在部署", "Custom Agent created successfully, deploying")) @@ -398,6 +446,10 @@ export default function DataToolsPage() { setSelectedFramework("") setSelectedServiceGateway("") setSelectedDataTemplate("") + setSelectedApiDataTemplate("") + setEnvConfig({}) + setAgentRole("") + setAgentCapabilities("") setToolName("") setPodConfig({ agentCount: 1, @@ -790,10 +842,92 @@ export default function DataToolsPage() {
- + + setToolName(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '-'))} + /> +
+ + {/* 数据存储模板选择 */} +
+ + +

+ {t("选择Agent使用的数据存储类型", "Select data storage type for the agent")} +

+
+ + {/* 动态环境变量配置(根据选择的模板) */} + {selectedApiDataTemplate && (() => { + const template = apiDataTemplates.find(t => t.template === selectedApiDataTemplate) + if (!template?.env_info) return null + const required = template.env_info.required || {} + const optional = template.env_info.optional || {} + return ( +
+

{t("数据库连接配置", "Database Connection Config")}

+ {Object.entries(required).map(([key, desc]) => ( +
+ + setEnvConfig({ ...envConfig, [key]: e.target.value })} + type={key.toLowerCase().includes('password') ? 'password' : 'text'} + /> +
+ ))} + {Object.entries(optional).map(([key, desc]) => ( +
+ + setEnvConfig({ ...envConfig, [key]: e.target.value })} + /> +
+ ))} +
+ ) + })()} + + {/* 框架类型选择 */} +
+

- {t("根据选择的框架注册相应的工具", "Register tools according to selected framework")} + {t("选择Agent运行框架,默认为MCP", "Select agent runtime framework, defaults to MCP")}

-
- - setToolName(e.target.value)} - /> -
+ {/* A2A 框架专用配置 */} + {selectedFramework === "A2A" && ( +
+

+ + {t("A2A 框架配置", "A2A Framework Config")} +

+
+ + setAgentRole(e.target.value)} + /> +
+
+ + setAgentCapabilities(e.target.value)} + /> +
+
+ )}

@@ -953,13 +1104,13 @@ export default function DataToolsPage() {

{t("配置摘要", "Configuration Summary")}

- {t("框架", "Framework")}: {selectedFramework || t("未选择", "Not selected")} + {t("Agent名称", "Agent Name")}: {toolName || t("未填写", "Not filled")}
- {t("网关", "Gateway")}: {selectedServiceGateway || t("未选择", "Not selected")} + {t("数据存储模板", "Data Template")}: {selectedApiDataTemplate || t("未选择", "Not selected")}
-
- {t("Agent数量", "Agent Count")}: {podConfig.agentCount} +
+ {t("框架", "Framework")}: {selectedFramework || "MCP"}
{t("CPU", "CPU")}: {podConfig.cpuCores} {t("核", "cores")} @@ -967,12 +1118,14 @@ export default function DataToolsPage() {
{t("内存", "Memory")}: {podConfig.memoryGB}GB
-
- {t("最大扩展", "Max Scale")}: {podConfig.maxAgents} -
{t("模型", "Model")}: {podConfig.model}
+ {selectedFramework === "A2A" && agentRole && ( +
+ {t("Agent角色", "Agent Role")}: {agentRole} +
+ )}
@@ -982,7 +1135,7 @@ export default function DataToolsPage() { - diff --git a/lib/api-client.ts b/lib/api-client.ts index a594d67..3438bff 100644 --- a/lib/api-client.ts +++ b/lib/api-client.ts @@ -685,20 +685,40 @@ export class TaijiAPIClient { * 创建租户自定义的Agent,将使用渠道为该租户分配的CPU和内存资源配额 * * 注意:后端实际路径为 /api/user/custom-agents(非 /api/user/agents/custom/create) + * + * @param data.name - Agent名称(小写字母、数字、连字符) + * @param data.template - 数据存储模板(如 "mysql_agent"、"postgresql_agent") + * @param data.frameworkTemplate - 框架类型("MCP" | "A2A" | "langchain"),默认 "MCP" + * @param data.description - Agent描述 + * @param data.cpuRequest - CPU请求量(如 "500m") + * @param data.cpuLimit - CPU限制量 + * @param data.memoryRequest - 内存请求量(如 "1Gi") + * @param data.memoryLimit - 内存限制量 + * @param data.tools - 工具ID列表(UUID) + * @param data.model - 模型名称(如 "gpt-4") + * @param data.endpoint - 自定义终结点 + * @param data.apiKey - API密钥 + * @param data.envConfig - 环境变量配置(数据库连接等) + * @param data.agentRole - A2A框架专用:Agent角色(如 "data_analyzer") + * @param data.agentCapabilities - A2A框架专用:Agent能力列表 */ static async createCustomAgent(data: { name: string - template?: string - frameworkTemplate?: string + template: string // 必填:数据存储模板 + frameworkTemplate?: string // 可选:框架类型 description?: string cpuRequest: string cpuLimit?: string memoryRequest: string memoryLimit?: string tools?: string[] + model?: string // 新增:模型名称 endpoint?: string apiKey?: string envConfig?: Record + // A2A 框架专用(新增) + agentRole?: string + agentCapabilities?: string[] }) { const response = await fetch(`${API_BASE_URLS.mcpServer}/api/user/custom-agents`, { method: "POST",