fix: 修复系统诊断页面一键修复配对,解决 origin not allowed 握手失败

根本原因:Gateway WebSocket 服务检查 HTTP Origin 头,Tauri 应用的
origin (tauri://localhost / https://tauri.localhost) 不在
gateway.controlUi.allowedOrigins 白名单,导致 code 1008 拒绝握手。

修复内容:
- pairing.rs: auto_pair_device 新增 patch_gateway_origins(),在写入
  paired.json 的同时将 tauri://localhost 和 https://tauri.localhost
  写入 openclaw.json gateway.controlUi.allowedOrigins
- chat-debug.js: fixPairing 流程补充 origins 写入提示;success 后
  触发主 wsClient.reconnect() 让主界面恢复正常;修复诊断建议去除
  重复条件,合并 origin/端口 两种可能原因
- chat-debug.js: testWebSocket 1008 关闭时给出明确原因和解决方法
- ws-client.js: onclose 1008 时自动触发 _autoPairAndReconnect()
  而非普通重连,实现主应用自愈
This commit is contained in:
晴天
2026-03-04 13:25:20 +08:00
parent 590f943e7b
commit 7c34f7919d
3 changed files with 71 additions and 10 deletions

View File

@@ -88,9 +88,48 @@ pub fn auto_pair_device() -> Result<String, String> {
std::fs::write(&paired_path, new_content).map_err(|e| format!("写入 paired.json 失败: {e}"))?;
// 同步写入 controlUi.allowedOrigins允许 Tauri 的 origin 连接 Gateway
patch_gateway_origins();
Ok("设备配对成功".into())
}
/// 将 Tauri 应用的 origin 写入 gateway.controlUi.allowedOrigins
/// 避免 Gateway 因 origin not allowed 拒绝 WebSocket 握手
fn patch_gateway_origins() {
let config_path = crate::commands::openclaw_dir().join("openclaw.json");
if !config_path.exists() {
return;
}
let Ok(content) = std::fs::read_to_string(&config_path) else {
return;
};
let Ok(mut config) = serde_json::from_str::<serde_json::Value>(&content) else {
return;
};
// Tauri v2: macOS/Linux 用 tauri://localhostWindows 用 https://tauri.localhost
let origins = serde_json::json!(["tauri://localhost", "https://tauri.localhost", "http://localhost"]);
if let Some(obj) = config.as_object_mut() {
let gateway = obj
.entry("gateway")
.or_insert_with(|| serde_json::json!({}));
if let Some(gw) = gateway.as_object_mut() {
let control_ui = gw
.entry("controlUi")
.or_insert_with(|| serde_json::json!({}));
if let Some(cui) = control_ui.as_object_mut() {
cui.insert("allowedOrigins".to_string(), origins);
}
}
}
if let Ok(new_json) = serde_json::to_string_pretty(&config) {
let _ = std::fs::write(&config_path, new_json);
}
}
#[tauri::command]
pub fn check_pairing_status() -> Result<bool, String> {
// 读取设备密钥