fix: 修复 pairing required - 改用 openclaw-control-ui 客户端 ID 触发静默自动配对

上游源码分析发现根本原因:
- Gateway 的 shouldAllowSilentLocalPairing 需要 isControlUi=true
  才能在本地连接时静默自动批准设备配对
- 我们之前用 gateway-client+backend,isControlUi=false,加上
  Tauri WebView 会发 Origin 头(hasBrowserOriginHeader=true),
  导致 shouldAllowSilentLocalPairing 返回 false → 'pairing required'

修复内容:
- device.rs: client.id 改为 openclaw-control-ui,mode 改为 ui,
  v3 签名 payload 同步更新,本地连接触发静默自动配对
- pairing.rs: paired.json 的 clientId/clientMode 同步更新
- main.js: 启动时自动调用 autoPairDevice(),确保 device 已配对
  + allowedOrigins 已写入,无需用户手动点击一键修复
This commit is contained in:
晴天
2026-03-04 14:39:48 +08:00
parent 7a05625aee
commit 73d7d6e7f5
3 changed files with 13 additions and 8 deletions

View File

@@ -101,8 +101,10 @@ pub fn create_connect_frame(nonce: String, gateway_token: String) -> Result<Valu
let scopes_str = SCOPES.join(",");
// v3 格式v3|deviceId|clientId|clientMode|role|scopes|signedAt|token|nonce|platform|deviceFamily
// 使用 openclaw-control-ui + ui 模式,使 Gateway 识别为 Control UI 客户端,
// 本地连接时触发静默自动配对shouldAllowSilentLocalPairing = true
let payload_str = format!(
"v3|{device_id}|gateway-client|backend|operator|{scopes_str}|{signed_at}|{gateway_token}|{nonce}|{platform}|{device_family}"
"v3|{device_id}|openclaw-control-ui|ui|operator|{scopes_str}|{signed_at}|{gateway_token}|{nonce}|{platform}|{device_family}"
);
let signature = signing_key.sign(payload_str.as_bytes());
@@ -116,11 +118,11 @@ pub fn create_connect_frame(nonce: String, gateway_token: String) -> Result<Valu
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "gateway-client",
"id": "openclaw-control-ui",
"version": "1.0.0",
"platform": platform,
"deviceFamily": device_family,
"mode": "backend"
"mode": "ui"
},
"role": "operator",
"scopes": SCOPES,

View File

@@ -62,8 +62,8 @@ pub fn auto_pair_device() -> Result<String, String> {
"deviceId": device_id,
"publicKey": public_key,
"platform": "desktop",
"clientId": "gateway-client",
"clientMode": "backend",
"clientId": "openclaw-control-ui",
"clientMode": "ui",
"role": "operator",
"roles": ["operator"],
"scopes": [