mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-14 07:00:23 +02:00
Add files via upload
This commit is contained in:
@@ -196,9 +196,13 @@ func (m *ExternalMCPManager) StartClient(name string) error {
|
|||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
delete(m.errors, name)
|
delete(m.errors, name)
|
||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
// 延迟再刷新工具数量,避免 SSE/Streamable 连接尚未就绪时立即请求导致 EOF(如值得买等远端)
|
// 立即刷新工具数量(HTTP/stdio 等可马上拿到)
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
m.triggerToolCountRefresh()
|
m.triggerToolCountRefresh()
|
||||||
|
// 2 秒后再刷新一次,覆盖 SSE/Streamable 等需稍等就绪的远端
|
||||||
|
go func() {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
m.triggerToolCountRefresh()
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
+35
-29
@@ -974,15 +974,17 @@ async function changePassword() {
|
|||||||
|
|
||||||
let currentEditingMCPName = null;
|
let currentEditingMCPName = null;
|
||||||
|
|
||||||
// 加载外部MCP列表
|
// 拉取外部MCP列表数据(供轮询使用,返回 { servers, stats })
|
||||||
|
async function fetchExternalMCPs() {
|
||||||
|
const response = await apiFetch('/api/external-mcp');
|
||||||
|
if (!response.ok) throw new Error('获取外部MCP列表失败');
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载外部MCP列表并渲染
|
||||||
async function loadExternalMCPs() {
|
async function loadExternalMCPs() {
|
||||||
try {
|
try {
|
||||||
const response = await apiFetch('/api/external-mcp');
|
const data = await fetchExternalMCPs();
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('获取外部MCP列表失败');
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
renderExternalMCPList(data.servers || {});
|
renderExternalMCPList(data.servers || {});
|
||||||
renderExternalMCPStats(data.stats || {});
|
renderExternalMCPStats(data.stats || {});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -994,18 +996,27 @@ async function loadExternalMCPs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 延迟刷新外部MCP列表(用于在保存/连接后拉取后端异步更新的工具数量)
|
// 轮询列表直到指定 MCP 的工具数量已更新(每秒拉一次,拿到即停,无固定延迟)
|
||||||
// 可选传入单次延迟毫秒数;不传则执行两次:2.5s 与 5s(覆盖启动后后端异步更新较慢的情况)
|
// name 为 null 时仅按 maxAttempts 次数轮询,不判断 tool_count
|
||||||
function scheduleExternalMCPToolCountRefresh(delayMs) {
|
async function pollExternalMCPToolCount(name, maxAttempts = 10) {
|
||||||
const delays = delayMs != null ? [delayMs] : [2500, 5000];
|
const pollIntervalMs = 1000;
|
||||||
delays.forEach((d) => {
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||||
setTimeout(async () => {
|
await new Promise(r => setTimeout(r, pollIntervalMs));
|
||||||
await loadExternalMCPs();
|
try {
|
||||||
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
const data = await fetchExternalMCPs();
|
||||||
window.refreshMentionTools();
|
renderExternalMCPList(data.servers || {});
|
||||||
|
renderExternalMCPStats(data.stats || {});
|
||||||
|
if (name != null) {
|
||||||
|
const server = data.servers && data.servers[name];
|
||||||
|
if (server && server.tool_count > 0) break;
|
||||||
}
|
}
|
||||||
}, d);
|
} catch (e) {
|
||||||
});
|
console.warn('轮询工具数量失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
||||||
|
window.refreshMentionTools();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 渲染外部MCP列表
|
// 渲染外部MCP列表
|
||||||
@@ -1364,12 +1375,11 @@ async function saveExternalMCP() {
|
|||||||
|
|
||||||
closeExternalMCPModal();
|
closeExternalMCPModal();
|
||||||
await loadExternalMCPs();
|
await loadExternalMCPs();
|
||||||
// 刷新对话界面的工具列表,使新添加的MCP工具立即可用
|
|
||||||
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
||||||
window.refreshMentionTools();
|
window.refreshMentionTools();
|
||||||
}
|
}
|
||||||
// 后端在连接成功约 2 秒后才更新工具数量,延迟再拉取一次以显示正确工具数
|
// 轮询几次以拉取后端异步更新的工具数量(无固定延迟,拿到即停)
|
||||||
scheduleExternalMCPToolCountRefresh();
|
pollExternalMCPToolCount(null, 5);
|
||||||
alert('保存成功');
|
alert('保存成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('保存外部MCP失败:', error);
|
console.error('保存外部MCP失败:', error);
|
||||||
@@ -1443,14 +1453,12 @@ async function toggleExternalMCP(name, currentStatus) {
|
|||||||
const status = statusData.status || 'disconnected';
|
const status = statusData.status || 'disconnected';
|
||||||
|
|
||||||
if (status === 'connected') {
|
if (status === 'connected') {
|
||||||
// 已经连接,立即刷新
|
|
||||||
await loadExternalMCPs();
|
await loadExternalMCPs();
|
||||||
// 刷新对话界面的工具列表
|
|
||||||
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
||||||
window.refreshMentionTools();
|
window.refreshMentionTools();
|
||||||
}
|
}
|
||||||
// 后端约 2 秒后才更新工具数量,延迟再拉取一次以显示正确工具数
|
// 轮询直到该 MCP 工具数量已更新(每秒拉一次,无固定延迟)
|
||||||
scheduleExternalMCPToolCountRefresh();
|
pollExternalMCPToolCount(name, 10);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1508,14 +1516,12 @@ async function pollExternalMCPStatus(name, maxAttempts = 30) {
|
|||||||
const button = document.getElementById(buttonId);
|
const button = document.getElementById(buttonId);
|
||||||
|
|
||||||
if (status === 'connected') {
|
if (status === 'connected') {
|
||||||
// 连接成功,刷新列表
|
|
||||||
await loadExternalMCPs();
|
await loadExternalMCPs();
|
||||||
// 刷新对话界面的工具列表
|
|
||||||
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
if (typeof window !== 'undefined' && typeof window.refreshMentionTools === 'function') {
|
||||||
window.refreshMentionTools();
|
window.refreshMentionTools();
|
||||||
}
|
}
|
||||||
// 后端约 2 秒后才更新工具数量,延迟再拉取一次以显示正确工具数
|
// 轮询直到该 MCP 工具数量已更新(每秒拉一次,无固定延迟)
|
||||||
scheduleExternalMCPToolCountRefresh();
|
pollExternalMCPToolCount(name, 10);
|
||||||
return;
|
return;
|
||||||
} else if (status === 'error' || status === 'disconnected') {
|
} else if (status === 'error' || status === 'disconnected') {
|
||||||
// 连接失败,刷新列表并显示错误
|
// 连接失败,刷新列表并显示错误
|
||||||
|
|||||||
Reference in New Issue
Block a user