fix(aiops): Agent CLI 连接 ssh-key 主机永久转圈修复
- buildSSHConfig 放宽认证判定:SSHKey 非空即走密钥认证,不再强依赖 AuthType=="key", 兼容编辑表单/历史数据未正确设置 AuthType 的 ssh-key 主机(与 WebShell 行为对齐) - agent_cli WS 握手:Upgrade 提前到预检之前,预检失败经 writeWSCloseError 推具体 error 帧;写 error 后 sleep 120ms 再发 close,避免 TCP 提前关闭导致 error 帧丢失 - 前端 AgentCLI 连接兜底:新增 8s 连接超时 + onclose 区分"从未连上"(push 明确 原因提示)与"连上后断开",杜绝预检失败时"正在连接主机"永久转圈、看不到原因 - 引擎配置补传 ReasoningEnabled Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
01967bc52b
commit
3b19ae6e98
3 files changed
+73
-25
No files matched your search
@@ -90,15 +90,45 @@ export default function AgentCLI() {
|
||||
if (!serverId) return;
|
||||
setItems([]);
|
||||
setRound(0); setTokens(0); setRunning(false);
|
||||
setConnected(false);
|
||||
const ws = new WebSocket(buildAgentCliWsUrl(serverId));
|
||||
wsRef.current = ws;
|
||||
ws.onopen = () => setConnected(true);
|
||||
ws.onclose = () => { setConnected(false); setRunning(false); };
|
||||
let everConnected = false; // 是否曾握手成功:区分"预检失败被拒"与"连上后断开" // Logan.Li
|
||||
let active = true; // 本轮连接是否仍活跃:切换主机/卸载后置 false,避免脏消息 // Logan.Li
|
||||
|
||||
// 连接超时兜底:握手迟迟不成功则判定失败,避免"正在连接主机"永久转圈 // Logan.Li
|
||||
const connectTimer = window.setTimeout(() => {
|
||||
if (active && !everConnected && ws.readyState !== WebSocket.OPEN) {
|
||||
push({ kind: 'error', content: '连接主机超时:后端长时间未响应,请检查后端服务状态、SSH 凭据与大模型配置后重试。' });
|
||||
try { ws.close(); } catch { /* noop */ }
|
||||
}
|
||||
}, 8000);
|
||||
|
||||
ws.onopen = () => { everConnected = true; setConnected(true); };
|
||||
ws.onclose = () => {
|
||||
if (!active) return; // 切换主机触发的关闭,忽略,不写脏消息
|
||||
window.clearTimeout(connectTimer);
|
||||
setConnected(false);
|
||||
setRunning(false);
|
||||
// 从未握上手就被对端关闭(SSH 凭据预检失败 / 大模型未启用 / 网络中断):
|
||||
// 此时后端的 error 帧可能因 TCP 提前关闭而丢失,onclose 收不到具体原因。
|
||||
// 这里兜底给出明确提示,杜绝"正在连接主机"永久转圈、用户看不到原因 // Logan.Li
|
||||
if (!everConnected) {
|
||||
push({ kind: 'error', content: '主机连接被拒绝:常见为该主机未关联可用的 SSH 凭据(密码或密钥),或大模型未启用。请到「服务器管理」确认该主机凭据、到「大模型设置」确认已启用模型后重试。' });
|
||||
} else {
|
||||
push({ kind: 'info', content: '连接已关闭' });
|
||||
}
|
||||
};
|
||||
ws.onerror = () => { setConnected(false); };
|
||||
ws.onmessage = (e) => {
|
||||
try { handleEvent(JSON.parse(e.data)); } catch { /* 忽略非 JSON */ }
|
||||
};
|
||||
return () => { ws.close(); wsRef.current = null; };
|
||||
return () => {
|
||||
active = false;
|
||||
window.clearTimeout(connectTimer);
|
||||
ws.close();
|
||||
wsRef.current = null;
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [serverId]);
|
||||
|
||||
|
||||
Reference in new issue
Block a user