diff --git a/src/lib/ws-client.js b/src/lib/ws-client.js index 6d03c85..40146c9 100644 --- a/src/lib/ws-client.js +++ b/src/lib/ws-client.js @@ -10,6 +10,8 @@ * 6. 开始正常通信 */ import { api } from './tauri-api.js' +import { t } from './i18n.js' +import { KERNEL_TARGET } from './feature-catalog.js' export function uuid() { if (crypto.randomUUID) return crypto.randomUUID() @@ -53,6 +55,27 @@ function isMethodUnsupportedError(err) { return false } +/** + * 判断 Gateway 关闭原因是否暗示 v3 协议 / 签名 payload 不被支持。 + * 老内核(仅 v1/v2 签名 payload,minProtocol < 3)会用类似 `device signature invalid` + * 或 `protocol mismatch` 关闭,字面对小白用户毫无意义,需要替换为人话。 + */ +function isProtocolIncompatReason(reason) { + return /signature\s+invalid|invalid\s+signature|protocol\s+mismatch|unsupported\s+protocol|min(imum)?\s*protocol|max(imum)?\s*protocol/i.test(reason || '') +} + +/** + * 构造「Gateway 内核过旧、不支持当前握手协议」的友好提示文案。 + * 直接读 feature-catalog 的 KERNEL_TARGET 常量,避免循环依赖 kernel.js。 + */ +function kernelTooOldMessage() { + const recommended = + KERNEL_TARGET?.openclaw?.chinese || + KERNEL_TARGET?.openclaw?.official || + '2026.5.x' + return t('kernel.tooOldForProtocol', { recommended }) +} + export class WsClient { constructor() { this._ws = null @@ -306,7 +329,16 @@ export class WsClient { }, 30000) return } - // 其他 1008(如 invalid role、protocol mismatch)→ 显示错误 + // Gateway 内核过旧:不支持 ClawPanel 0.15+ 使用的 v3 签名 payload / minProtocol=3 + // 关闭 reason 通常是 'device signature invalid' / 'protocol mismatch' + if (isProtocolIncompatReason(reason)) { + console.warn('[ws] Gateway 协议/签名不兼容(内核过旧):', e.reason) + this._intentionalClose = true + this._flushPending() + this._setConnected(false, 'error', kernelTooOldMessage()) + return + } + // 其他 1008(如 invalid role)→ 显示错误 console.warn('[ws] 收到 1008 关闭:', e.reason) this._setConnected(false, 'error', e.reason || '连接被 Gateway 拒绝') return @@ -438,6 +470,24 @@ export class WsClient { return } + // Gateway 内核过旧:自动配对后仍签名失败,或上游已明确返回协议不兼容 + // → 大概率是老 Gateway 不识别 v3 payload / minProtocol=3,给「内核过旧」提示 + if (!handled && ( + detailCode === 'DEVICE_AUTH_SIGNATURE_INVALID' || + detailCode === 'DEVICE_AUTH_INVALID' || + detailCode === 'PROTOCOL_VERSION_MISMATCH' || + detailCode === 'UNSUPPORTED_PROTOCOL' + )) { + const friendly = kernelTooOldMessage() + this._intentionalClose = true + this._flushPending() + this._setConnected(false, 'error', friendly) + this._readyCallbacks.forEach(fn => { + try { fn(null, null, { error: true, message: friendly, detailCode, nextStep }) } catch {} + }) + return + } + // 使用 recommendedNextStep 给用户更好的提示 const hints = { 'retry_with_device_token': '设备令牌需要更新,请重启面板', diff --git a/src/locales/en.json b/src/locales/en.json index a135422..bc9b3cc 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2237,7 +2237,8 @@ "title": "New kernel available", "subtitle": "{from} → {to}, click to upgrade", "dismissTooltip": "Don't remind me this session" - } + }, + "tooOldForProtocol": "Gateway kernel is too old and does not support the handshake protocol used by this ClawPanel. Please upgrade the OpenClaw kernel to the recommended version ({recommended}) and retry. You can upgrade from \"Services → OpenClaw → Upgrade\"." }, "cliConflict": { "title": "Detected {count} possibly conflicting OpenClaw installation(s)", diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index 50179c9..68f30cc 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -2320,7 +2320,8 @@ "title": "有新内核可用", "subtitle": "{from} → {to},点此一键升级", "dismissTooltip": "本次会话不再提醒" - } + }, + "tooOldForProtocol": "Gateway 内核版本过旧,不兼容当前 ClawPanel 使用的握手协议。请把 OpenClaw 内核升级到推荐版本({recommended})后重试。可在「服务管理 → OpenClaw → 一键升级」中完成升级。" }, "cliConflict": { "title": "检测到 {count} 处可能冲突的 OpenClaw 安装",