From d55a496ff429f43cc0c415f4052df0e3211075dc Mon Sep 17 00:00:00 2001 From: QihuAI Design Date: Mon, 20 Jul 2026 14:45:21 +0800 Subject: [PATCH] Phase 4.3 ACA: MCP.tsx protocol selector panel + api ACA methods (v2026.07.19.12) --- frontend/src/api/index.ts | 3 + frontend/src/pages/admin/Mcp.tsx | 141 +++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index fbaadf5..1131d0d 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -897,6 +897,9 @@ export const adminAPI = { importYamlOrch: (id: string, yaml: string) => post(`/admin/agents/${id}/orchestration/yaml/import`, { yaml_text: yaml }), exportYamlOrch: (id: string) => post(`/admin/agents/${id}/orchestration/yaml/export`), getYamlTemplates: () => get('/admin/agents/orchestration/yaml/templates'), + getAcaProtocols: () => get("/admin/agents/aca/protocols"), + getAcaProtocolTools: (name: string) => get(`/admin/agents/aca/protocols/${name}/tools`), + checkAcaHealth: (name: string) => post(`/admin/agents/aca/protocols/${name}/health`, {}), getAdminAvailableSkills: (params?: any) => { diff --git a/frontend/src/pages/admin/Mcp.tsx b/frontend/src/pages/admin/Mcp.tsx index a06d6d2..b7c3b66 100644 --- a/frontend/src/pages/admin/Mcp.tsx +++ b/frontend/src/pages/admin/Mcp.tsx @@ -34,6 +34,29 @@ const styles: Record = { detailsGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginTop: 16 }, detailsItem: { fontSize: 13 }, detailsLabel: { color: '#6b7280', marginBottom: 4 }, + // ACA 协议抽象层 (Phase 4.3) + acaSection: { marginTop: 32, backgroundColor: '#fff', borderRadius: 12, padding: 24, boxShadow: '0 1px 3px rgba(0,0,0,0.08)' }, + acaHead: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }, + acaTitle: { fontSize: 18, fontWeight: 700, color: '#1A1F36' }, + acaSub: { fontSize: 13, color: '#6b7280', marginTop: 4 }, + acaRefresh: { padding: '8px 16px', border: '1px solid #e5e7eb', borderRadius: 8, cursor: 'pointer', backgroundColor: '#fff', fontSize: 13 }, + acaGrid: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 16 }, + acaCard: { border: '1px solid #e5e7eb', borderRadius: 12, padding: 16 }, + acaCardTop: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }, + acaProtoName: { fontSize: 16, fontWeight: 700, color: '#1A1F36', textTransform: 'uppercase' }, + acaVer: { fontSize: 12, color: '#9ca3af', marginLeft: 8 }, + acaCaps: { display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 10 }, + acaCap: { fontSize: 12, padding: '2px 8px', borderRadius: 12, backgroundColor: '#eef2ff', color: '#4338ca' }, + acaActions: { display: 'flex', gap: 8, marginTop: 14 }, + acaBtn: { padding: '6px 14px', border: '1px solid #e5e7eb', borderRadius: 6, cursor: 'pointer', backgroundColor: '#fff', fontSize: 13 }, + acaBtnPrimary: { padding: '6px 14px', border: 'none', borderRadius: 6, cursor: 'pointer', backgroundColor: '#4f46e5', color: '#fff', fontSize: 13 }, + acaHealth: { fontSize: 12, fontWeight: 600, marginTop: 10 }, + acaTools: { marginTop: 12, borderTop: '1px solid #f3f4f6', paddingTop: 12 }, + acaTool: { padding: '8px 0', borderBottom: '1px solid #f9fafb' }, + acaToolName: { fontSize: 13, fontWeight: 600, color: '#374151' }, + acaToolServer: { fontSize: 11, color: '#4f46e5', marginLeft: 8 }, + acaToolDesc: { fontSize: 12, color: '#9ca3af', marginTop: 2 }, + acaEmpty: { fontSize: 13, color: '#9ca3af', padding: '12px 0' }, }; const TRANSPORT_TYPES = [ @@ -83,6 +106,13 @@ export default function AdminMcp() { const [editingServer, setEditingServer] = useState(null); const [toast, setToast] = useState<{ message: string; type: string } | null>(null); const pageSize = 20; + // ACA 协议抽象层 (Phase 4.3) + const [acaProtocols, setAcaProtocols] = useState([]); + const [acaLoading, setAcaLoading] = useState(true); + const [acaTools, setAcaTools] = useState>({}); + const [acaExpanded, setAcaExpanded] = useState>({}); + const [acaHealth, setAcaHealth] = useState>({}); + const [acaChecking, setAcaChecking] = useState>({}); const showToast = (message: string, type: string = 'success') => { setToast({ message, type }); @@ -119,6 +149,52 @@ export default function AdminMcp() { fetchStats(); fetchServers(); }, [fetchStats, fetchServers]); + // ACA 协议抽象层 (Phase 4.3) + const fetchAcaProtocols = useCallback(async () => { + setAcaLoading(true); + try { + const result = await adminAPI.getAcaProtocols() as any; + const list = Array.isArray(result) ? result : (result && result.data ? result.data : []); + setAcaProtocols(list); + } catch (e) { + setAcaProtocols([]); + } finally { + setAcaLoading(false); + } + }, []); + + const fetchAcaTools = useCallback(async (name: string) => { + try { + const result = await adminAPI.getAcaProtocolTools(name) as any; + const tools = result && result.tools ? result.tools : (result && result.data ? (result.data.tools || []) : []); + setAcaTools(prev => ({ ...prev, [name]: tools })); + } catch (e) { + setAcaTools(prev => ({ ...prev, [name]: [] })); + } + }, []); + + const toggleAcaTools = (name: string) => { + setAcaExpanded(prev => { + const next = !prev[name]; + if (next && !acaTools[name]) fetchAcaTools(name); + return { ...prev, [name]: next }; + }); + }; + + const checkAcaHealth = async (name: string) => { + setAcaChecking(prev => ({ ...prev, [name]: true })); + try { + const result = await adminAPI.checkAcaHealth(name) as any; + const healthy = result ? (result.healthy !== undefined ? result.healthy : (result.data ? result.data.healthy : false)) : false; + setAcaHealth(prev => ({ ...prev, [name]: healthy })); + } catch (e) { + setAcaHealth(prev => ({ ...prev, [name]: false })); + } finally { + setAcaChecking(prev => ({ ...prev, [name]: false })); + } + }; + + useEffect(() => { fetchAcaProtocols(); }, [fetchAcaProtocols]); const handleCreate = () => { setEditingServer(null); @@ -238,6 +314,71 @@ export default function AdminMcp() { + {/* Phase 4.3: ACA 协议抽象层 */} +
+
+
+
ACA 协议抽象层
+
统一协议接入(MCP / A2A / 自定义),隔离底层实现,防止协议绑架
+
+ +
+ {acaLoading ? ( +
加载中...
+ ) : acaProtocols.length === 0 ? ( +
未注册任何 ACA 协议
+ ) : ( +
+ {acaProtocols.map((p: any) => ( +
+
+
+ {p.name} + v{p.version} +
+ 已注册 +
+
+ {(p.capabilities || []).map((c: string) => ( + {c} + ))} +
+ {acaHealth[p.name] !== undefined && ( +
+ 健康:{acaHealth[p.name] ? '正常' : '异常'} +
+ )} +
+ + +
+ {acaExpanded[p.name] && ( +
+ {(acaTools[p.name] || []).length === 0 ? ( +
暂无工具
+ ) : ( + (acaTools[p.name] || []).map((t: any, idx: number) => ( +
+
+ {t.name} + {t._mcp_server_name && @{t._mcp_server_name}} +
+ {t.description &&
{String(t.description).substring(0, 120)}
} +
+ )) + )} +
+ )} +
+ ))} +
+ )} +
+