diff --git a/docs/zh-CN/cli/devices.md b/docs/zh-CN/cli/devices.md index cebfc430a..1a6800f45 100644 --- a/docs/zh-CN/cli/devices.md +++ b/docs/zh-CN/cli/devices.md @@ -1,40 +1,40 @@ --- read_when: - 你正在批准设备配对请求 - - 你需要轮换或吊销设备 token -summary: '`openclaw devices` 的 CLI 参考(设备配对 + token 轮换/吊销)' + - 你需要轮换或撤销设备令牌 +summary: '`openclaw devices` 的 CLI 参考(设备配对 + 令牌轮换/撤销)' title: 设备 x-i18n: - generated_at: "2026-04-27T06:03:16Z" + generated_at: "2026-04-27T14:14:31Z" model: gpt-5.4 provider: openai - source_hash: df4240f8f9f4dc873c954e4bdb9697c13c1f7045951b13ad749ad3e82599f247 + source_hash: df105135a12ec733e45a67792e8447628f1538fc2536a008d615d46d1eaff5c8 source_path: cli/devices.md workflow: 15 --- # `openclaw devices` -管理设备配对请求和设备范围的 token。 +管理设备配对请求和设备作用域令牌。 ## 命令 ### `openclaw devices list` -列出待处理的配对请求和已配对的设备。 +列出待处理的配对请求和已配对设备。 ``` openclaw devices list openclaw devices list --json ``` -当设备已经配对时,待处理请求的输出会在该设备当前已批准的访问权限旁边显示其请求的访问权限。这样可以明确显示 scope/role 升级,而不会看起来像是配对已丢失。 +当设备已配对时,待处理请求的输出会在该设备当前已批准的访问权限旁显示所请求的访问权限。这样可以明确展示作用域/角色升级,而不是看起来像配对已丢失。 ### `openclaw devices remove ` -移除一个已配对的设备条目。 +删除一个已配对设备条目。 -当你使用已配对设备 token 完成认证时,非管理员调用方只能移除**自己的**设备条目。移除其他设备需要 `operator.admin`。 +当你使用已配对设备令牌进行身份验证时,非管理员调用方只能删除**自己的**设备条目。删除其他设备需要 `operator.admin`。 ``` openclaw devices remove @@ -56,12 +56,12 @@ openclaw devices clear --yes --pending --json 通过精确的 `requestId` 批准待处理的设备配对请求。如果省略 `requestId` 或传入 `--latest`,OpenClaw 只会打印所选的待处理请求并退出;在核实详细信息后,请使用精确的请求 ID 重新运行批准命令。 -如果设备在认证详情发生变化后重试配对(role、scopes 或 public key),OpenClaw 会替换之前的待处理条目并发出新的 `requestId`。请在批准前立即运行 `openclaw devices list`,以使用当前 ID。 +如果设备使用变更后的认证详情(角色、作用域或公钥)重试配对,OpenClaw 会取代之前的待处理条目并签发一个新的 `requestId`。请在批准前立即运行 `openclaw devices list` 以使用当前 ID。 -如果设备已经配对,并请求更宽的 scopes 或更高的 role,OpenClaw 会保留现有批准,并创建一个新的待处理升级请求。请查看 `openclaw devices list` 中的 `Requested` 与 `Approved` 列,或使用 `openclaw devices approve --latest` 预览确切的升级内容,然后再批准。 +如果设备已配对且请求更宽泛的作用域或更高的角色,OpenClaw 会保留现有批准状态,并创建一个新的待处理升级请求。在批准前,请查看 `openclaw devices list` 中的 `Requested` 与 `Approved` 列,或使用 `openclaw devices approve --latest` 预览精确的升级内容。 -如果 Gateway 网关 显式配置了 `gateway.nodes.pairing.autoApproveCidrs`,则来自匹配客户端 IP 的首次 `role: node` 请求,可能会在出现在此列表之前就被批准。该策略默认禁用,且绝不会应用于 operator/browser 客户端或升级请求。 +如果 Gateway 网关 已显式配置 `gateway.nodes.pairing.autoApproveCidrs`,来自匹配客户端 IP 的首次 `role: node` 请求可能会在出现在此列表之前就被批准。该策略默认禁用,且绝不会应用于 operator/browser 客户端或升级请求。 ``` openclaw devices approve @@ -79,61 +79,61 @@ openclaw devices reject ### `openclaw devices rotate --device --role [--scope ]` -为特定 role 轮换设备 token(可选地更新 scopes)。 -目标 role 必须已存在于该设备已批准的配对契约中;轮换不能铸造新的未批准 role。 -如果你省略 `--scope`,后续使用存储的已轮换 token 重新连接时,会复用该 token 缓存的已批准 scopes。如果你显式传入 `--scope` 值,这些值将成为未来基于缓存 token 重连时存储的 scope 集合。 -非管理员的已配对设备调用方只能轮换**自己的**设备 token。 -目标 token 的 scope 集合还必须保持在调用方当前会话自身的 operator scopes 范围内;轮换不能铸造或保留比调用方当前拥有的权限更高的 operator token。 +为特定角色轮换设备令牌(可选地更新作用域)。 +目标角色必须已存在于该设备已批准的配对契约中;轮换不能铸造新的未批准角色。 +如果你省略 `--scope`,之后使用已存储的轮换后令牌重新连接时,会复用该令牌缓存的已批准作用域。如果你传入显式的 `--scope` 值,这些值将成为未来缓存令牌重新连接时所使用的已存储作用域集合。 +非管理员已配对设备调用方只能轮换**自己的**设备令牌。 +目标令牌的作用域集合必须保持在调用方当前会话自身的 operator 作用域范围内;轮换不能铸造或保留比调用方当前拥有的更宽泛的 operator 令牌。 ``` openclaw devices rotate --device --role operator --scope operator.read --scope operator.write ``` -以 JSON 返回新的 token 负载。 +以 JSON 格式返回轮换元数据。如果调用方正在轮换自己的令牌,且当前使用该设备令牌进行身份验证,则响应还会包含替换令牌,以便客户端在重新连接前持久化保存。共享/管理员轮换不会回显 bearer token。 ### `openclaw devices revoke --device --role ` -吊销特定 role 的设备 token。 +撤销特定角色的设备令牌。 -非管理员的已配对设备调用方只能吊销**自己的**设备 token。 -吊销其他设备的 token 需要 `operator.admin`。 -目标 token 的 scope 集合也必须适配调用方当前会话自身的 operator scopes;仅具备配对权限的调用方不能吊销 admin/write operator token。 +非管理员已配对设备调用方只能撤销**自己的**设备令牌。 +撤销其他设备的令牌需要 `operator.admin`。 +目标令牌的作用域集合也必须符合调用方当前会话自身的 operator 作用域;仅具备配对权限的调用方不能撤销 admin/write operator 令牌。 ``` openclaw devices revoke --device --role node ``` -以 JSON 返回吊销结果。 +以 JSON 格式返回撤销结果。 ## 常用选项 -- `--url `:Gateway 网关 WebSocket URL(配置后默认使用 `gateway.remote.url`)。 -- `--token `:Gateway 网关 token(如需要)。 -- `--password `:Gateway 网关 密码(密码认证)。 +- `--url `:Gateway 网关 WebSocket URL(配置时默认使用 `gateway.remote.url`)。 +- `--token `:Gateway 网关令牌(如果需要)。 +- `--password `:Gateway 网关密码(密码认证)。 - `--timeout `:RPC 超时。 - `--json`:JSON 输出(推荐用于脚本)。 -当你设置 `--url` 时,CLI 不会回退到配置或环境变量凭证。请显式传入 `--token` 或 `--password`。缺少显式凭证会报错。 +当你设置 `--url` 时,CLI 不会回退到配置或环境变量凭证。请显式传入 `--token` 或 `--password`。如果缺少显式凭证,将报错。 ## 说明 -- token 轮换会返回一个新的 token(敏感信息)。请像对待密钥一样对待它。 -- 这些命令需要 `operator.pairing`(或 `operator.admin`)scope。 -- `gateway.nodes.pairing.autoApproveCidrs` 是一个仅适用于新节点设备配对的可选启用 Gateway 网关 策略;它不会改变 CLI 的批准权限。 -- token 轮换和吊销始终受限于该设备已批准的配对 role 集合和已批准的基础 scope。意外残留的缓存 token 条目不会授予 token 管理目标。 -- 对于已配对设备 token 会话,跨设备管理仅限管理员:`remove`、`rotate` 和 `revoke` 都只能操作自己,除非调用方拥有 `operator.admin`。 -- token 变更也受调用方 scope 限制:仅具备配对权限的会话不能轮换或吊销当前携带 `operator.admin` 或 `operator.write` 的 token。 -- `devices clear` 刻意要求 `--yes` 作为保护门槛。 -- 如果 local loopback 上不可用配对 scope(且未显式传入 `--url`),`list/approve` 可以使用本地配对回退机制。 -- `devices approve` 在铸造 token 之前需要显式请求 ID;省略 `requestId` 或传入 `--latest` 只会预览最新的待处理请求。 +- 令牌轮换会返回一个新令牌(敏感信息)。请像对待密钥一样对待它。 +- 这些命令需要 `operator.pairing`(或 `operator.admin`)作用域。 +- `gateway.nodes.pairing.autoApproveCidrs` 是一项可选启用的 Gateway 网关策略,仅适用于新的节点设备配对;它不会改变 CLI 的批准权限。 +- 令牌轮换和撤销始终限制在该设备已批准的配对角色集合和已批准的作用域基线之内。一个游离的缓存令牌条目不会授予令牌管理目标。 +- 对于已配对设备令牌会话,跨设备管理仅限管理员:`remove`、`rotate` 和 `revoke` 仅限操作自身,除非调用方具有 `operator.admin`。 +- 令牌变更同样受调用方作用域限制:仅具备配对权限的会话不能轮换或撤销当前携带 `operator.admin` 或 `operator.write` 的令牌。 +- `devices clear` 被有意通过 `--yes` 进行保护。 +- 如果 local loopback 上不可用配对作用域(且未传入显式 `--url`),`list`/`approve` 可以使用本地配对回退。 +- `devices approve` 在铸造令牌前需要显式请求 ID;省略 `requestId` 或传入 `--latest` 只会预览最新的待处理请求。 -## token 漂移恢复检查清单 +## 令牌漂移恢复检查清单 当 Control UI 或其他客户端持续因 `AUTH_TOKEN_MISMATCH` 或 `AUTH_DEVICE_TOKEN_MISMATCH` 失败时,请使用此清单。 -1. 确认当前 Gateway 网关 token 来源: +1. 确认当前 Gateway 网关令牌来源: ```bash openclaw config get gateway.auth.token @@ -145,7 +145,7 @@ openclaw config get gateway.auth.token openclaw devices list ``` -3. 为受影响的设备轮换 operator token: +3. 为受影响设备轮换 operator 令牌: ```bash openclaw devices rotate --device --role operator @@ -159,19 +159,19 @@ openclaw devices list openclaw devices approve ``` -5. 使用当前共享 token/password 重试客户端连接。 +5. 使用当前共享令牌/密码重试客户端连接。 说明: -- 正常重连认证优先级依次为:显式共享 token/password、显式 `deviceToken`、存储的设备 token、bootstrap token。 -- 对于可信的 `AUTH_TOKEN_MISMATCH` 恢复,可以在一次受限重试中临时同时发送共享 token 和存储的设备 token。 +- 正常重连认证优先级依次为:显式共享令牌/密码,然后是显式 `deviceToken`,然后是已存储设备令牌,最后是引导令牌。 +- 可信的 `AUTH_TOKEN_MISMATCH` 恢复在一次受限重试中,可以临时同时发送共享令牌和已存储设备令牌。 相关内容: -- [Dashboard auth troubleshooting](/zh-CN/web/dashboard#if-you-see-unauthorized-1008) -- [Gateway troubleshooting](/zh-CN/gateway/troubleshooting#dashboard-control-ui-connectivity) +- [Dashboard 认证故障排除](/zh-CN/web/dashboard#if-you-see-unauthorized-1008) +- [Gateway 网关故障排除](/zh-CN/gateway/troubleshooting#dashboard-control-ui-connectivity) ## 相关 -- [CLI reference](/zh-CN/cli) -- [Nodes](/zh-CN/nodes) +- [CLI 参考](/zh-CN/cli) +- [节点](/zh-CN/nodes) diff --git a/docs/zh-CN/gateway/protocol.md b/docs/zh-CN/gateway/protocol.md index 583981e0c..bdc187f5e 100644 --- a/docs/zh-CN/gateway/protocol.md +++ b/docs/zh-CN/gateway/protocol.md @@ -6,25 +6,25 @@ read_when: summary: Gateway 网关 WebSocket 协议:握手、帧、版本控制 title: Gateway 网关协议 x-i18n: - generated_at: "2026-04-27T13:09:16Z" + generated_at: "2026-04-27T14:14:33Z" model: gpt-5.4 provider: openai - source_hash: 0cca49f3c8612e719ad97e1748cb263e8824e0e4c59548ba0809cb0bc095f363 + source_hash: db234f3b04b5a2c3b1a5f4c12f6b551efcdf616968b65b83abba88f86059a339 source_path: gateway/protocol.md workflow: 15 --- -Gateway 网关 WS 协议是 OpenClaw 的**单一控制平面 + 节点传输层**。所有客户端(CLI、web UI、macOS 应用、iOS/Android 节点、无头节点)都通过 WebSocket 连接,并在握手时声明其**角色** + **作用域**。 +Gateway 网关 WS 协议是 OpenClaw 的**单一控制平面 + 节点传输层**。所有客户端(CLI、Web UI、macOS 应用、iOS/Android 节点、无头节点)都通过 WebSocket 连接,并在握手时声明其**角色** + **作用域**。 ## 传输 - WebSocket,使用带有 JSON 负载的文本帧。 -- 第一帧**必须**是 `connect` 请求。 -- 连接前帧的大小上限为 64 KiB。成功握手后,客户端应遵循 `hello-ok.policy.maxPayload` 和 `hello-ok.policy.maxBufferedBytes` 限制。启用诊断后,过大的入站帧和缓慢的出站缓冲区会在 Gateway 网关关闭连接或丢弃受影响帧之前发出 `payload.large` 事件。这些事件会保留大小、限制、表面和安全原因代码。它们不会保留消息正文、附件内容、原始帧正文、令牌、cookie 或秘密值。 +- 第一帧**必须**是一个 `connect` 请求。 +- 连接前的帧大小上限为 64 KiB。成功握手后,客户端应遵循 `hello-ok.policy.maxPayload` 和 `hello-ok.policy.maxBufferedBytes` 的限制。启用诊断后,超大的入站帧和缓慢的出站缓冲区会在 Gateway 网关关闭连接或丢弃受影响帧之前发出 `payload.large` 事件。这些事件会保留大小、限制、表面和安全原因代码。它们不会保留消息正文、附件内容、原始帧正文、令牌、cookie 或秘密值。 ## 握手(connect) -Gateway 网关 → 客户端(连接前质询): +Gateway 网关 → 客户端(连接前挑战): ```json { @@ -95,9 +95,9 @@ Gateway 网关 → 客户端: } ``` -`server`、`features`、`snapshot` 和 `policy` 都是 schema 所要求的(`src/gateway/protocol/schema/frames.ts`)。`auth` 也是必需的,并报告协商后的角色/作用域。`canvasHostUrl` 是可选的。 +`server`、`features`、`snapshot` 和 `policy` 都是 schema(`src/gateway/protocol/schema/frames.ts`)要求的字段。`auth` 也是必需的,并会报告协商后的角色/作用域。`canvasHostUrl` 是可选的。 -未发放设备令牌时,`hello-ok.auth` 会报告协商后的权限,但不包含令牌字段: +当未签发设备令牌时,`hello-ok.auth` 会报告协商后的权限信息,但不包含令牌字段: ```json { @@ -108,9 +108,9 @@ Gateway 网关 → 客户端: } ``` -受信任的同进程后端客户端(`client.id: "gateway-client"`、`client.mode: "backend"`)在直接 loopback 连接上使用共享 Gateway 网关令牌/密码进行身份验证时,可以省略 `device`。此路径保留给内部控制平面 RPC,用于避免陈旧的 CLI/设备配对基线阻塞本地后端工作,例如子智能体会话更新。远程客户端、源自浏览器的客户端、节点客户端,以及显式设备令牌/设备身份客户端,仍会使用正常的配对和作用域升级检查。 +受信任的同进程后端客户端(`client.id: "gateway-client"`、`client.mode: "backend"`)在直接 loopback 连接上使用共享 Gateway 网关令牌/密码进行认证时,可以省略 `device`。此路径仅保留给内部控制平面 RPC,用于避免过期的 CLI/设备配对基线阻塞本地后端工作,例如子智能体会话更新。远程客户端、浏览器来源客户端、节点客户端以及显式设备令牌/设备身份客户端仍然使用正常的配对和作用域升级检查。 -发放设备令牌时,`hello-ok` 还会包含: +当签发设备令牌时,`hello-ok` 还会包含: ```json { @@ -122,7 +122,7 @@ Gateway 网关 → 客户端: } ``` -在受信任的引导移交流程中,`hello-ok.auth` 还可能在 `deviceTokens` 中包含额外的有界角色条目: +在受信任的 bootstrap 交接期间,`hello-ok.auth` 还可能在 `deviceTokens` 中包含额外的有界角色条目: ```json { @@ -141,7 +141,7 @@ Gateway 网关 → 客户端: } ``` -对于内置的节点/操作员引导流程,主节点令牌保持为 `scopes: []`,而任何移交的操作员令牌都保持受限于引导操作员允许列表(`operator.approvals`、`operator.read`、`operator.talk.secrets`、`operator.write`)。引导作用域检查保持角色前缀规则:操作员条目仅满足操作员请求,而非操作员角色仍需要其自身角色前缀下的作用域。 +对于内置的 node/operator bootstrap 流程,主 node 令牌保持 `scopes: []`,任何交接的 operator 令牌都保持限制在 bootstrap operator allowlist(`operator.approvals`、`operator.read`、`operator.talk.secrets`、`operator.write`)内。Bootstrap 作用域检查仍按角色前缀进行:operator 条目仅满足 operator 请求,非 operator 角色仍需要其自身角色前缀下的作用域。 ### 节点示例 @@ -184,7 +184,7 @@ Gateway 网关 → 客户端: - **响应**:`{type:"res", id, ok, payload|error}` - **事件**:`{type:"event", event, payload, seq?, stateVersion?}` -有副作用的方法需要 **idempotency keys**(参见 schema)。 +有副作用的方法需要 **幂等键**(参见 schema)。 ## 角色 + 作用域 @@ -206,11 +206,11 @@ Gateway 网关 → 客户端: 带有 `includeSecrets: true` 的 `talk.config` 需要 `operator.talk.secrets`(或 `operator.admin`)。 -由插件注册的 Gateway 网关 RPC 方法可以请求其自己的操作员作用域,但保留的核心管理员前缀(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)始终解析为 `operator.admin`。 +插件注册的 Gateway 网关 RPC 方法可以请求它们自己的 operator 作用域,但保留的核心 admin 前缀(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)始终解析为 `operator.admin`。 -方法作用域只是第一道门。通过 `chat.send` 到达的一些斜杠命令还会在其之上应用更严格的命令级检查。例如,持久化的 `/config set` 和 `/config unset` 写入需要 `operator.admin`。 +方法作用域只是第一道门槛。通过 `chat.send` 到达的一些斜杠命令会在此基础上应用更严格的命令级检查。例如,持久化的 `/config set` 和 `/config unset` 写入需要 `operator.admin`。 -`node.pair.approve` 在基础方法作用域之上还带有额外的审批时作用域检查: +`node.pair.approve` 也在基础方法作用域之上增加了额外的审批时作用域检查: - 无命令请求:`operator.pairing` - 带有非 exec 节点命令的请求:`operator.pairing` + `operator.write` @@ -218,39 +218,39 @@ Gateway 网关 → 客户端: ### 能力/命令/权限(node) -节点在连接时声明能力主张: +节点在连接时声明能力声明: -- `caps`:高层能力类别。 -- `commands`:用于 invoke 的命令允许列表。 +- `caps`:高层级能力类别。 +- `commands`:用于 invoke 的命令 allowlist。 - `permissions`:细粒度开关(例如 `screen.record`、`camera.capture`)。 -Gateway 网关将这些视为**主张**,并在服务端强制执行允许列表。 +Gateway 网关将这些视为**声明**,并在服务端执行 allowlist 限制。 ## 在线状态 -- `system-presence` 返回按设备身份键控的条目。 -- 在线状态条目包含 `deviceId`、`roles` 和 `scopes`,因此 UI 即使在设备同时以 **operator** 和 **node** 身份连接时,也能为每台设备显示单独一行。 +- `system-presence` 返回按设备身份作为键的条目。 +- 在线状态条目包含 `deviceId`、`roles` 和 `scopes`,以便 UI 在设备同时以 **operator** 和 **node** 连接时,仍可为其显示单独一行。 -## 广播事件作用域 +## 广播事件作用域限制 -服务器推送的 WebSocket 广播事件受作用域门控,因此仅有配对作用域或仅节点的会话不会被动接收会话内容。 +服务端推送的 WebSocket 广播事件会按作用域进行限制,因此仅具备配对作用域或仅限节点的会话不会被动接收会话内容。 - **聊天、智能体和工具结果帧**(包括流式 `agent` 事件和工具调用结果)至少需要 `operator.read`。没有 `operator.read` 的会话会完全跳过这些帧。 -- **插件定义的 `plugin.*` 广播** 会根据插件注册方式,被门控为需要 `operator.write` 或 `operator.admin`。 -- **状态和传输事件**(`heartbeat`、`presence`、`tick`、连接/断开生命周期等)保持不受限制,以便每个已认证会话都能观察传输健康状态。 -- **未知广播事件族** 默认进行作用域门控(失败即关闭),除非已注册处理程序明确放宽它们。 +- **插件定义的 `plugin.*` 广播** 会根据插件注册方式限制为 `operator.write` 或 `operator.admin`。 +- **Status 和传输事件**(`heartbeat`、`presence`、`tick`、连接/断开生命周期等)仍然不受限制,以便每个已认证会话都能观察传输健康状态。 +- **未知广播事件家族** 默认按作用域限制(失败时关闭),除非已注册处理器显式放宽。 -每个客户端连接都维护自己的每客户端序列号,因此即使不同客户端看到的事件流子集因作用域过滤而不同,广播在该 socket 上仍会保持单调顺序。 +每个客户端连接都维护其自己的每客户端序列号,因此即使不同客户端看到的事件流子集因作用域过滤而不同,广播仍能在该 socket 上保持单调排序。 ## 常见 RPC 方法族 -公共 WS 表面比上面的握手/认证示例更广。这不是生成的导出——`hello-ok.features.methods` 是基于 `src/gateway/server-methods-list.ts` 加上已加载的插件/渠道方法导出构建的保守发现列表。请将其视为功能发现,而不是 `src/gateway/server-methods/*.ts` 的完整枚举。 +公共 WS 表面比上面的握手/认证示例更广。这不是生成的转储——`hello-ok.features.methods` 是一个保守的发现列表,由 `src/gateway/server-methods-list.ts` 和已加载的插件/渠道方法导出构建而成。应将其视为功能发现,而不是对 `src/gateway/server-methods/*.ts` 的完整枚举。 - - - `health` 返回缓存的或新近探测的 Gateway 网关健康快照。 - - `diagnostics.stability` 返回最近的有界诊断稳定性记录器。它会保留操作元数据,例如事件名称、计数、字节大小、内存读数、队列/会话状态、渠道/插件名称以及会话 id。它不会保留聊天文本、webhook 正文、工具输出、原始请求或响应正文、令牌、cookie 或秘密值。需要 operator.read 作用域。 - - `status` 返回 `/status` 风格的 Gateway 网关摘要;敏感字段仅对具有管理员作用域的操作员客户端包含。 + + - `health` 返回缓存的或新探测的 Gateway 网关健康快照。 + - `diagnostics.stability` 返回最近的有界诊断稳定性记录器。它会保留诸如事件名称、计数、字节大小、内存读数、队列/会话状态、渠道/插件名称以及会话 id 等操作元数据。它不会保留聊天文本、webhook 正文、工具输出、原始请求或响应正文、令牌、cookie 或秘密值。需要 operator.read 作用域。 + - `status` 返回 `/status` 风格的 Gateway 网关摘要;敏感字段仅对具有 admin 作用域的 operator 客户端包含。 - `gateway.identity.get` 返回 relay 和配对流程使用的 Gateway 网关设备身份。 - `system-presence` 返回当前已连接 operator/node 设备的在线状态快照。 - `system-event` 追加一个系统事件,并可更新/广播在线状态上下文。 @@ -258,69 +258,69 @@ Gateway 网关将这些视为**主张**,并在服务端强制执行允许列 - `set-heartbeats` 切换 Gateway 网关上的 heartbeat 处理。 - + - `models.list` 返回运行时允许的模型目录。 - `usage.status` 返回提供商用量窗口/剩余额度摘要。 - - `usage.cost` 返回指定日期范围的聚合成本用量摘要。 - - `doctor.memory.status` 返回活动默认 Agent 工作区的向量内存 / 缓存嵌入就绪状态。仅当调用方明确需要实时嵌入提供商 ping 时,才传递 `{ "probe": true }` 或 `{ "deep": true }`。 + - `usage.cost` 返回某个日期范围内聚合的成本用量摘要。 + - `doctor.memory.status` 返回当前默认 Agent 工作区的向量记忆/缓存 embedding 就绪状态。仅当调用方明确希望实时 ping embedding 提供商时,才传入 `{ "probe": true }` 或 `{ "deep": true }`。 - `sessions.usage` 返回每个会话的用量摘要。 - - `sessions.usage.timeseries` 返回单个会话的时间序列用量。 + - `sessions.usage.timeseries` 返回单个会话的时序用量数据。 - `sessions.usage.logs` 返回单个会话的用量日志条目。 - - `channels.status` 返回内置 + 内置打包的渠道/插件状态摘要。 - - `channels.logout` 在该渠道支持登出的情况下,从特定渠道/账号登出。 - - `web.login.start` 为当前支持 QR 的 web 渠道 provider 启动 QR/web 登录流程。 - - `web.login.wait` 等待该 QR/web 登录流程完成,并在成功后启动渠道。 + - `channels.status` 返回内置 + 内置打包的渠道/插件 Status 摘要。 + - `channels.logout` 在渠道支持登出的情况下,登出特定渠道/账户。 + - `web.login.start` 为当前支持 QR 的 Web 渠道提供商启动 QR/Web 登录流程。 + - `web.login.wait` 等待该 QR/Web 登录流程完成,并在成功后启动渠道。 - `push.test` 向已注册的 iOS 节点发送测试 APNs 推送。 - - `voicewake.get` 返回已存储的唤醒词触发器。 - - `voicewake.set` 更新唤醒词触发器并广播该变更。 + - `voicewake.get` 返回存储的唤醒词触发器。 + - `voicewake.set` 更新唤醒词触发器并广播变更。 - - - `send` 是用于渠道/账号/线程目标发送的直接出站投递 RPC,在 chat runner 之外使用。 - - `logs.tail` 返回已配置的 Gateway 网关文件日志尾部,并带有 cursor/limit 和最大字节数控制。 + + - `send` 是 chat runner 之外、用于面向渠道/账户/线程目标发送的直接出站投递 RPC。 + - `logs.tail` 返回已配置的 Gateway 网关文件日志 tail,并带有 cursor/limit 和最大字节数控制。 - `talk.config` 返回生效的 Talk 配置负载;`includeSecrets` 需要 `operator.talk.secrets`(或 `operator.admin`)。 - `talk.mode` 为 WebChat/Control UI 客户端设置/广播当前 Talk 模式状态。 - - `talk.speak` 通过当前激活的 Talk speech provider 合成语音。 - - `tts.status` 返回 TTS 启用状态、活动 provider、回退 provider 以及 provider 配置状态。 - - `tts.providers` 返回可见的 TTS provider 清单。 + - `talk.speak` 通过当前激活的 Talk 语音提供商合成语音。 + - `tts.status` 返回 TTS 启用状态、当前提供商、后备提供商以及提供商配置状态。 + - `tts.providers` 返回可见的 TTS 提供商清单。 - `tts.enable` 和 `tts.disable` 切换 TTS 偏好设置状态。 - - `tts.setProvider` 更新首选 TTS provider。 + - `tts.setProvider` 更新首选 TTS 提供商。 - `tts.convert` 执行一次性文本转语音转换。 - - `secrets.reload` 重新解析活动的 SecretRefs,并且仅在完全成功时才切换运行时秘密状态。 - - `secrets.resolve` 为特定命令/目标集解析命令目标秘密赋值。 + - `secrets.reload` 重新解析活跃的 SecretRef,并仅在完全成功时切换运行时秘密状态。 + - `secrets.resolve` 为特定命令/目标集解析命令目标秘密分配。 - `config.get` 返回当前配置快照和哈希值。 - `config.set` 写入经过验证的配置负载。 - `config.patch` 合并部分配置更新。 - `config.apply` 验证并替换完整配置负载。 - - `config.schema` 返回 Control UI 和 CLI 工具使用的实时配置 schema 负载:schema、`uiHints`、版本和生成元数据,包括当运行时能够加载时的插件 + 渠道 schema 元数据。该 schema 包含源自 UI 所用相同标签和帮助文本的字段 `title` / `description` 元数据,包括嵌套对象、通配符、数组项以及 `anyOf` / `oneOf` / `allOf` 组合分支,只要存在匹配的字段文档。 - - `config.schema.lookup` 返回单个配置路径的路径作用域查找负载:规范化路径、浅层 schema 节点、匹配的提示 + `hintPath`,以及用于 UI/CLI 深入查看的直接子项摘要。查找 schema 节点保留面向用户的文档和常见验证字段(`title`、`description`、`type`、`enum`、`const`、`format`、`pattern`、数值/字符串/数组/对象边界,以及如 `additionalProperties`、`deprecated`、`readOnly`、`writeOnly` 之类的标志)。子项摘要公开 `key`、规范化后的 `path`、`type`、`required`、`hasChildren`,以及匹配的 `hint` / `hintPath`。 - - `update.run` 运行 Gateway 网关更新流程,并且仅当更新本身成功时才安排重启。 - - `update.status` 返回最新缓存的更新重启哨兵,包括可用时的重启后运行版本。 + - `config.schema` 返回由 Control UI 和 CLI 工具使用的实时配置 schema 负载:schema、`uiHints`、版本和生成元数据;当运行时可以加载时,还包括插件 + 渠道 schema 元数据。该 schema 包含字段 `title` / `description` 元数据,这些元数据来自 UI 使用的相同标签和帮助文本;当存在匹配字段文档时,也包括嵌套对象、通配符、数组项以及 `anyOf` / `oneOf` / `allOf` 组合分支。 + - `config.schema.lookup` 为单个配置路径返回路径范围的查找负载:标准化路径、浅层 schema 节点、匹配的 hint + `hintPath`,以及用于 UI/CLI 下钻的直接子项摘要。查找 schema 节点保留面向用户的文档和常见验证字段(`title`、`description`、`type`、`enum`、`const`、`format`、`pattern`、数值/字符串/数组/对象边界,以及 `additionalProperties`、`deprecated`、`readOnly`、`writeOnly` 等标志)。子项摘要公开 `key`、标准化后的 `path`、`type`、`required`、`hasChildren`,以及匹配的 `hint` / `hintPath`。 + - `update.run` 运行 Gateway 网关更新流程,并仅在更新本身成功时安排重启。 + - `update.status` 返回最新缓存的更新重启哨兵信息,并在可用时包含重启后的运行版本。 - `wizard.start`、`wizard.next`、`wizard.status` 和 `wizard.cancel` 通过 WS RPC 暴露新手引导向导。 - `agents.list` 返回已配置的智能体条目。 - `agents.create`、`agents.update` 和 `agents.delete` 管理智能体记录和工作区连线。 - - `agents.files.list`、`agents.files.get` 和 `agents.files.set` 管理为智能体公开的引导工作区文件。 + - `agents.files.list`、`agents.files.get` 和 `agents.files.set` 管理为某个智能体暴露的 bootstrap 工作区文件。 - `agent.identity.get` 返回某个智能体或会话的生效助手身份。 - - `agent.wait` 等待某次运行结束,并在可用时返回终态快照。 + - `agent.wait` 等待一次运行完成,并在可用时返回终态快照。 - `sessions.list` 返回当前会话索引。 - `sessions.subscribe` 和 `sessions.unsubscribe` 为当前 WS 客户端切换会话变更事件订阅。 - - `sessions.messages.subscribe` 和 `sessions.messages.unsubscribe` 为单个会话切换转录/消息事件订阅。 - - `sessions.preview` 返回特定会话键的有界转录预览。 + - `sessions.messages.subscribe` 和 `sessions.messages.unsubscribe` 为某个会话切换 transcript/消息事件订阅。 + - `sessions.preview` 返回特定会话键的有界 transcript 预览。 - `sessions.resolve` 解析或规范化会话目标。 - `sessions.create` 创建新的会话条目。 - `sessions.send` 向现有会话发送消息。 @@ -329,120 +329,120 @@ Gateway 网关将这些视为**主张**,并在服务端强制执行允许列 - `sessions.patch` 更新会话元数据/覆盖项。 - `sessions.reset`、`sessions.delete` 和 `sessions.compact` 执行会话维护。 - `sessions.get` 返回完整存储的会话行。 - - 聊天执行仍使用 `chat.history`、`chat.send`、`chat.abort` 和 `chat.inject`。`chat.history` 会为 UI 客户端进行显示规范化:内联指令标签会从可见文本中剥离,纯文本工具调用 XML 负载(包括 `...`、`...`、`...`、`...` 以及截断的工具调用块)和泄露的 ASCII/全角模型控制令牌会被移除,纯静默令牌的助手行(例如精确的 `NO_REPLY` / `no_reply`)会被省略,过大的行可被占位符替换。 + - 聊天执行仍使用 `chat.history`、`chat.send`、`chat.abort` 和 `chat.inject`。`chat.history` 已为 UI 客户端做显示规范化:内联指令标签会从可见文本中移除,纯文本工具调用 XML 负载(包括 `...`、`...`、`...`、`...` 以及被截断的工具调用块)和泄露的 ASCII/全角模型控制令牌会被移除,纯静默令牌的助手行(例如精确的 `NO_REPLY` / `no_reply`)会被省略,而超大行可能会被占位符替换。 - - `device.pair.list` 返回待处理和已批准的已配对设备。 + - `device.pair.list` 返回待处理和已批准的配对设备。 - `device.pair.approve`、`device.pair.reject` 和 `device.pair.remove` 管理设备配对记录。 - - `device.token.rotate` 在其已批准角色和调用方作用域边界内轮换已配对设备令牌。 - - `device.token.revoke` 在其已批准角色和调用方作用域边界内撤销已配对设备令牌。 + - `device.token.rotate` 在已批准角色和调用方作用域边界内轮换配对设备令牌。 + - `device.token.revoke` 在已批准角色和调用方作用域边界内吊销配对设备令牌。 - - `node.pair.request`、`node.pair.list`、`node.pair.approve`、`node.pair.reject`、`node.pair.remove` 和 `node.pair.verify` 涵盖节点配对和引导验证。 + - `node.pair.request`、`node.pair.list`、`node.pair.approve`、`node.pair.reject`、`node.pair.remove` 和 `node.pair.verify` 涵盖节点配对和 bootstrap 验证。 - `node.list` 和 `node.describe` 返回已知/已连接的节点状态。 - `node.rename` 更新已配对节点标签。 - `node.invoke` 将命令转发到已连接节点。 - - `node.invoke.result` 返回调用请求的结果。 - - `node.event` 将节点来源事件回传到 Gateway 网关。 + - `node.invoke.result` 返回某个调用请求的结果。 + - `node.event` 将节点来源事件携带回 Gateway 网关。 - `node.canvas.capability.refresh` 刷新有作用域限制的 canvas 能力令牌。 - `node.pending.pull` 和 `node.pending.ack` 是已连接节点队列 API。 - - `node.pending.enqueue` 和 `node.pending.drain` 管理离线/断开连接节点的持久待处理工作。 + - `node.pending.enqueue` 和 `node.pending.drain` 为离线/断开连接的节点管理持久待处理工作。 - `exec.approval.request`、`exec.approval.get`、`exec.approval.list` 和 `exec.approval.resolve` 涵盖一次性 exec 审批请求,以及待处理审批的查找/重放。 - - `exec.approval.waitDecision` 等待单个待处理 exec 审批,并返回最终决定(或在超时时返回 `null`)。 + - `exec.approval.waitDecision` 等待一个待处理 exec 审批,并返回最终决定(超时时返回 `null`)。 - `exec.approvals.get` 和 `exec.approvals.set` 管理 Gateway 网关 exec 审批策略快照。 - `exec.approvals.node.get` 和 `exec.approvals.node.set` 通过节点中继命令管理节点本地 exec 审批策略。 - `plugin.approval.request`、`plugin.approval.list`、`plugin.approval.waitDecision` 和 `plugin.approval.resolve` 涵盖插件定义的审批流程。 - - 自动化:`wake` 安排立即或下一次 heartbeat 的唤醒文本注入;`cron.list`、`cron.status`、`cron.add`、`cron.update`、`cron.remove`、`cron.run`、`cron.runs` 管理计划任务。 + - 自动化:`wake` 安排立即或下一次 heartbeat 的唤醒文本注入;`cron.list`、`cron.status`、`cron.add`、`cron.update`、`cron.remove`、`cron.run`、`cron.runs` 管理计划工作。 - Skills 和工具:`commands.list`、`skills.*`、`tools.catalog`、`tools.effective`。 ### 常见事件族 -- `chat`:UI 聊天更新,例如 `chat.inject` 和其他仅转录的聊天事件。 -- `session.message` 和 `session.tool`:已订阅会话的转录/事件流更新。 +- `chat`:UI 聊天更新,例如 `chat.inject` 和其他仅 transcript 的聊天事件。 +- `session.message` 和 `session.tool`:已订阅会话的 transcript/事件流更新。 - `sessions.changed`:会话索引或元数据已更改。 - `presence`:系统在线状态快照更新。 -- `tick`:周期性 keepalive / 存活事件。 +- `tick`:定期 keepalive / 存活事件。 - `health`:Gateway 网关健康快照更新。 - `heartbeat`:heartbeat 事件流更新。 - `cron`:cron 运行/任务变更事件。 - `shutdown`:Gateway 网关关闭通知。 - `node.pair.requested` / `node.pair.resolved`:节点配对生命周期。 - `node.invoke.request`:节点调用请求广播。 -- `device.pair.requested` / `device.pair.resolved`:已配对设备生命周期。 +- `device.pair.requested` / `device.pair.resolved`:配对设备生命周期。 - `voicewake.changed`:唤醒词触发器配置已更改。 - `exec.approval.requested` / `exec.approval.resolved`:exec 审批生命周期。 - `plugin.approval.requested` / `plugin.approval.resolved`:插件审批生命周期。 ### 节点辅助方法 -- 节点可以调用 `skills.bins` 来获取当前 Skill 可执行文件列表,用于自动允许检查。 +- 节点可以调用 `skills.bins` 以获取当前 Skills 可执行文件列表,用于自动允许检查。 -### 操作员辅助方法 +### Operator 辅助方法 -- 操作员可以调用 `commands.list`(`operator.read`)来获取某个智能体的运行时命令清单。 +- Operator 可以调用 `commands.list`(`operator.read`)以获取某个智能体的运行时命令清单。 - `agentId` 是可选的;省略它可读取默认 Agent 工作区。 - - `scope` 控制主 `name` 目标指向哪个表面: + - `scope` 控制主 `name` 指向哪个表面: - `text` 返回不带前导 `/` 的主文本命令令牌 - - `native` 和默认的 `both` 路径在可用时返回 provider 感知的原生命名 + - `native` 以及默认的 `both` 路径在可用时返回 provider 感知的原生命名 - `textAliases` 携带精确的斜杠别名,例如 `/model` 和 `/m`。 - - `nativeName` 在存在时携带 provider 感知的原生命令名称。 - - `provider` 是可选的,并且只影响原生命名以及原生插件命令可用性。 - - `includeArgs=false` 会从响应中省略序列化的参数元数据。 -- 操作员可以调用 `tools.catalog`(`operator.read`)来获取某个智能体的运行时工具目录。响应包括分组工具和来源元数据: + - `nativeName` 在存在时携带 provider 感知的原生命令名。 + - `provider` 是可选的,仅影响原生命名以及原生插件命令可用性。 + - `includeArgs=false` 会从响应中省略序列化参数元数据。 +- Operator 可以调用 `tools.catalog`(`operator.read`)以获取某个智能体的运行时工具目录。响应包括分组工具和来源元数据: - `source`:`core` 或 `plugin` - `pluginId`:当 `source="plugin"` 时的插件所有者 - - `optional`:插件工具是否可选 -- 操作员可以调用 `tools.effective`(`operator.read`)来获取某个会话的运行时生效工具清单。 + - `optional`:某个插件工具是否为可选 +- Operator 可以调用 `tools.effective`(`operator.read`)以获取某个会话的运行时生效工具清单。 - `sessionKey` 是必需的。 - - Gateway 网关从服务端会话派生可信运行时上下文,而不是接受调用方提供的认证或投递上下文。 - - 响应具有会话作用域,并反映当前活动对话此刻可用的内容,包括 core、插件和渠道工具。 -- 操作员可以调用 `skills.status`(`operator.read`)来获取某个智能体的可见 Skill 清单。 + - Gateway 网关从服务端的会话派生受信任的运行时上下文,而不是接受调用方提供的认证或投递上下文。 + - 响应具有会话作用域,并反映当前活动对话此刻可使用的内容,包括核心、插件和渠道工具。 +- Operator 可以调用 `skills.status`(`operator.read`)以获取某个智能体的可见 Skills 清单。 - `agentId` 是可选的;省略它可读取默认 Agent 工作区。 - - 响应包括资格、缺失要求、配置检查以及已清洗的安装选项,不会暴露原始秘密值。 -- 操作员可以调用 `skills.search` 和 `skills.detail`(`operator.read`)来获取 ClawHub 发现元数据。 -- 操作员可以在两种模式下调用 `skills.install`(`operator.admin`): - - ClawHub 模式:`{ source: "clawhub", slug, version?, force? }` 将一个 Skill 文件夹安装到默认 Agent 工作区的 `skills/` 目录中。 - - Gateway 网关安装器模式:`{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }` 在 Gateway 网关主机上运行声明的 `metadata.openclaw.install` 操作。 -- 操作员可以在两种模式下调用 `skills.update`(`operator.admin`): - - ClawHub 模式会更新一个已跟踪 slug,或更新默认 Agent 工作区中所有已跟踪的 ClawHub 安装项。 + - 响应包括资格、缺失的要求、配置检查以及已清理的安装选项,且不会暴露原始秘密值。 +- Operator 可以调用 `skills.search` 和 `skills.detail`(`operator.read`)以获取 ClawHub 发现元数据。 +- Operator 可以通过两种模式调用 `skills.install`(`operator.admin`): + - ClawHub 模式:`{ source: "clawhub", slug, version?, force? }` 将一个 skill 文件夹安装到默认 Agent 工作区的 `skills/` 目录中。 + - Gateway 网关安装器模式:`{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }` 在 Gateway 网关宿主机上运行已声明的 `metadata.openclaw.install` 操作。 +- Operator 可以通过两种模式调用 `skills.update`(`operator.admin`): + - ClawHub 模式会更新一个已跟踪的 slug,或更新默认 Agent 工作区中所有已跟踪的 ClawHub 安装项。 - 配置模式会修补 `skills.entries.` 值,例如 `enabled`、`apiKey` 和 `env`。 ## Exec 审批 -- 当 exec 请求需要审批时,Gateway 网关会广播 `exec.approval.requested`。 -- 操作员客户端通过调用 `exec.approval.resolve` 来处理(需要 `operator.approvals` 作用域)。 -- 对于 `host=node`,`exec.approval.request` 必须包含 `systemRunPlan`(规范化的 `argv`/`cwd`/`rawCommand`/会话元数据)。缺少 `systemRunPlan` 的请求会被拒绝。 -- 审批后,转发的 `node.invoke system.run` 调用会复用该规范化的 `systemRunPlan` 作为权威命令/cwd/会话上下文。 -- 如果调用方在 prepare 和最终获批的 `system.run` 转发之间修改了 `command`、`rawCommand`、`cwd`、`agentId` 或 `sessionKey`,Gateway 网关将拒绝该运行,而不是信任被修改的负载。 +- 当某个 exec 请求需要审批时,Gateway 网关会广播 `exec.approval.requested`。 +- Operator 客户端通过调用 `exec.approval.resolve` 来处理(需要 `operator.approvals` 作用域)。 +- 对于 `host=node`,`exec.approval.request` 必须包含 `systemRunPlan`(规范的 `argv`/`cwd`/`rawCommand`/会话元数据)。缺少 `systemRunPlan` 的请求会被拒绝。 +- 审批后,转发的 `node.invoke system.run` 调用会复用该规范的 `systemRunPlan` 作为权威的命令/cwd/会话上下文。 +- 如果调用方在 prepare 与最终批准的 `system.run` 转发之间修改了 `command`、`rawCommand`、`cwd`、`agentId` 或 `sessionKey`,Gateway 网关会拒绝该运行,而不会信任被篡改的负载。 ## 智能体投递回退 -- `agent` 请求可以包含 `deliver=true` 来请求出站投递。 +- `agent` 请求可以包含 `deliver=true` 以请求出站投递。 - `bestEffortDeliver=false` 保持严格行为:未解析或仅内部的投递目标会返回 `INVALID_REQUEST`。 -- `bestEffortDeliver=true` 允许在无法解析外部可投递路由时回退为仅会话执行(例如内部/webchat 会话或含糊的多渠道配置)。 +- `bestEffortDeliver=true` 允许在无法解析出外部可投递路由时回退为仅会话执行(例如内部/webchat 会话或含糊的多渠道配置)。 ## 版本控制 - `PROTOCOL_VERSION` 位于 `src/gateway/protocol/schema/protocol-schemas.ts`。 -- 客户端发送 `minProtocol` + `maxProtocol`;服务器会拒绝不匹配。 -- Schemas + 模型从 TypeBox 定义生成: +- 客户端发送 `minProtocol` + `maxProtocol`;服务端会拒绝不匹配的情况。 +- Schemas + 模型由 TypeBox 定义生成: - `pnpm protocol:gen` - `pnpm protocol:gen:swift` - `pnpm protocol:check` ### 客户端常量 -`src/gateway/client.ts` 中的参考客户端使用这些默认值。这些值在协议 v3 中保持稳定,并且是第三方客户端的预期基线。 +`src/gateway/client.ts` 中的参考客户端使用这些默认值。这些值在协议 v3 中保持稳定,是第三方客户端的预期基线。 | 常量 | 默认值 | 来源 | | ----------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- | @@ -455,55 +455,56 @@ Gateway 网关将这些视为**主张**,并在服务端强制执行允许列 | `terminate()` 前的强制停止宽限期 | `250` ms | `FORCE_STOP_TERMINATE_GRACE_MS` | | `stopAndWait()` 默认超时 | `1_000` ms | `STOP_AND_WAIT_TIMEOUT_MS` | | 默认 tick 间隔(`hello-ok` 之前) | `30_000` ms | `src/gateway/client.ts` | -| tick 超时关闭 | 当静默超过 `tickIntervalMs * 2` 时,代码为 `4000` | `src/gateway/client.ts` | +| Tick 超时关闭 | 当静默超过 `tickIntervalMs * 2` 时使用代码 `4000` | `src/gateway/client.ts` | | `MAX_PAYLOAD_BYTES` | `25 * 1024 * 1024`(25 MB) | `src/gateway/server-constants.ts` | -服务器会在 `hello-ok` 中公布生效的 `policy.tickIntervalMs`、`policy.maxPayload` 和 `policy.maxBufferedBytes`;客户端应遵循这些值,而不是使用握手前的默认值。 +服务端会在 `hello-ok` 中通告生效的 `policy.tickIntervalMs`、`policy.maxPayload` 和 `policy.maxBufferedBytes`;客户端应遵循这些值,而不是握手前的默认值。 ## 认证 -- 基于共享密钥的 Gateway 网关认证使用 `connect.params.auth.token` 或 `connect.params.auth.password`,具体取决于已配置的认证模式。 -- 带身份的模式,例如 Tailscale Serve(`gateway.auth.allowTailscale: true`)或非 loopback 的 `gateway.auth.mode: "trusted-proxy"`,会通过请求头而不是 `connect.params.auth.*` 来满足连接认证检查。 -- 私有入口的 `gateway.auth.mode: "none"` 会完全跳过基于共享密钥的连接认证;不要在公开/不受信任的入口上暴露此模式。 -- 配对后,Gateway 网关会发出一个按连接角色 + 作用域限定的**设备令牌**。它会在 `hello-ok.auth.deviceToken` 中返回,客户端应将其持久化以供未来连接使用。 -- 客户端应在每次成功连接后持久化主 `hello-ok.auth.deviceToken`。 -- 使用该**已存储**设备令牌重新连接时,也应复用为该令牌存储的已批准作用域集合。这样可以保留已获授的读取/探测/状态访问权限,并避免重连时静默收窄为更窄的隐式仅管理员作用域。 -- 客户端侧连接认证组装(`src/gateway/client.ts` 中的 `selectConnectAuth`): - - `auth.password` 是正交项,设置后始终会被转发。 - - `auth.token` 按优先级填充:首先是显式共享令牌,然后是显式 `deviceToken`,最后是已存储的每设备令牌(按 `deviceId` + `role` 键控)。 - - 仅当以上都未解析出 `auth.token` 时,才会发送 `auth.bootstrapToken`。共享令牌或任何已解析设备令牌都会抑制它。 - - 在一次性的 `AUTH_TOKEN_MISMATCH` 重试中,自动提升已存储设备令牌仅对**受信任端点**开放——loopback,或带已固定 `tlsFingerprint` 的 `wss://`。未固定证书的公共 `wss://` 不符合条件。 -- 额外的 `hello-ok.auth.deviceTokens` 条目是引导移交令牌。仅当连接使用了受信任传输(如 `wss://` 或 loopback/本地配对)上的引导认证时,才持久化它们。 -- 如果客户端提供了**显式** `deviceToken` 或显式 `scopes`,则该调用方请求的作用域集合仍为权威;仅当客户端复用已存储的每设备令牌时,才会复用缓存作用域。 -- 设备令牌可通过 `device.token.rotate` 和 `device.token.revoke` 进行轮换/撤销(需要 `operator.pairing` 作用域)。 -- 令牌发放、轮换和撤销始终受限于该设备配对条目中记录的已批准角色集合;令牌变更不能扩展到或针对配对审批从未授予的设备角色。 -- 对于已配对设备令牌会话,设备管理默认仅限自身作用域,除非调用方还具有 `operator.admin`:非管理员调用方只能移除/撤销/轮换其**自己的**设备条目。 -- `device.token.rotate` 和 `device.token.revoke` 还会根据调用方当前会话作用域检查目标操作员令牌作用域集合。非管理员调用方不能轮换或撤销比自己当前持有更宽的操作员令牌。 -- 认证失败会包含 `error.details.code` 和恢复提示: +- 共享密钥 Gateway 网关认证使用 `connect.params.auth.token` 或 `connect.params.auth.password`,具体取决于已配置的认证模式。 +- 带身份的模式,例如 Tailscale Serve(`gateway.auth.allowTailscale: true`)或非 loopback 的 `gateway.auth.mode: "trusted-proxy"`,会通过请求头而不是 `connect.params.auth.*` 来满足 connect 认证检查。 +- 私有入口的 `gateway.auth.mode: "none"` 会完全跳过共享密钥 connect 认证;不要在公共/不受信任入口上暴露该模式。 +- 配对后,Gateway 网关会签发一个**设备令牌**,其作用域受连接角色 + 作用域限制。它会在 `hello-ok.auth.deviceToken` 中返回,客户端应将其持久化以供未来连接使用。 +- 客户端应在任何成功连接后持久化主 `hello-ok.auth.deviceToken`。 +- 使用该**已存储**设备令牌重新连接时,也应重用该令牌已存储的已批准作用域集合。这可以保留已授予的读取/探测/状态访问权限,并避免重连时静默收缩为更窄的隐式仅 admin 作用域。 +- 客户端侧 connect 认证组装(`src/gateway/client.ts` 中的 `selectConnectAuth`): + - `auth.password` 是正交的,设置时始终会被转发。 + - `auth.token` 按以下优先级填充:显式共享令牌优先,其次是显式 `deviceToken`,再其次是按 `deviceId` + `role` 键控的已存储每设备令牌。 + - 只有在以上都未解析出 `auth.token` 时,才会发送 `auth.bootstrapToken`。共享令牌或任何已解析设备令牌都会抑制它。 + - 在一次性 `AUTH_TOKEN_MISMATCH` 重试中自动提升已存储设备令牌的行为仅对**受信任端点**开放——loopback,或带固定 `tlsFingerprint` 的 `wss://`。未固定证书的公共 `wss://` 不符合条件。 +- 额外的 `hello-ok.auth.deviceTokens` 条目是 bootstrap 交接令牌。仅当连接使用 bootstrap 认证且传输是受信任的(如 `wss://` 或 loopback/本地配对)时,才应持久化它们。 +- 如果客户端提供了**显式** `deviceToken` 或显式 `scopes`,则该调用方请求的作用域集合仍是权威;仅当客户端重用已存储的每设备令牌时,才会重用缓存的作用域。 +- 设备令牌可以通过 `device.token.rotate` 和 `device.token.revoke` 轮换/吊销(需要 `operator.pairing` 作用域)。 +- `device.token.rotate` 返回轮换元数据。仅对于已经使用该设备令牌完成认证的同设备调用,它才会回显替换后的 bearer 令牌,这样纯令牌客户端就可以在重连前持久化替换令牌。共享/admin 轮换不会回显 bearer 令牌。 +- 令牌签发、轮换和吊销都受限于该设备配对条目中记录的已批准角色集合;令牌变更不能扩展到或针对配对批准从未授予的设备角色。 +- 对于配对设备令牌会话,除非调用方还具有 `operator.admin`,否则设备管理是自作用域的:非 admin 调用方只能移除/吊销/轮换其**自己的**设备条目。 +- `device.token.rotate` 和 `device.token.revoke` 还会根据调用方当前会话作用域检查目标 operator 令牌作用域集合。非 admin 调用方不能轮换或吊销比其当前持有权限更广的 operator 令牌。 +- 认证失败会包含 `error.details.code` 以及恢复提示: - `error.details.canRetryWithDeviceToken`(布尔值) - `error.details.recommendedNextStep`(`retry_with_device_token`、`update_auth_configuration`、`update_auth_credentials`、`wait_then_retry`、`review_auth_configuration`) - 客户端对 `AUTH_TOKEN_MISMATCH` 的行为: - - 受信任客户端可以使用缓存的每设备令牌尝试一次有界重试。 - - 如果该重试失败,客户端应停止自动重连循环,并向操作员显示操作指引。 + - 受信任客户端可以使用缓存的每设备令牌进行一次有界重试。 + - 如果该重试失败,客户端应停止自动重连循环,并给出需要操作员采取行动的指导。 ## 设备身份 + 配对 -- 节点应包含一个稳定的设备身份(`device.id`),该身份来自密钥对指纹。 -- Gateway 网关会按设备 + 角色发放令牌。 -- 除非启用了本地自动批准,否则新的设备 ID 需要经过配对批准。 +- 节点应包含稳定的设备身份(`device.id`),该身份来源于密钥对指纹。 +- Gateway 网关按设备 + 角色签发令牌。 +- 除非启用了本地自动批准,否则新的设备 ID 需要配对批准。 - 配对自动批准以直接本地 local loopback 连接为中心。 -- OpenClaw 还为受信任的共享密钥辅助流提供了一条狭窄的后端/容器本地自连接路径。 -- 同主机 tailnet 或 LAN 连接在配对方面仍被视为远程连接,并且需要批准。 -- WS 客户端通常会在 `connect` 期间包含 `device` 身份(operator + node)。唯一允许无设备的操作员例外是显式信任路径: - - `gateway.controlUi.allowInsecureAuth=true`,用于仅 localhost 的不安全 HTTP 兼容。 - - 成功的 `gateway.auth.mode: "trusted-proxy"` 操作员 Control UI 认证。 +- OpenClaw 还为受信任的共享密钥辅助流程提供了一条狭窄的后端/容器本地自连接路径。 +- 同一主机的 tailnet 或 LAN 连接在配对上仍被视为远程连接,仍需批准。 +- WS 客户端通常会在 `connect` 期间包含 `device` 身份(operator + node)。仅有的无设备 operator 例外是显式信任路径: + - `gateway.controlUi.allowInsecureAuth=true`,用于仅 localhost 的不安全 HTTP 兼容性。 + - 成功的 `gateway.auth.mode: "trusted-proxy"` operator Control UI 认证。 - `gateway.controlUi.dangerouslyDisableDeviceAuth=true`(紧急兜底,严重降低安全性)。 - 使用共享 Gateway 网关令牌/密码认证的直接 loopback `gateway-client` 后端 RPC。 -- 所有连接都必须签署服务器提供的 `connect.challenge` nonce。 +- 所有连接都必须对服务端提供的 `connect.challenge` nonce 进行签名。 ### 设备认证迁移诊断 -对于仍使用 challenge 前签名行为的旧版客户端,`connect` 现在会在 `error.details.code` 下返回 `DEVICE_AUTH_*` 详细代码,并附带稳定的 `error.details.reason`。 +对于仍使用挑战前签名行为的旧客户端,`connect` 现在会在 `error.details.code` 下返回 `DEVICE_AUTH_*` 详细代码,并带有稳定的 `error.details.reason`。 常见迁移失败: @@ -512,17 +513,17 @@ Gateway 网关将这些视为**主张**,并在服务端强制执行允许列 | `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | 客户端省略了 `device.nonce`(或发送了空值)。 | | `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | 客户端使用了过期/错误的 nonce 进行签名。 | | `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | 签名负载与 v2 负载不匹配。 | -| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | 签名时间戳超出了允许的偏差范围。 | +| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | 签名时间戳超出了允许的时钟偏移范围。 | | `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` 与公钥指纹不匹配。 | | `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | 公钥格式/规范化失败。 | 迁移目标: - 始终等待 `connect.challenge`。 -- 对包含服务器 nonce 的 v2 负载进行签名。 +- 对包含服务端 nonce 的 v2 负载进行签名。 - 在 `connect.params.device.nonce` 中发送相同的 nonce。 -- 首选签名负载是 `v3`,它除了设备/客户端/角色/作用域/令牌/nonce 字段外,还绑定 `platform` 和 `deviceFamily`。 -- 为兼容性起见,旧版 `v2` 签名仍被接受,但已配对设备的元数据固定仍会在重连时控制命令策略。 +- 首选签名负载是 `v3`,它除了 device/client/role/scopes/token/nonce 字段外,还绑定 `platform` 和 `deviceFamily`。 +- 为了兼容性,旧版 `v2` 签名仍然接受,但配对设备元数据固定仍会在重连时控制命令策略。 ## TLS + 固定 @@ -531,9 +532,9 @@ Gateway 网关将这些视为**主张**,并在服务端强制执行允许列 ## 范围 -该协议暴露了**完整的 Gateway 网关 API**(状态、渠道、模型、聊天、智能体、会话、节点、审批等)。确切表面由 `src/gateway/protocol/schema.ts` 中的 TypeBox schemas 定义。 +该协议暴露了**完整的 Gateway 网关 API**(status、渠道、模型、聊天、智能体、会话、节点、审批等)。确切表面由 `src/gateway/protocol/schema.ts` 中的 TypeBox schemas 定义。 ## 相关内容 - [Bridge protocol(旧版节点,历史参考)](/zh-CN/gateway/bridge-protocol) -- [Gateway 网关 runbook](/zh-CN/gateway) +- [Gateway 网关运行手册](/zh-CN/gateway)