chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
ffac44a313
commit
7c025e7f04
@ -5,39 +5,40 @@ read_when:
|
||||
summary: '`openclaw node` 的 CLI 参考(无头节点主机)'
|
||||
title: 节点
|
||||
x-i18n:
|
||||
generated_at: "2026-04-24T05:21:41Z"
|
||||
generated_at: "2026-04-24T06:43:56Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 61b16bdd0c52115bc9938a0fc975369159a4e45d743173ab4e65fce8292af51e
|
||||
source_hash: 9f2bd6d61ee87d36f7691207d03a91c914e6460549256e0cc6ea7bebfa713923
|
||||
source_path: cli/node.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw node`
|
||||
|
||||
运行一个**无头节点主机**,连接到 Gateway 网关 WebSocket,并在此机器上公开
|
||||
运行一个**无头节点主机**,连接到 Gateway 网关 WebSocket,并在这台机器上暴露
|
||||
`system.run` / `system.which`。
|
||||
|
||||
## 为什么要使用节点主机?
|
||||
|
||||
当你希望智能体能够**在网络中的其他机器上运行命令**,而又不想在那些机器上安装完整的 macOS 配套应用时,可以使用节点主机。
|
||||
当你希望智能体能够**在网络中的其他机器上运行命令**,而又不想在那里安装完整的 macOS 配套应用时,可以使用节点主机。
|
||||
|
||||
常见用例:
|
||||
|
||||
- 在远程 Linux/Windows 机器上运行命令(构建服务器、实验室机器、NAS)。
|
||||
- 将 exec 保持在 Gateway 网关上的**沙箱隔离**状态,同时把已批准的执行委托给其他主机。
|
||||
- 为自动化或 CI 节点提供一个轻量级、无头的执行目标。
|
||||
- 将 exec 保持在 Gateway 网关上**沙箱隔离**,但把已批准的运行委派给其他主机。
|
||||
- 为自动化或 CI 节点提供轻量级、无头的执行目标。
|
||||
|
||||
执行仍然受**exec 批准**和节点主机上按智能体划分的允许列表保护,因此你可以将命令访问范围保持为受限且明确。
|
||||
执行仍然受到**exec 批准**和节点主机上按智能体划分的允许列表保护,因此你可以让命令访问保持在明确且受限的范围内。
|
||||
|
||||
## 浏览器代理(零配置)
|
||||
|
||||
如果节点上的 `browser.enabled` 未被禁用,节点主机会自动公布一个浏览器代理。这样,智能体无需额外配置即可在该节点上使用浏览器自动化。
|
||||
如果节点上的 `browser.enabled` 未被禁用,节点主机会自动公布一个浏览器代理。这样一来,智能体无需额外配置即可在该节点上使用浏览器自动化。
|
||||
|
||||
默认情况下,该代理会公开节点的常规浏览器配置文件界面。如果你设置了 `nodeHost.browserProxy.allowProfiles`,该代理将变为受限模式:
|
||||
不在允许列表中的配置文件目标会被拒绝,并且通过代理会阻止持久化配置文件的创建/删除路由。
|
||||
默认情况下,该代理会暴露节点的常规浏览器配置文件表面。如果你设置了
|
||||
`nodeHost.browserProxy.allowProfiles`,代理将变为受限模式:
|
||||
不在允许列表中的配置文件目标会被拒绝,并且通过该代理会阻止持久化配置文件的创建/删除路由。
|
||||
|
||||
如有需要,可在节点上禁用它:
|
||||
如有需要,可在节点上将其禁用:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -66,17 +67,18 @@ openclaw node run --host <gateway-host> --port 18789
|
||||
|
||||
## 节点主机的 Gateway 网关认证
|
||||
|
||||
`openclaw node run` 和 `openclaw node install` 会从配置/环境变量中解析 Gateway 网关认证信息(节点命令上没有 `--token`/`--password` 标志):
|
||||
`openclaw node run` 和 `openclaw node install` 会从配置/环境变量中解析 Gateway 网关认证信息(节点命令不支持 `--token`/`--password` 标志):
|
||||
|
||||
- 首先检查 `OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`。
|
||||
- 然后回退到本地配置:`gateway.auth.token` / `gateway.auth.password`。
|
||||
- 在本地模式下,节点主机不会刻意继承 `gateway.remote.token` / `gateway.remote.password`。
|
||||
- 如果通过 SecretRef 显式配置了 `gateway.auth.token` / `gateway.auth.password` 但未能解析,节点认证解析会以失败关闭的方式处理(不会用远程回退来掩盖问题)。
|
||||
- 在 `gateway.mode=remote` 中,远程客户端字段(`gateway.remote.token` / `gateway.remote.password`)也会根据远程优先级规则纳入候选。
|
||||
- 节点主机认证解析只接受 `OPENCLAW_GATEWAY_*` 环境变量。
|
||||
- 在本地模式下,节点主机有意不继承 `gateway.remote.token` / `gateway.remote.password`。
|
||||
- 如果通过 SecretRef 显式配置了 `gateway.auth.token` / `gateway.auth.password` 但未能解析,节点认证解析会以关闭方式失败(不会使用远程回退来掩盖问题)。
|
||||
- 在 `gateway.mode=remote` 下,远程客户端字段(`gateway.remote.token` / `gateway.remote.password`)也会按照远程优先级规则参与解析。
|
||||
- 节点主机认证解析仅识别 `OPENCLAW_GATEWAY_*` 环境变量。
|
||||
|
||||
对于连接到受信任私有网络中非 loopback `ws://` Gateway 网关的节点,请设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`。如果不设置,节点启动将以失败关闭的方式终止,并提示你使用 `wss://`、SSH 隧道或 Tailscale。
|
||||
`openclaw node install` 会将此显式启用项持久化到受监管的节点服务中。
|
||||
对于要连接到受信任私有网络中非 loopback `ws://` Gateway 网关的节点,请设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`。如果不设置,节点启动将以关闭方式失败,并提示你使用 `wss://`、SSH 隧道或 Tailscale。
|
||||
这是进程环境级别的显式启用项,不是 `openclaw.json` 配置键。
|
||||
当它存在于安装命令环境中时,`openclaw node install` 会将其持久化到受监管的节点服务中。
|
||||
|
||||
## 服务(后台)
|
||||
|
||||
@ -95,9 +97,9 @@ openclaw node install --host <gateway-host> --port 18789
|
||||
- `--node-id <id>`:覆盖节点 id(会清除配对令牌)
|
||||
- `--display-name <name>`:覆盖节点显示名称
|
||||
- `--runtime <runtime>`:服务运行时(`node` 或 `bun`)
|
||||
- `--force`:如果已安装,则重新安装/覆盖
|
||||
- `--force`:如果已安装则重新安装/覆盖
|
||||
|
||||
管理该服务:
|
||||
管理服务:
|
||||
|
||||
```bash
|
||||
openclaw node status
|
||||
@ -106,24 +108,24 @@ openclaw node restart
|
||||
openclaw node uninstall
|
||||
```
|
||||
|
||||
如需前台节点主机(非服务),请使用 `openclaw node run`。
|
||||
如需前台运行的节点主机(非服务),请使用 `openclaw node run`。
|
||||
|
||||
服务命令接受 `--json`,用于机器可读输出。
|
||||
服务命令支持 `--json`,用于机器可读输出。
|
||||
|
||||
## 配对
|
||||
|
||||
首次连接会在 Gateway 网关上创建一个待处理的设备配对请求(`role: node`)。
|
||||
可通过以下方式批准:
|
||||
第一次连接会在 Gateway 网关上创建一个待处理的设备配对请求(`role: node`)。
|
||||
通过以下命令批准:
|
||||
|
||||
```bash
|
||||
openclaw devices list
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
|
||||
如果节点在认证细节(角色/作用域/公钥)发生变化后重试配对,之前待处理的请求会被新请求取代,并创建新的 `requestId`。
|
||||
批准前请再次运行 `openclaw devices list`。
|
||||
如果节点在认证详情发生变化(角色/作用域/公钥)后重试配对,之前的待处理请求会被替代,并创建新的 `requestId`。
|
||||
请在批准前再次运行 `openclaw devices list`。
|
||||
|
||||
节点主机会将其节点 id、令牌、显示名称和 Gateway 网关连接信息存储在
|
||||
节点主机会将其节点 id、令牌、显示名称以及 Gateway 网关连接信息存储在
|
||||
`~/.openclaw/node.json` 中。
|
||||
|
||||
## Exec 批准
|
||||
@ -135,9 +137,9 @@ openclaw devices approve <requestId>
|
||||
- `openclaw approvals --node <id|name|ip>`(从 Gateway 网关编辑)
|
||||
|
||||
对于已批准的异步节点 exec,OpenClaw 会在提示前准备规范化的 `systemRunPlan`。
|
||||
之后转发的已批准 `system.run` 会复用该已存储的计划,因此在批准请求创建后,对命令/cwd/session 字段的编辑会被拒绝,而不是改变节点实际执行的内容。
|
||||
之后被批准的 `system.run` 转发会复用该已存储的计划,因此在批准请求创建之后对命令/cwd/session 字段的编辑将被拒绝,而不是改变节点实际执行的内容。
|
||||
|
||||
## 相关内容
|
||||
## 相关
|
||||
|
||||
- [CLI 参考](/zh-CN/cli)
|
||||
- [节点](/zh-CN/nodes)
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
---
|
||||
read_when:
|
||||
- 你希望通过引导式设置完成 gateway、工作区、认证、渠道和 Skills 的配置
|
||||
- 你希望通过引导式设置来配置 Gateway 网关、工作区、凭证、渠道和 Skills
|
||||
summary: '`openclaw onboard` 的 CLI 参考(交互式新手引导)'
|
||||
title: 新手引导
|
||||
x-i18n:
|
||||
generated_at: "2026-04-23T20:44:32Z"
|
||||
generated_at: "2026-04-24T06:43:47Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ab92ff5651b7db18850558cbb47527bf0486f278c8aed0929eaeff0017b6c280
|
||||
source_hash: c1959ad7014b891230e497a2e0ab494ba316090c81629f25b8147614b694ead5
|
||||
source_path: cli/onboard.md
|
||||
workflow: 15
|
||||
---
|
||||
@ -18,11 +18,11 @@ x-i18n:
|
||||
|
||||
## 相关指南
|
||||
|
||||
- CLI 新手引导总览:[新手引导(CLI)](/zh-CN/start/wizard)
|
||||
- CLI 新手引导中心:[设置向导(CLI)](/zh-CN/start/wizard)
|
||||
- 新手引导概览:[新手引导概览](/zh-CN/start/onboarding-overview)
|
||||
- CLI 新手引导参考:[CLI 设置参考](/zh-CN/start/wizard-cli-reference)
|
||||
- CLI 自动化:[CLI 自动化](/zh-CN/start/wizard-cli-automation)
|
||||
- macOS 新手引导:[新手引导(macOS App)](/zh-CN/start/onboarding)
|
||||
- macOS 新手引导:[新手引导(macOS 应用)](/zh-CN/start/onboarding)
|
||||
|
||||
## 示例
|
||||
|
||||
@ -35,8 +35,10 @@ openclaw onboard --mode remote --remote-url wss://gateway-host:18789
|
||||
|
||||
对于明文私有网络 `ws://` 目标(仅限受信任网络),请在新手引导进程环境中设置
|
||||
`OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`。
|
||||
此客户端传输层紧急开关
|
||||
没有对应的 `openclaw.json` 等效项。
|
||||
|
||||
非交互式自定义 provider:
|
||||
非交互式自定义提供商:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
@ -48,9 +50,9 @@ openclaw onboard --non-interactive \
|
||||
--custom-compatibility openai
|
||||
```
|
||||
|
||||
在非交互模式下,`--custom-api-key` 是可选的。如果省略,新手引导会检查 `CUSTOM_API_KEY`。
|
||||
在非交互式模式下,`--custom-api-key` 是可选的。如果省略,新手引导会检查 `CUSTOM_API_KEY`。
|
||||
|
||||
LM Studio 在非交互模式下也支持 provider 专用密钥标志:
|
||||
LM Studio 在非交互式模式下也支持提供商专用的密钥标志:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
@ -71,9 +73,9 @@ openclaw onboard --non-interactive \
|
||||
--accept-risk
|
||||
```
|
||||
|
||||
`--custom-base-url` 默认值为 `http://127.0.0.1:11434`。`--custom-model-id` 是可选的;如果省略,新手引导会使用 Ollama 建议的默认值。像 `kimi-k2.5:cloud` 这样的云模型 ID 也可在此使用。
|
||||
`--custom-base-url` 默认为 `http://127.0.0.1:11434`。`--custom-model-id` 是可选的;如果省略,新手引导会使用 Ollama 建议的默认值。像 `kimi-k2.5:cloud` 这样的云端模型 ID 在这里也可用。
|
||||
|
||||
将 provider 密钥存储为引用而不是明文:
|
||||
将提供商密钥存储为引用而不是明文:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
@ -83,25 +85,25 @@ openclaw onboard --non-interactive \
|
||||
```
|
||||
|
||||
使用 `--secret-input-mode ref` 时,新手引导会写入由环境变量支持的引用,而不是明文密钥值。
|
||||
对于基于 auth-profile 的 providers,这会写入 `keyRef` 条目;对于自定义 providers,这会将 `models.providers.<id>.apiKey` 写为环境变量引用(例如 `{ source: "env", provider: "default", id: "CUSTOM_API_KEY" }`)。
|
||||
对于基于 auth-profile 的提供商,这会写入 `keyRef` 条目;对于自定义提供商,这会将 `models.providers.<id>.apiKey` 写为环境变量引用(例如 `{ source: "env", provider: "default", id: "CUSTOM_API_KEY" }`)。
|
||||
|
||||
非交互式 `ref` 模式契约:
|
||||
非交互式 `ref` 模式约定:
|
||||
|
||||
- 在新手引导进程环境中设置 provider 环境变量(例如 `OPENAI_API_KEY`)。
|
||||
- 不要传递内联密钥标志(例如 `--openai-api-key`),除非该环境变量也已设置。
|
||||
- 如果传递了内联密钥标志但缺少所需环境变量,新手引导会快速失败并给出指引。
|
||||
- 在新手引导进程环境中设置提供商环境变量(例如 `OPENAI_API_KEY`)。
|
||||
- 不要传递内联密钥标志(例如 `--openai-api-key`),除非同时设置了该环境变量。
|
||||
- 如果传递了内联密钥标志但未设置所需环境变量,新手引导会快速失败并给出指引。
|
||||
|
||||
非交互模式下的 Gateway 网关 token 选项:
|
||||
非交互式模式下的 Gateway 网关令牌选项:
|
||||
|
||||
- `--gateway-auth token --gateway-token <token>` 存储明文 token。
|
||||
- `--gateway-auth token --gateway-token <token>` 存储明文令牌。
|
||||
- `--gateway-auth token --gateway-token-ref-env <name>` 将 `gateway.auth.token` 存储为环境变量 SecretRef。
|
||||
- `--gateway-token` 和 `--gateway-token-ref-env` 互斥。
|
||||
- `--gateway-token-ref-env` 要求在新手引导进程环境中存在一个非空环境变量。
|
||||
- 配合 `--install-daemon` 使用时,当 token 认证要求 token 时,由 SecretRef 管理的 Gateway 网关 token 会被验证,但不会以已解析的明文形式持久化到 supervisor 服务环境元数据中。
|
||||
- 配合 `--install-daemon` 使用时,如果 token 模式要求 token,且配置的 token SecretRef 未解析,新手引导会以失败关闭方式终止,并提供修复指引。
|
||||
- 配合 `--install-daemon` 使用时,如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,但未设置 `gateway.auth.mode`,新手引导会阻止安装,直到显式设置 mode。
|
||||
- 本地新手引导会将 `gateway.mode="local"` 写入配置。如果之后的配置文件缺少 `gateway.mode`,应视为配置损坏或不完整的手动编辑,而不是合法的本地模式快捷方式。
|
||||
- `--allow-unconfigured` 是单独的 Gateway 网关运行时逃生开关。它并不意味着新手引导可以省略 `gateway.mode`。
|
||||
- `--gateway-token-ref-env` 要求在新手引导进程环境中存在非空环境变量。
|
||||
- 配合 `--install-daemon` 使用时,当令牌认证需要令牌时,由 SecretRef 管理的 Gateway 网关令牌会被校验,但不会作为已解析的明文持久化到 supervisor 服务环境元数据中。
|
||||
- 配合 `--install-daemon` 使用时,如果令牌模式需要令牌,而配置的令牌 SecretRef 无法解析,新手引导会以安全默认方式失败,并提供修复指引。
|
||||
- 配合 `--install-daemon` 使用时,如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,且未设置 `gateway.auth.mode`,新手引导会阻止安装,直到显式设置模式。
|
||||
- 本地新手引导会将 `gateway.mode="local"` 写入配置。如果之后的配置文件缺少 `gateway.mode`,应将其视为配置损坏或不完整的手动编辑,而不是有效的本地模式简写。
|
||||
- `--allow-unconfigured` 是一个单独的 Gateway 网关运行时紧急开关。这并不意味着新手引导可以省略 `gateway.mode`。
|
||||
|
||||
示例:
|
||||
|
||||
@ -117,24 +119,24 @@ openclaw onboard --non-interactive \
|
||||
|
||||
非交互式本地 Gateway 网关健康检查:
|
||||
|
||||
- 除非你传递 `--skip-health`,否则新手引导会在本地 Gateway 网关可连接之前一直等待,只有成功后才退出。
|
||||
- `--install-daemon` 会先启动受管理的 Gateway 网关安装路径。如果不使用它,你必须已经运行本地 Gateway 网关,例如 `openclaw gateway run`。
|
||||
- 如果你在自动化中只想写入配置/工作区/引导文件,请使用 `--skip-health`。
|
||||
- 在原生 Windows 上,`--install-daemon` 会先尝试 Scheduled Tasks;如果任务创建被拒绝,则回退到每用户 Startup 文件夹登录项。
|
||||
- 除非你传递 `--skip-health`,否则新手引导会等待本地 Gateway 网关可达后才成功退出。
|
||||
- `--install-daemon` 会先启动托管式 Gateway 网关安装路径。如果不使用它,你必须已经有一个正在运行的本地 Gateway 网关,例如 `openclaw gateway run`。
|
||||
- 如果你只想在自动化中写入配置 / 工作区 / 引导初始内容,请使用 `--skip-health`。
|
||||
- 在原生 Windows 上,`--install-daemon` 会先尝试使用计划任务;如果任务创建被拒绝,则回退到每用户 Startup 文件夹登录项。
|
||||
|
||||
启用引用模式时的交互式新手引导行为:
|
||||
使用引用模式时的交互式新手引导行为:
|
||||
|
||||
- 出现提示时选择**使用 secret reference**。
|
||||
- 然后选择以下之一:
|
||||
- 环境变量
|
||||
- 出现提示时,选择 **Use secret reference**。
|
||||
- 然后选择以下其中一项:
|
||||
- Environment variable
|
||||
- 已配置的 secret provider(`file` 或 `exec`)
|
||||
- 新手引导会在保存引用前执行快速预检验证。
|
||||
- 如果验证失败,新手引导会显示错误并允许你重试。
|
||||
- 新手引导会在保存引用前执行快速预检校验。
|
||||
- 如果校验失败,新手引导会显示错误并允许你重试。
|
||||
|
||||
非交互式 Z.AI 端点选项:
|
||||
非交互式 Z.AI 端点选择:
|
||||
|
||||
注意:`--auth-choice zai-api-key` 现在会自动为你的密钥检测最佳 Z.AI 端点(优先使用通用 API 和 `zai/glm-5.1`)。
|
||||
如果你特别想使用 GLM Coding Plan 端点,请选择 `zai-coding-global` 或 `zai-coding-cn`。
|
||||
注意:`--auth-choice zai-api-key` 现在会为你的密钥自动检测最佳 Z.AI 端点(优先使用通用 API 和 `zai/glm-5.1`)。
|
||||
如果你明确想使用 GLM Coding Plan 端点,请选择 `zai-coding-global` 或 `zai-coding-cn`。
|
||||
|
||||
```bash
|
||||
# 无提示端点选择
|
||||
@ -158,17 +160,16 @@ openclaw onboard --non-interactive \
|
||||
|
||||
流程说明:
|
||||
|
||||
- `quickstart`:最少提示,自动生成 gateway token。
|
||||
- `manual`:针对 port/bind/auth 提供完整提示(`advanced` 的别名)。
|
||||
- 当某个认证选项暗示首选 provider 时,新手引导会将默认模型和允许列表选择器预过滤到该 provider。对于 Volcengine 和 BytePlus(国际版),这也会匹配 coding-plan 变体
|
||||
(`volcengine-plan/*`、`byteplus-plan/*`)。
|
||||
- 如果首选 provider 过滤后尚未得到任何已加载模型,新手引导会回退到未过滤目录,而不是让选择器保持为空。
|
||||
- 在网页搜索步骤中,某些 providers 可能触发 provider 专用的后续提示:
|
||||
- **Grok** 可以提供可选的 `x_search` 设置,使用同一个 `XAI_API_KEY` 和一个 `x_search` 模型选择。
|
||||
- **Kimi** 可能会询问 Moonshot API 区域(`api.moonshot.ai` 与 `api.moonshot.cn`)以及默认的 Kimi Web 搜索模型。
|
||||
- 本地新手引导私信范围行为:[CLI 设置参考](/zh-CN/start/wizard-cli-reference#outputs-and-internals)。
|
||||
- 最快开始首次聊天的方式:`openclaw dashboard`(Control UI,无需设置渠道)。
|
||||
- 自定义 Provider:连接任意兼容 OpenAI 或 Anthropic 的端点,包括未列出的托管 provider。使用 Unknown 进行自动检测。
|
||||
- `quickstart`:最少提示,自动生成 Gateway 网关令牌。
|
||||
- `manual`:提供端口 / 绑定 / 认证的完整提示(`advanced` 的别名)。
|
||||
- 当某个认证选项隐含首选提供商时,新手引导会将默认模型和 allowlist 选择器预先筛选到该提供商。对于 Volcengine 和 BytePlus(国际版),这也会匹配 coding-plan 变体(`volcengine-plan/*`、`byteplus-plan/*`)。
|
||||
- 如果首选提供商筛选后尚未产生任何已加载模型,新手引导会回退到未筛选目录,而不是让选择器保持为空。
|
||||
- 在 web-search 步骤中,某些提供商可能会触发提供商专属的后续提示:
|
||||
- **Grok** 可能会提供可选的 `x_search` 设置,使用同一个 `XAI_API_KEY` 和一个 `x_search` 模型选择。
|
||||
- **Kimi** 可能会询问 Moonshot AI API 区域(`api.moonshot.ai` 或 `api.moonshot.cn`)以及默认的 Kimi web-search 模型。
|
||||
- 本地新手引导的私信范围行为:[CLI 设置参考](/zh-CN/start/wizard-cli-reference#outputs-and-internals)。
|
||||
- 最快开始第一次聊天:`openclaw dashboard`(控制 UI,无需设置渠道)。
|
||||
- 自定义提供商:连接任何兼容 OpenAI 或 Anthropic 的端点,包括未列出的托管提供商。使用 Unknown 可自动检测。
|
||||
|
||||
## 常见后续命令
|
||||
|
||||
@ -178,5 +179,5 @@ openclaw agents add <name>
|
||||
```
|
||||
|
||||
<Note>
|
||||
`--json` 不代表非交互模式。脚本中请使用 `--non-interactive`。
|
||||
`--json` 并不表示非交互式模式。脚本中请使用 `--non-interactive`。
|
||||
</Note>
|
||||
|
||||
@ -2,32 +2,32 @@
|
||||
read_when:
|
||||
- 你需要精确到字段级别的配置语义或默认值
|
||||
- 你正在验证渠道、模型、Gateway 网关或工具配置块
|
||||
summary: OpenClaw 核心配置键、默认值及专用子系统参考链接的 Gateway 网关配置参考
|
||||
summary: Gateway 网关配置参考,涵盖核心 OpenClaw 键名、默认值,以及指向专用子系统参考文档的链接
|
||||
title: 配置参考
|
||||
x-i18n:
|
||||
generated_at: "2026-04-24T04:02:19Z"
|
||||
generated_at: "2026-04-24T06:43:47Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6dc3b920ada38951086908713e9347141d8b11faa007df23a90a2532ac6f3bb2
|
||||
source_hash: dc0d9feea2f2707f267d50ec83aa664ef503db8f9132762345cc80305f8bef73
|
||||
source_path: gateway/configuration-reference.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
`~/.openclaw/openclaw.json` 的核心配置参考。若需面向任务的概览,请参阅[配置](/zh-CN/gateway/configuration)。
|
||||
`~/.openclaw/openclaw.json` 的核心配置参考。若需按任务查看的概览,请参见 [Configuration](/zh-CN/gateway/configuration)。
|
||||
|
||||
本页涵盖 OpenClaw 的主要配置能力,并在某个子系统拥有更深入的独立参考时提供跳转链接。它**不会**尝试在单个页面中内联每个由渠道/插件拥有的命令目录,或每个深层记忆/QMD 调节项。
|
||||
本页涵盖 OpenClaw 的主要配置面,并在某个子系统有自己更深入的参考文档时提供跳转链接。它**不会**尝试在单页中内联每个渠道 / 插件自有的命令目录,也不会包含每个深层 memory/QMD 旋钮。
|
||||
|
||||
代码真相:
|
||||
代码真实来源:
|
||||
|
||||
- `openclaw config schema` 会打印用于验证和 Control UI 的实时 JSON Schema,并在可用时合并内置/插件/渠道元数据
|
||||
- `config.schema.lookup` 会返回一个按路径限定的 schema 节点,供下钻工具使用
|
||||
- `pnpm config:docs:check` / `pnpm config:docs:gen` 会根据当前 schema 能力验证配置文档基线哈希
|
||||
- `openclaw config schema` 会打印用于验证和 Control UI 的实时 JSON Schema,并在可用时合并内置 / 插件 / 渠道元数据
|
||||
- `config.schema.lookup` 返回一个按路径作用域划分的 schema 节点,供深入查看工具使用
|
||||
- `pnpm config:docs:check` / `pnpm config:docs:gen` 会根据当前 schema 表面校验配置文档基线哈希
|
||||
|
||||
专门的深度参考:
|
||||
专用深度参考:
|
||||
|
||||
- [记忆配置参考](/zh-CN/reference/memory-config),适用于 `agents.defaults.memorySearch.*`、`memory.qmd.*`、`memory.citations` 以及位于 `plugins.entries.memory-core.config.dreaming` 下的 dreaming 配置
|
||||
- [斜杠命令](/zh-CN/tools/slash-commands),查看当前内置 + 内置打包命令目录
|
||||
- 各自所属的渠道/插件页面,用于查看渠道专属命令能力
|
||||
- [Memory configuration reference](/zh-CN/reference/memory-config),适用于 `agents.defaults.memorySearch.*`、`memory.qmd.*`、`memory.citations`,以及位于 `plugins.entries.memory-core.config.dreaming` 下的 dreaming 配置
|
||||
- [Slash Commands](/zh-CN/tools/slash-commands),查看当前内置 + 内置插件命令目录
|
||||
- 各所属渠道 / 插件页面,查看渠道专属命令面
|
||||
|
||||
配置格式为 **JSON5**(允许注释和尾随逗号)。所有字段都是可选的——省略时,OpenClaw 会使用安全默认值。
|
||||
|
||||
@ -35,28 +35,28 @@ x-i18n:
|
||||
|
||||
## 渠道
|
||||
|
||||
各渠道配置键已移至独立页面——请参阅
|
||||
[配置——渠道](/zh-CN/gateway/config-channels),了解 `channels.*`,
|
||||
包括 Slack、Discord、Telegram、WhatsApp、Matrix、iMessage 及其他
|
||||
每个渠道的配置键已迁移到专用页面——请参见
|
||||
[Configuration — channels](/zh-CN/gateway/config-channels) 了解 `channels.*`,
|
||||
包括 Slack、Discord、Telegram、WhatsApp、Matrix、iMessage 以及其他
|
||||
内置渠道(认证、访问控制、多账号、提及门控)。
|
||||
|
||||
## 智能体默认值、多智能体、会话与消息
|
||||
## 智能体默认值、多智能体、会话和消息
|
||||
|
||||
已移至独立页面——请参阅
|
||||
[配置——智能体](/zh-CN/gateway/config-agents),了解:
|
||||
已迁移到专用页面——请参见
|
||||
[Configuration — agents](/zh-CN/gateway/config-agents) 了解:
|
||||
|
||||
- `agents.defaults.*`(工作区、模型、思考、心跳、记忆、媒体、Skills、沙箱)
|
||||
- `multiAgent.*`(多智能体路由和绑定)
|
||||
- `session.*`(会话生命周期、压缩、清理)
|
||||
- `session.*`(会话生命周期、压缩、修剪)
|
||||
- `messages.*`(消息投递、TTS、Markdown 渲染)
|
||||
- `talk.*`(Talk 模式)
|
||||
- `talk.silenceTimeoutMs`:未设置时,Talk 会在发送转录内容前保留平台默认的停顿窗口(`macOS 和 Android 为 700 ms,iOS 为 900 ms`)
|
||||
- `talk.silenceTimeoutMs`:未设置时,Talk 会在发送转录内容前保持平台默认的停顿窗口(`macOS 和 Android 为 700 ms,iOS 为 900 ms`)
|
||||
|
||||
## 工具和自定义提供商
|
||||
|
||||
工具策略、实验性开关、提供商支持的工具配置,以及自定义
|
||||
提供商 / base-URL 设置已移至独立页面——请参阅
|
||||
[配置——工具和自定义提供商](/zh-CN/gateway/config-tools)。
|
||||
提供商 / 基础 URL 设置已迁移到专用页面——请参见
|
||||
[Configuration — tools and custom providers](/zh-CN/gateway/config-tools)。
|
||||
|
||||
## Skills
|
||||
|
||||
@ -83,12 +83,12 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
- `allowBundled`:仅针对内置 Skills 的可选允许列表(不影响托管/工作区 Skills)。
|
||||
- `load.extraDirs`:额外的共享 Skills 根目录(最低优先级)。
|
||||
- `install.preferBrew`:为 true 时,如果 `brew` 可用,则优先使用 Homebrew 安装器,之后才回退到其他安装器类型。
|
||||
- `install.nodeManager`:用于 `metadata.openclaw.install` 规范的 Node 安装器偏好(`npm` | `pnpm` | `yarn` | `bun`)。
|
||||
- `entries.<skillKey>.enabled: false`:即使某个 Skill 已内置/已安装,也会禁用它。
|
||||
- `entries.<skillKey>.apiKey`:为声明了主环境变量的 Skills 提供的便捷字段(明文字符串或 SecretRef 对象)。
|
||||
- `allowBundled`:仅对内置 skills 生效的可选允许列表(托管 / 工作区 skills 不受影响)。
|
||||
- `load.extraDirs`:额外的共享 skill 根目录(最低优先级)。
|
||||
- `install.preferBrew`:为 `true` 时,若 `brew` 可用,则优先使用 Homebrew 安装器,再回退到其他安装器类型。
|
||||
- `install.nodeManager`:用于 `metadata.openclaw.install` 规范的 Node 安装器优先项(`npm` | `pnpm` | `yarn` | `bun`)。
|
||||
- `entries.<skillKey>.enabled: false`:即使某个 skill 已内置 / 已安装,也会禁用它。
|
||||
- `entries.<skillKey>.apiKey`:为声明了主环境变量的 skills 提供的便捷字段(明文字符串或 SecretRef 对象)。
|
||||
|
||||
---
|
||||
|
||||
@ -117,42 +117,42 @@ x-i18n:
|
||||
```
|
||||
|
||||
- 从 `~/.openclaw/extensions`、`<workspace>/.openclaw/extensions` 以及 `plugins.load.paths` 加载。
|
||||
- 发现过程接受原生 OpenClaw 插件,以及兼容的 Codex bundle 和 Claude bundle,包括无 manifest 的 Claude 默认布局 bundle。
|
||||
- 设备发现接受原生 OpenClaw 插件,以及兼容的 Codex bundle 和 Claude bundle,包括无 manifest 的 Claude 默认布局 bundle。
|
||||
- **配置变更需要重启 Gateway 网关。**
|
||||
- `allow`:可选允许列表(仅加载列出的插件)。`deny` 优先。
|
||||
- `plugins.entries.<id>.apiKey`:插件级 API key 便捷字段(插件支持时可用)。
|
||||
- `allow`:可选允许列表(仅加载列出的插件)。`deny` 优先生效。
|
||||
- `plugins.entries.<id>.apiKey`:插件级 API 密钥便捷字段(插件支持时可用)。
|
||||
- `plugins.entries.<id>.env`:插件作用域的环境变量映射。
|
||||
- `plugins.entries.<id>.hooks.allowPromptInjection`:当为 `false` 时,核心会阻止 `before_prompt_build`,并忽略旧版 `before_agent_start` 中会修改提示的字段,同时保留旧版 `modelOverride` 和 `providerOverride`。适用于原生插件 hook,以及受支持 bundle 提供的 hook 目录。
|
||||
- `plugins.entries.<id>.subagent.allowModelOverride`:显式信任该插件可为后台子智能体运行请求按次生效的 `provider` 和 `model` 覆盖。
|
||||
- `plugins.entries.<id>.subagent.allowedModels`:受信任子智能体覆盖可使用的规范 `provider/model` 目标可选允许列表。仅当你有意允许任意模型时才使用 `"*"`。
|
||||
- `plugins.entries.<id>.config`:插件定义的配置对象(在可用时由原生 OpenClaw 插件 schema 验证)。
|
||||
- `plugins.entries.firecrawl.config.webFetch`:Firecrawl web-fetch 提供商设置。
|
||||
- `apiKey`:Firecrawl API key(接受 SecretRef)。会回退到 `plugins.entries.firecrawl.config.webSearch.apiKey`、旧版 `tools.web.fetch.firecrawl.apiKey` 或 `FIRECRAWL_API_KEY` 环境变量。
|
||||
- `baseUrl`:Firecrawl API base URL(默认:`https://api.firecrawl.dev`)。
|
||||
- `plugins.entries.<id>.hooks.allowPromptInjection`:为 `false` 时,核心会阻止 `before_prompt_build`,并忽略旧版 `before_agent_start` 中会修改提示词的字段,同时保留旧版 `modelOverride` 和 `providerOverride`。适用于原生插件 hooks,以及受支持的 bundle 提供的 hook 目录。
|
||||
- `plugins.entries.<id>.subagent.allowModelOverride`:显式信任此插件,使其可为后台子智能体运行请求按次运行的 `provider` 和 `model` 覆盖。
|
||||
- `plugins.entries.<id>.subagent.allowedModels`:受信任子智能体覆盖的规范 `provider/model` 目标可选允许列表。仅当你明确想允许任意模型时才使用 `"*"`。
|
||||
- `plugins.entries.<id>.config`:插件定义的配置对象(若可用,则由原生 OpenClaw 插件 schema 验证)。
|
||||
- `plugins.entries.firecrawl.config.webFetch`:Firecrawl 网页抓取提供商设置。
|
||||
- `apiKey`:Firecrawl API 密钥(接受 SecretRef)。会回退到 `plugins.entries.firecrawl.config.webSearch.apiKey`、旧版 `tools.web.fetch.firecrawl.apiKey` 或 `FIRECRAWL_API_KEY` 环境变量。
|
||||
- `baseUrl`:Firecrawl API 基础 URL(默认:`https://api.firecrawl.dev`)。
|
||||
- `onlyMainContent`:仅提取页面主体内容(默认:`true`)。
|
||||
- `maxAgeMs`:缓存的最大存活时间(毫秒)(默认:`172800000` / 2 天)。
|
||||
- `timeoutSeconds`:抓取请求超时时间(秒)(默认:`60`)。
|
||||
- `maxAgeMs`:缓存的最大保留时长,单位毫秒(默认:`172800000` / 2 天)。
|
||||
- `timeoutSeconds`:抓取请求超时,单位秒(默认:`60`)。
|
||||
- `plugins.entries.xai.config.xSearch`:xAI X Search(Grok web search)设置。
|
||||
- `enabled`:启用 X Search 提供商。
|
||||
- `model`:用于搜索的 Grok 模型(例如 `"grok-4-1-fast"`)。
|
||||
- `plugins.entries.memory-core.config.dreaming`:记忆 Dreaming 设置。阶段和阈值请参阅 [Dreaming](/zh-CN/concepts/dreaming)。
|
||||
- `enabled`:Dreaming 总开关(默认 `false`)。
|
||||
- `frequency`:每次完整 Dreaming 扫描的 cron 频率(默认 `"0 3 * * *"`)。
|
||||
- `plugins.entries.memory-core.config.dreaming`:memory dreaming 设置。各阶段和阈值请参见 [Dreaming](/zh-CN/concepts/dreaming)。
|
||||
- `enabled`:dreaming 总开关(默认 `false`)。
|
||||
- `frequency`:每次完整 dreaming 扫描的 cron 频率(默认 `"0 3 * * *"`)。
|
||||
- 阶段策略和阈值属于实现细节(不是面向用户的配置键)。
|
||||
- 完整记忆配置位于[记忆配置参考](/zh-CN/reference/memory-config):
|
||||
- 完整 memory 配置位于 [Memory configuration reference](/zh-CN/reference/memory-config):
|
||||
- `agents.defaults.memorySearch.*`
|
||||
- `memory.backend`
|
||||
- `memory.citations`
|
||||
- `memory.qmd.*`
|
||||
- `plugins.entries.memory-core.config.dreaming`
|
||||
- 已启用的 Claude bundle 插件也可以通过 `settings.json` 提供嵌入式 Pi 默认值;OpenClaw 会将其作为已净化的智能体设置应用,而不是作为原始 OpenClaw 配置补丁。
|
||||
- `plugins.slots.memory`:选择活动记忆插件 id,或设为 `"none"` 以禁用记忆插件。
|
||||
- `plugins.slots.contextEngine`:选择活动上下文引擎插件 id;默认是 `"legacy"`,除非你安装并选择了其他引擎。
|
||||
- 已启用的 Claude bundle 插件也可以通过 `settings.json` 提供内嵌的 Pi 默认值;OpenClaw 会将其作为清理后的智能体设置应用,而不是作为原始 OpenClaw 配置补丁。
|
||||
- `plugins.slots.memory`:选择当前启用的 memory 插件 id,或设为 `"none"` 以禁用 memory 插件。
|
||||
- `plugins.slots.contextEngine`:选择当前启用的 context engine 插件 id;默认值为 `"legacy"`,除非你安装并选择了其他引擎。
|
||||
- `plugins.installs`:由 CLI 管理的安装元数据,供 `openclaw plugins update` 使用。
|
||||
- 包含 `source`、`spec`、`sourcePath`、`installPath`、`version`、`resolvedName`、`resolvedVersion`、`resolvedSpec`、`integrity`、`shasum`、`resolvedAt`、`installedAt`。
|
||||
- 请将 `plugins.installs.*` 视为托管状态;优先使用 CLI 命令,而不是手动编辑。
|
||||
- 将 `plugins.installs.*` 视为托管状态;优先使用 CLI 命令,而不是手动编辑。
|
||||
|
||||
参见 [插件](/zh-CN/tools/plugin)。
|
||||
参见 [Plugins](/zh-CN/tools/plugin)。
|
||||
|
||||
---
|
||||
|
||||
@ -193,21 +193,28 @@ x-i18n:
|
||||
```
|
||||
|
||||
- `evaluateEnabled: false` 会禁用 `act:evaluate` 和 `wait --fn`。
|
||||
- 未设置时,`ssrfPolicy.dangerouslyAllowPrivateNetwork` 为禁用,因此浏览器导航默认保持严格模式。
|
||||
- 未设置 `ssrfPolicy.dangerouslyAllowPrivateNetwork` 时,该项为禁用状态,因此浏览器导航默认保持严格。
|
||||
- 仅当你明确可信任私有网络浏览器导航时,才设置 `ssrfPolicy.dangerouslyAllowPrivateNetwork: true`。
|
||||
- 在严格模式下,远程 CDP 配置文件端点(`profiles.*.cdpUrl`)在可达性/发现检查期间也受同样的私有网络阻止策略约束。
|
||||
- `ssrfPolicy.allowPrivateNetwork` 仍支持作为旧版别名使用。
|
||||
- 在严格模式下,使用 `ssrfPolicy.hostnameAllowlist` 和 `ssrfPolicy.allowedHostnames` 做显式例外配置。
|
||||
- 远程配置文件为仅附加模式(禁用启动/停止/重置)。
|
||||
- 在严格模式下,远程 CDP 配置项端点(`profiles.*.cdpUrl`)在可达性 / 设备发现检查期间也会受到相同的私有网络阻止策略约束。
|
||||
- `ssrfPolicy.allowPrivateNetwork` 仍作为旧版别名受支持。
|
||||
- 在严格模式下,使用 `ssrfPolicy.hostnameAllowlist` 和 `ssrfPolicy.allowedHostnames` 来添加显式例外。
|
||||
- 远程配置项为仅附加模式(禁用 start/stop/reset)。
|
||||
- `profiles.*.cdpUrl` 接受 `http://`、`https://`、`ws://` 和 `wss://`。
|
||||
当你希望 OpenClaw 发现 `/json/version` 时,使用 HTTP(S);当提供商直接给出 DevTools WebSocket URL 时,使用 WS(S)。
|
||||
- `existing-session` 配置文件使用 Chrome MCP 而不是 CDP,并且可以附加到选定主机上,或通过已连接的浏览器节点附加。
|
||||
- `existing-session` 配置文件可以设置 `userDataDir`,以定位特定的 Chromium 系浏览器配置文件,例如 Brave 或 Edge。
|
||||
- `existing-session` 配置文件保留当前 Chrome MCP 路由限制:使用 snapshot/ref 驱动操作而非 CSS 选择器定位、单文件上传 hook、不支持对话框超时覆盖、不支持 `wait --load networkidle`,以及不支持 `responsebody`、PDF 导出、下载拦截或批量操作。
|
||||
- 本地受管的 `openclaw` 配置文件会自动分配 `cdpPort` 和 `cdpUrl`;只有远程 CDP 才需要显式设置 `cdpUrl`。
|
||||
- 自动检测顺序:默认浏览器(如果是 Chromium 系)→ Chrome → Brave → Edge → Chromium → Chrome Canary。
|
||||
当你希望 OpenClaw 发现 `/json/version` 时,请使用 HTTP(S);
|
||||
当你的提供商直接给出 DevTools WebSocket URL 时,请使用 WS(S)。
|
||||
- `existing-session` 配置项使用 Chrome MCP 而不是 CDP,并且可以附加到
|
||||
所选主机上,或通过已连接的浏览器节点附加。
|
||||
- `existing-session` 配置项可设置 `userDataDir`,以指定特定的
|
||||
基于 Chromium 的浏览器配置,例如 Brave 或 Edge。
|
||||
- `existing-session` 配置项保留当前的 Chrome MCP 路由限制:
|
||||
使用 snapshot/ref 驱动的操作,而不是 CSS 选择器定位;单文件上传
|
||||
hooks;不支持对话框超时覆盖;不支持 `wait --load networkidle`,也不支持
|
||||
`responsebody`、PDF 导出、下载拦截或批量操作。
|
||||
- 本地托管的 `openclaw` 配置项会自动分配 `cdpPort` 和 `cdpUrl`;仅在远程 CDP 场景下才显式设置 `cdpUrl`。
|
||||
- 自动检测顺序:默认浏览器若为基于 Chromium → Chrome → Brave → Edge → Chromium → Chrome Canary。
|
||||
- 控制服务:仅 loopback(端口由 `gateway.port` 派生,默认 `18791`)。
|
||||
- `extraArgs` 会将额外启动标志附加到本地 Chromium 启动参数中(例如 `--disable-gpu`、窗口大小设置或调试标志)。
|
||||
- `extraArgs` 会将额外启动标志追加到本地 Chromium 启动参数中(例如
|
||||
`--disable-gpu`、窗口尺寸或调试标志)。
|
||||
|
||||
---
|
||||
|
||||
@ -226,7 +233,7 @@ x-i18n:
|
||||
```
|
||||
|
||||
- `seamColor`:原生应用 UI 外观的强调色(Talk 模式气泡色调等)。
|
||||
- `assistant`:Control UI 身份覆盖。会回退到当前活动智能体身份。
|
||||
- `assistant`:Control UI 身份覆盖。默认回退到当前激活的智能体身份。
|
||||
|
||||
---
|
||||
|
||||
@ -273,12 +280,12 @@ x-i18n:
|
||||
// password: "your-password",
|
||||
},
|
||||
trustedProxies: ["10.0.0.1"],
|
||||
// Optional. Default false.
|
||||
// 可选。默认 false。
|
||||
allowRealIpFallback: false,
|
||||
tools: {
|
||||
// Additional /tools/invoke HTTP denies
|
||||
// 对 /tools/invoke HTTP 的额外拒绝项
|
||||
deny: ["browser"],
|
||||
// Remove tools from the default HTTP deny list
|
||||
// 从默认 HTTP 拒绝列表中移除工具
|
||||
allow: ["gateway"],
|
||||
},
|
||||
push: {
|
||||
@ -293,66 +300,70 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
<Accordion title="Gateway 字段详情">
|
||||
<Accordion title="Gateway 网关字段详情">
|
||||
|
||||
- `mode`:`local`(运行 Gateway 网关)或 `remote`(连接到远程 Gateway 网关)。除非为 `local`,否则 Gateway 网关将拒绝启动。
|
||||
- `mode`:`local`(运行 Gateway 网关)或 `remote`(连接到远程 Gateway 网关)。除非为 `local`,否则 Gateway 网关会拒绝启动。
|
||||
- `port`:用于 WS + HTTP 的单一复用端口。优先级:`--port` > `OPENCLAW_GATEWAY_PORT` > `gateway.port` > `18789`。
|
||||
- `bind`:`auto`、`loopback`(默认)、`lan`(`0.0.0.0`)、`tailnet`(仅 Tailscale IP)或 `custom`。
|
||||
- **旧版 bind 别名**:请在 `gateway.bind` 中使用 bind 模式值(`auto`、`loopback`、`lan`、`tailnet`、`custom`),不要使用主机别名(`0.0.0.0`、`127.0.0.1`、`localhost`、`::`、`::1`)。
|
||||
- **Docker 说明**:默认的 `loopback` bind 会在容器内部监听 `127.0.0.1`。使用 Docker bridge 网络(`-p 18789:18789`)时,流量会到达 `eth0`,因此 Gateway 网关不可访问。请使用 `--network host`,或设置 `bind: "lan"`(或设置 `bind: "custom"` 且 `customBindHost: "0.0.0.0"`)以监听所有接口。
|
||||
- **Auth**:默认必需。非 loopback bind 要求 Gateway 网关 auth。实际上,这意味着需要共享 token/password,或使用带有 `gateway.auth.mode: "trusted-proxy"` 的身份感知型反向代理。新手引导向导默认会生成 token。
|
||||
- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`(包括 SecretRefs),请显式设置 `gateway.auth.mode` 为 `token` 或 `password`。如果两者都已配置但未设置 mode,启动以及服务安装/修复流程都会失败。
|
||||
- `gateway.auth.mode: "none"`:显式无 auth 模式。仅用于受信任的本地 local loopback 设置;新手引导提示中不会提供此选项。
|
||||
- `gateway.auth.mode: "trusted-proxy"`:将 auth 委托给身份感知型反向代理,并信任来自 `gateway.trustedProxies` 的身份头(参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth))。此模式要求**非 loopback** 代理来源;同机 loopback 反向代理不满足 trusted-proxy auth 的要求。
|
||||
- `gateway.auth.allowTailscale`:为 `true` 时,Tailscale Serve 身份头可满足 Control UI/WebSocket auth(通过 `tailscale whois` 验证)。HTTP API 端点**不会**使用该 Tailscale 头 auth;它们仍遵循 Gateway 网关常规的 HTTP auth 模式。此无 token 流程假设 Gateway 网关主机是受信任的。当 `tailscale.mode = "serve"` 时默认值为 `true`。
|
||||
- `gateway.auth.rateLimit`:可选的 auth 失败限速器。按客户端 IP 和 auth 作用域生效(共享密钥与设备 token 分开跟踪)。被阻止的尝试会返回 `429` + `Retry-After`。
|
||||
- 在异步 Tailscale Serve Control UI 路径上,对于相同 `{scope, clientIp}` 的失败尝试,会在写入失败记录前进行串行化。因此,同一客户端并发的错误尝试,可能会在第二个请求时触发限速,而不是两个请求都作为普通不匹配同时通过。
|
||||
- `gateway.auth.rateLimit.exemptLoopback` 默认为 `true`;如果你有意也要对 localhost 流量进行限速(用于测试设置或严格代理部署),请设为 `false`。
|
||||
- 来自浏览器源的 WS auth 尝试始终会应用限速,且禁用 loopback 豁免(作为针对基于浏览器的 localhost 暴力破解的纵深防御)。
|
||||
- 在 loopback 上,这些来自浏览器源的锁定会按规范化后的 `Origin`
|
||||
值彼此隔离,因此一个 localhost origin 的重复失败不会自动
|
||||
- **Docker 注意事项**:默认的 `loopback` bind 会在容器内监听 `127.0.0.1`。使用 Docker bridge 网络(`-p 18789:18789`)时,流量会到达 `eth0`,因此 Gateway 网关无法访问。请使用 `--network host`,或设置 `bind: "lan"`(或 `bind: "custom"` 并搭配 `customBindHost: "0.0.0.0"`)以在所有网络接口上监听。
|
||||
- **认证**:默认必须启用。非 loopback bind 必须使用 Gateway 网关认证。实际这意味着共享 token/password,或使用带有 `gateway.auth.mode: "trusted-proxy"` 的身份感知型反向代理。新手引导向导默认会生成 token。
|
||||
- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`(包括 SecretRef),请显式将 `gateway.auth.mode` 设为 `token` 或 `password`。若两者都已配置但未设置 mode,启动以及服务安装 / 修复流程都会失败。
|
||||
- `gateway.auth.mode: "none"`:显式无认证模式。仅可用于受信任的本地 local loopback 设置;新手引导提示中不会提供此选项。
|
||||
- `gateway.auth.mode: "trusted-proxy"`:将认证委托给身份感知型反向代理,并信任来自 `gateway.trustedProxies` 的身份头(见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth))。此模式要求**非 loopback** 的代理来源;同机 loopback 反向代理不满足 trusted-proxy 认证要求。
|
||||
- `gateway.auth.allowTailscale`:为 `true` 时,Tailscale Serve 身份头可用于满足 Control UI/WebSocket 认证(通过 `tailscale whois` 验证)。HTTP API 端点**不会**使用该 Tailscale 头认证;它们仍遵循 Gateway 网关正常的 HTTP 认证模式。这个无 token 流程假定 Gateway 网关主机是受信任的。当 `tailscale.mode = "serve"` 时,默认值为 `true`。
|
||||
- `gateway.auth.rateLimit`:可选的认证失败限流器。按客户端 IP 和认证范围生效(共享密钥与设备 token 分别独立跟踪)。被阻止的尝试会返回 `429` + `Retry-After`。
|
||||
- 在异步 Tailscale Serve Control UI 路径上,同一 `{scope, clientIp}` 的失败尝试会在写入失败记录前串行化处理。因此,同一客户端的并发错误尝试,可能会在第二个请求时触发限流,而不是两个请求都竞态通过并仅表现为普通不匹配。
|
||||
- `gateway.auth.rateLimit.exemptLoopback` 默认值为 `true`;如果你明确希望 localhost 流量也被限流(用于测试设置或严格代理部署),请设为 `false`。
|
||||
- 来自浏览器源的 WS 认证尝试始终会受到限流,且不会豁免 loopback(作为防御加固,以应对基于浏览器的 localhost 暴力破解)。
|
||||
- 在 loopback 上,这些来自浏览器源的锁定会按标准化后的 `Origin`
|
||||
值隔离,因此来自某个 localhost origin 的重复失败不会自动
|
||||
锁定另一个 origin。
|
||||
- `tailscale.mode`:`serve`(仅 tailnet,loopback bind)或 `funnel`(公网,需要 auth)。
|
||||
- `controlUi.allowedOrigins`:用于 Gateway 网关 WebSocket 连接的显式浏览器源允许列表。当预期浏览器客户端来自非 loopback 源时为必需。
|
||||
- `controlUi.dangerouslyAllowHostHeaderOriginFallback`:危险模式,为有意依赖 Host 头 origin 策略的部署启用 Host 头 origin 回退。
|
||||
- `remote.transport`:`ssh`(默认)或 `direct`(ws/wss)。对于 `direct`,`remote.url` 必须是 `ws://` 或 `wss://`。
|
||||
- `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`:客户端侧的紧急破窗覆盖,允许向受信任私有网络 IP 使用明文 `ws://`;默认情况下,明文仍然仅限 loopback。
|
||||
- `gateway.remote.token` / `.password` 是远程客户端凭证字段。它们本身不会配置 Gateway 网关 auth。
|
||||
- `gateway.push.apns.relay.baseUrl`:官方/TestFlight iOS 构建在将基于 relay 的注册发布到 Gateway 网关后,供其使用的外部 APNs relay 的基础 HTTPS URL。该 URL 必须与编译进 iOS 构建中的 relay URL 匹配。
|
||||
- `gateway.push.apns.relay.timeoutMs`:Gateway 网关到 relay 的发送超时时间(毫秒)。默认值为 `10000`。
|
||||
- 基于 relay 的注册会委托给特定的 Gateway 网关身份。配对的 iOS 应用会获取 `gateway.identity.get`,在 relay 注册中包含该身份,并将注册作用域的发送授权转发给 Gateway 网关。另一个 Gateway 网关无法复用该已存储注册。
|
||||
- `OPENCLAW_APNS_RELAY_BASE_URL` / `OPENCLAW_APNS_RELAY_TIMEOUT_MS`:上述 relay 配置的临时环境变量覆盖。
|
||||
- `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true`:仅供开发使用的例外开关,允许使用 loopback HTTP relay URL。生产环境的 relay URL 应保持为 HTTPS。
|
||||
- `gateway.channelHealthCheckMinutes`:渠道健康监视器间隔,单位为分钟。设为 `0` 可全局禁用健康监视器重启。默认值:`5`。
|
||||
- `gateway.channelStaleEventThresholdMinutes`:过期 socket 阈值,单位为分钟。请保持其大于或等于 `gateway.channelHealthCheckMinutes`。默认值:`30`。
|
||||
- `gateway.channelMaxRestartsPerHour`:滚动一小时内每个渠道/账号的健康监视器最大重启次数。默认值:`10`。
|
||||
- `channels.<provider>.healthMonitor.enabled`:按渠道关闭健康监视器重启,同时保留全局监视器启用。
|
||||
- `channels.<provider>.accounts.<accountId>.healthMonitor.enabled`:多账号渠道中的按账号覆盖。设置后,它的优先级高于渠道级覆盖。
|
||||
- 仅当 `gateway.auth.*` 未设置时,本地 Gateway 网关调用路径才能使用 `gateway.remote.*` 作为回退。
|
||||
- 如果 `gateway.auth.token` / `gateway.auth.password` 通过 SecretRef 显式配置但无法解析,则解析会以关闭方式失败(不会使用远程回退进行掩盖)。
|
||||
- `trustedProxies`:终止 TLS 或注入转发客户端头的反向代理 IP。只列出你控制的代理。loopback 条目对于同机代理/本地检测设置(例如 Tailscale Serve 或本地反向代理)仍然有效,但它们**不会**让 loopback 请求符合 `gateway.auth.mode: "trusted-proxy"` 的条件。
|
||||
- `allowRealIpFallback`:为 `true` 时,若缺少 `X-Forwarded-For`,Gateway 网关会接受 `X-Real-IP`。默认 `false`,以保持失败即关闭的行为。
|
||||
- `gateway.tools.deny`:为 HTTP `POST /tools/invoke` 额外阻止的工具名称(扩展默认阻止列表)。
|
||||
- `gateway.tools.allow`:从默认 HTTP 阻止列表中移除工具名称。
|
||||
- `tailscale.mode`:`serve`(仅 tailnet,loopback bind)或 `funnel`(公开访问,需要认证)。
|
||||
- `controlUi.allowedOrigins`:用于 Gateway 网关 WebSocket 连接的显式浏览器源允许列表。当预期浏览器客户端来自非 loopback origin 时必须设置。
|
||||
- `controlUi.dangerouslyAllowHostHeaderOriginFallback`:危险模式,为刻意依赖 Host 头 origin 策略的部署启用 Host 头 origin 回退。
|
||||
- `remote.transport`:`ssh`(默认)或 `direct`(ws/wss)。对于 `direct`,`remote.url` 必须为 `ws://` 或 `wss://`。
|
||||
- `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`:客户端进程环境变量级别的紧急覆盖,
|
||||
允许明文 `ws://` 连接到受信任的私有网络 IP;默认情况下,明文连接仍仅限于 loopback。
|
||||
没有对应的 `openclaw.json` 配置项,而且诸如
|
||||
`browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` 之类的浏览器私有网络配置
|
||||
不会影响 Gateway 网关 WebSocket 客户端。
|
||||
- `gateway.remote.token` / `.password` 是远程客户端凭据字段。它们本身不会配置 Gateway 网关认证。
|
||||
- `gateway.push.apns.relay.baseUrl`:官方 / TestFlight iOS 构建在将基于 relay 的注册发布到 Gateway 网关之后,用于外部 APNs relay 的基础 HTTPS URL。此 URL 必须与编译进 iOS 构建的 relay URL 一致。
|
||||
- `gateway.push.apns.relay.timeoutMs`:Gateway 网关到 relay 的发送超时,单位毫秒。默认值为 `10000`。
|
||||
- 基于 relay 的注册会委托给特定的 Gateway 网关身份。配对的 iOS 应用会获取 `gateway.identity.get`,在 relay 注册中包含该身份,并将按注册范围的发送授权转发给 Gateway 网关。其他 Gateway 网关无法复用该已存储注册。
|
||||
- `OPENCLAW_APNS_RELAY_BASE_URL` / `OPENCLAW_APNS_RELAY_TIMEOUT_MS`:对上述 relay 配置的临时环境变量覆盖。
|
||||
- `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true`:仅用于开发环境的放宽开关,允许使用 loopback HTTP relay URL。生产环境的 relay URL 应保持使用 HTTPS。
|
||||
- `gateway.channelHealthCheckMinutes`:渠道健康监控间隔,单位分钟。设为 `0` 可全局禁用健康监控重启。默认值:`5`。
|
||||
- `gateway.channelStaleEventThresholdMinutes`:陈旧 socket 阈值,单位分钟。应保持大于或等于 `gateway.channelHealthCheckMinutes`。默认值:`30`。
|
||||
- `gateway.channelMaxRestartsPerHour`:每个渠道 / 账号在滚动一小时内允许的最大健康监控重启次数。默认值:`10`。
|
||||
- `channels.<provider>.healthMonitor.enabled`:按渠道选择退出健康监控重启,同时保留全局监控启用。
|
||||
- `channels.<provider>.accounts.<accountId>.healthMonitor.enabled`:多账号渠道中的按账号覆盖。设置后,其优先级高于渠道级覆盖。
|
||||
- 仅当 `gateway.auth.*` 未设置时,本地 Gateway 网关调用路径才能将 `gateway.remote.*` 用作回退。
|
||||
- 如果通过 SecretRef 显式配置了 `gateway.auth.token` / `gateway.auth.password` 但无法解析,则解析会以关闭方式失败(不会通过远程回退掩盖问题)。
|
||||
- `trustedProxies`:终止 TLS 或注入转发客户端头的反向代理 IP。只列出你控制的代理。loopback 条目对同机代理 / 本地检测设置仍然有效(例如 Tailscale Serve 或本地反向代理),但它们**不会**让 loopback 请求符合 `gateway.auth.mode: "trusted-proxy"` 的资格。
|
||||
- `allowRealIpFallback`:为 `true` 时,如果缺少 `X-Forwarded-For`,Gateway 网关会接受 `X-Real-IP`。默认值为 `false`,以保持失败即关闭的行为。
|
||||
- `gateway.tools.deny`:对 HTTP `POST /tools/invoke` 额外阻止的工具名(扩展默认拒绝列表)。
|
||||
- `gateway.tools.allow`:从默认 HTTP 拒绝列表中移除工具名。
|
||||
|
||||
</Accordion>
|
||||
|
||||
### OpenAI 兼容端点
|
||||
|
||||
- Chat Completions:默认禁用。通过 `gateway.http.endpoints.chatCompletions.enabled: true` 启用。
|
||||
- Chat Completions:默认禁用。使用 `gateway.http.endpoints.chatCompletions.enabled: true` 启用。
|
||||
- Responses API:`gateway.http.endpoints.responses.enabled`。
|
||||
- Responses URL 输入加固:
|
||||
- `gateway.http.endpoints.responses.maxUrlParts`
|
||||
- `gateway.http.endpoints.responses.files.urlAllowlist`
|
||||
- `gateway.http.endpoints.responses.images.urlAllowlist`
|
||||
空允许列表会被视为未设置;使用 `gateway.http.endpoints.responses.files.allowUrl=false`
|
||||
和/或 `gateway.http.endpoints.responses.images.allowUrl=false` 可禁用 URL 抓取。
|
||||
- 可选的响应加固头:
|
||||
- `gateway.http.securityHeaders.strictTransportSecurity`(仅对你控制的 HTTPS 源设置;参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth#tls-termination-and-hsts))
|
||||
和 / 或 `gateway.http.endpoints.responses.images.allowUrl=false` 可禁用 URL 抓取。
|
||||
- 可选响应加固头:
|
||||
- `gateway.http.securityHeaders.strictTransportSecurity`(仅对你控制的 HTTPS origin 设置;参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth#tls-termination-and-hsts))
|
||||
|
||||
### 多实例隔离
|
||||
|
||||
在同一主机上运行多个 Gateway 网关时,请使用唯一端口和状态目录:
|
||||
在一台主机上运行多个 Gateway 网关时,请为每个实例使用唯一端口和状态目录:
|
||||
|
||||
```bash
|
||||
OPENCLAW_CONFIG_PATH=~/.openclaw/a.json \
|
||||
@ -360,9 +371,9 @@ OPENCLAW_STATE_DIR=~/.openclaw-a \
|
||||
openclaw gateway --port 19001
|
||||
```
|
||||
|
||||
便捷标志:`--dev`(使用 `~/.openclaw-dev` + 端口 `19001`)、`--profile <name>`(使用 `~/.openclaw-<name>`)。
|
||||
便捷标志:`--dev`(使用 `~/.openclaw-dev` + 端口 `19001`),`--profile <name>`(使用 `~/.openclaw-<name>`)。
|
||||
|
||||
参见 [多个 Gateway 网关](/zh-CN/gateway/multiple-gateways)。
|
||||
参见 [Multiple Gateways](/zh-CN/gateway/multiple-gateways)。
|
||||
|
||||
### `gateway.tls`
|
||||
|
||||
@ -380,10 +391,10 @@ openclaw gateway --port 19001
|
||||
}
|
||||
```
|
||||
|
||||
- `enabled`:在 Gateway 网关监听器上启用 TLS 终止(HTTPS/WSS)(默认:`false`)。
|
||||
- `autoGenerate`:当未配置显式文件时,自动生成本地自签名证书/密钥对;仅适用于本地/开发环境。
|
||||
- `enabled`:在 Gateway 网关监听器处启用 TLS 终止(HTTPS/WSS)(默认:`false`)。
|
||||
- `autoGenerate`:当未配置显式文件时,自动生成本地自签名证书 / 密钥对;仅用于本地 / 开发环境。
|
||||
- `certPath`:TLS 证书文件的文件系统路径。
|
||||
- `keyPath`:TLS 私钥文件的文件系统路径;请限制文件权限。
|
||||
- `keyPath`:TLS 私钥文件的文件系统路径;应限制访问权限。
|
||||
- `caPath`:用于客户端验证或自定义信任链的可选 CA bundle 路径。
|
||||
|
||||
### `gateway.reload`
|
||||
@ -400,13 +411,13 @@ openclaw gateway --port 19001
|
||||
}
|
||||
```
|
||||
|
||||
- `mode`:控制在运行时如何应用配置编辑。
|
||||
- `mode`:控制如何在运行时应用配置编辑。
|
||||
- `"off"`:忽略实时编辑;更改需要显式重启。
|
||||
- `"restart"`:配置变更时始终重启 Gateway 网关进程。
|
||||
- `"hot"`:在进程内应用更改而不重启。
|
||||
- `"hybrid"`(默认):先尝试热重载;如有需要则回退为重启。
|
||||
- `debounceMs`:应用配置变更前的去抖窗口,单位为毫秒(非负整数)。
|
||||
- `deferralTimeoutMs`:在强制重启前等待进行中操作完成的最长时间,单位为毫秒(默认:`300000` = 5 分钟)。
|
||||
- `"hybrid"`(默认):先尝试热重载;如果必须,再回退为重启。
|
||||
- `debounceMs`:应用配置更改前的防抖窗口,单位毫秒(非负整数)。
|
||||
- `deferralTimeoutMs`:在强制重启前等待进行中操作完成的最长时间,单位毫秒(默认:`300000` = 5 分钟)。
|
||||
|
||||
---
|
||||
|
||||
@ -443,47 +454,47 @@ openclaw gateway --port 19001
|
||||
}
|
||||
```
|
||||
|
||||
Auth:`Authorization: Bearer <token>` 或 `x-openclaw-token: <token>`。
|
||||
拒绝使用查询字符串中的 hook token。
|
||||
认证方式:`Authorization: Bearer <token>` 或 `x-openclaw-token: <token>`。
|
||||
不接受查询字符串中的 hook token。
|
||||
|
||||
验证与安全说明:
|
||||
|
||||
- `hooks.enabled=true` 需要一个非空的 `hooks.token`。
|
||||
- `hooks.token` 必须与 `gateway.auth.token` **不同**;重复使用 Gateway 网关 token 会被拒绝。
|
||||
- `hooks.path` 不能是 `/`;请使用专用子路径,例如 `/hooks`。
|
||||
- `hooks.enabled=true` 要求 `hooks.token` 为非空。
|
||||
- `hooks.token` 必须与 `gateway.auth.token` **不同**;复用 Gateway 网关 token 会被拒绝。
|
||||
- `hooks.path` 不能为 `/`;请使用专用子路径,例如 `/hooks`。
|
||||
- 如果 `hooks.allowRequestSessionKey=true`,请限制 `hooks.allowedSessionKeyPrefixes`(例如 `["hook:"]`)。
|
||||
- 如果某个映射或 preset 使用模板化的 `sessionKey`,请设置 `hooks.allowedSessionKeyPrefixes` 和 `hooks.allowRequestSessionKey=true`。静态映射键不需要该选择加入开关。
|
||||
- 如果某个 mapping 或 preset 使用了模板化的 `sessionKey`,请设置 `hooks.allowedSessionKeyPrefixes` 和 `hooks.allowRequestSessionKey=true`。静态 mapping 键不需要此显式启用。
|
||||
|
||||
**端点:**
|
||||
|
||||
- `POST /hooks/wake` → `{ text, mode?: "now"|"next-heartbeat" }`
|
||||
- `POST /hooks/agent` → `{ message, name?, agentId?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }`
|
||||
- 仅当 `hooks.allowRequestSessionKey=true`(默认:`false`)时,才接受请求载荷中的 `sessionKey`。
|
||||
- 仅当 `hooks.allowRequestSessionKey=true`(默认:`false`)时,才接受请求负载中的 `sessionKey`。
|
||||
- `POST /hooks/<name>` → 通过 `hooks.mappings` 解析
|
||||
- 模板渲染后的映射 `sessionKey` 值会被视为外部提供,因此同样要求 `hooks.allowRequestSessionKey=true`。
|
||||
- 模板渲染后的 mapping `sessionKey` 值会被视为外部提供,因此同样要求 `hooks.allowRequestSessionKey=true`。
|
||||
|
||||
<Accordion title="映射详情">
|
||||
|
||||
- `match.path` 匹配 `/hooks` 之后的子路径(例如 `/hooks/gmail` → `gmail`)。
|
||||
- `match.source` 匹配通用路径的某个载荷字段。
|
||||
- `{{messages[0].subject}}` 这类模板会从载荷中读取。
|
||||
- `match.source` 匹配通用路径中的某个负载字段。
|
||||
- 类似 `{{messages[0].subject}}` 的模板会从负载中读取。
|
||||
- `transform` 可以指向一个返回 hook 动作的 JS/TS 模块。
|
||||
- `transform.module` 必须是相对路径,并保持在 `hooks.transformsDir` 内(绝对路径和路径穿越都会被拒绝)。
|
||||
- `agentId` 会路由到特定智能体;未知 id 会回退到默认值。
|
||||
- `transform.module` 必须是相对路径,并且必须位于 `hooks.transformsDir` 内部(绝对路径和路径穿越都会被拒绝)。
|
||||
- `agentId` 会路由到特定智能体;未知 ID 会回退到默认值。
|
||||
- `allowedAgentIds`:限制显式路由(`*` 或省略 = 允许全部,`[]` = 全部拒绝)。
|
||||
- `defaultSessionKey`:对于没有显式 `sessionKey` 的 hook 智能体运行,可选的固定会话键。
|
||||
- `allowRequestSessionKey`:允许 `/hooks/agent` 调用方以及模板驱动的映射会话键设置 `sessionKey`(默认:`false`)。
|
||||
- `allowedSessionKeyPrefixes`:显式 `sessionKey` 值(请求 + 映射)的可选前缀允许列表,例如 `["hook:"]`。当任何映射或 preset 使用模板化 `sessionKey` 时,它就变为必需项。
|
||||
- `deliver: true` 会将最终回复发送到渠道;`channel` 默认为 `last`。
|
||||
- `model` 会为此 hook 运行覆盖 LLM(如果设置了模型目录,则该模型必须被允许)。
|
||||
- `defaultSessionKey`:可选的固定会话键,用于没有显式 `sessionKey` 的 hook 智能体运行。
|
||||
- `allowRequestSessionKey`:允许 `/hooks/agent` 调用方和模板驱动的 mapping session key 设置 `sessionKey`(默认:`false`)。
|
||||
- `allowedSessionKeyPrefixes`:显式 `sessionKey` 值(请求 + mapping)的可选前缀允许列表,例如 `["hook:"]`。当任何 mapping 或 preset 使用模板化 `sessionKey` 时,此项变为必需。
|
||||
- `deliver: true` 会将最终回复发送到某个渠道;`channel` 默认值为 `last`。
|
||||
- `model` 为此次 hook 运行覆盖 LLM(如果设置了模型目录,则该模型必须被允许)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
### Gmail 集成
|
||||
|
||||
- 内置 Gmail preset 使用 `sessionKey: "hook:gmail:{{messages[0].id}}"`。
|
||||
- 如果你保留这种按消息路由的方式,请设置 `hooks.allowRequestSessionKey: true`,并限制 `hooks.allowedSessionKeyPrefixes` 以匹配 Gmail 命名空间,例如 `["hook:", "hook:gmail:"]`。
|
||||
- 如果你需要 `hooks.allowRequestSessionKey: false`,请使用静态 `sessionKey` 覆盖该 preset,而不是使用默认的模板化值。
|
||||
- 如果你保留这种按消息路由的方式,请设置 `hooks.allowRequestSessionKey: true`,并将 `hooks.allowedSessionKeyPrefixes` 限制为匹配 Gmail 命名空间,例如 `["hook:", "hook:gmail:"]`。
|
||||
- 如果你需要 `hooks.allowRequestSessionKey: false`,请用静态 `sessionKey` 覆盖该 preset,而不是使用默认的模板化值。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -527,14 +538,14 @@ Auth:`Authorization: Bearer <token>` 或 `x-openclaw-token: <token>`。
|
||||
- `http://<gateway-host>:<gateway.port>/__openclaw__/canvas/`
|
||||
- `http://<gateway-host>:<gateway.port>/__openclaw__/a2ui/`
|
||||
- 仅限本地:保持 `gateway.bind: "loopback"`(默认)。
|
||||
- 非 loopback bind:canvas 路由和其他 Gateway 网关 HTTP 能力一样,需要 Gateway 网关 auth(token/password/trusted-proxy)。
|
||||
- Node WebView 通常不会发送 auth 头;节点配对并连接后,Gateway 网关会为 canvas/A2UI 访问公布节点作用域的能力 URL。
|
||||
- 能力 URL 绑定到当前活动的节点 WS 会话,并且很快过期。不使用基于 IP 的回退。
|
||||
- 非 loopback bind:canvas 路由与其他 Gateway 网关 HTTP 面一样,需要 Gateway 网关认证(token/password/trusted-proxy)。
|
||||
- 节点 WebView 通常不会发送认证头;节点完成配对并连接后,Gateway 网关会发布节点作用域的能力 URL,用于访问 canvas/A2UI。
|
||||
- 能力 URL 绑定到当前活跃的节点 WS 会话,并且会很快过期。不使用基于 IP 的回退。
|
||||
- 会向所提供的 HTML 中注入 live-reload 客户端。
|
||||
- 为空时会自动创建初始 `index.html`。
|
||||
- 同时也会在 `/__openclaw__/a2ui/` 下提供 A2UI。
|
||||
- 更改需要重启 Gateway 网关。
|
||||
- 对于大型目录或 `EMFILE` 错误,请禁用 live reload。
|
||||
- 为空时会自动创建起始 `index.html`。
|
||||
- 也会在 `/__openclaw__/a2ui/` 提供 A2UI。
|
||||
- 变更需要重启 Gateway 网关。
|
||||
- 对于大型目录或出现 `EMFILE` 错误时,请禁用 live reload。
|
||||
|
||||
---
|
||||
|
||||
@ -552,9 +563,9 @@ Auth:`Authorization: Bearer <token>` 或 `x-openclaw-token: <token>`。
|
||||
}
|
||||
```
|
||||
|
||||
- `minimal`(默认):在 TXT 记录中省略 `cliPath` 和 `sshPort`。
|
||||
- `full`:包含 `cliPath` 和 `sshPort`。
|
||||
- 主机名默认为 `openclaw`。可使用 `OPENCLAW_MDNS_HOSTNAME` 覆盖。
|
||||
- `minimal`(默认):从 TXT 记录中省略 `cliPath` + `sshPort`。
|
||||
- `full`:包含 `cliPath` + `sshPort`。
|
||||
- 主机名默认为 `openclaw`。可通过 `OPENCLAW_MDNS_HOSTNAME` 覆盖。
|
||||
|
||||
### 广域(DNS-SD)
|
||||
|
||||
@ -566,7 +577,7 @@ Auth:`Authorization: Bearer <token>` 或 `x-openclaw-token: <token>`。
|
||||
}
|
||||
```
|
||||
|
||||
会在 `~/.openclaw/dns/` 下写入一个单播 DNS-SD 区域。要实现跨网络发现,请配合 DNS 服务器(推荐 CoreDNS)+ Tailscale split DNS 使用。
|
||||
会在 `~/.openclaw/dns/` 下写入一个单播 DNS-SD 区域。若要实现跨网络设备发现,请结合 DNS 服务器(推荐 CoreDNS)+ Tailscale split DNS 一起使用。
|
||||
|
||||
设置:`openclaw dns setup --apply`。
|
||||
|
||||
@ -591,10 +602,10 @@ Auth:`Authorization: Bearer <token>` 或 `x-openclaw-token: <token>`。
|
||||
}
|
||||
```
|
||||
|
||||
- 仅当进程环境中缺少该键时,才会应用内联环境变量。
|
||||
- 只有当进程环境中缺少对应键时,才会应用内联环境变量。
|
||||
- `.env` 文件:当前工作目录下的 `.env` + `~/.openclaw/.env`(两者都不会覆盖现有变量)。
|
||||
- `shellEnv`:从你的登录 shell 配置文件中导入缺失的预期键名。
|
||||
- 完整优先级请参阅[环境](/zh-CN/help/environment)。
|
||||
- `shellEnv`:从你的登录 shell profile 中导入缺失的预期键名。
|
||||
- 完整优先级请参见 [Environment](/zh-CN/help/environment)。
|
||||
|
||||
### 环境变量替换
|
||||
|
||||
@ -609,15 +620,15 @@ Auth:`Authorization: Bearer <token>` 或 `x-openclaw-token: <token>`。
|
||||
```
|
||||
|
||||
- 仅匹配大写名称:`[A-Z_][A-Z0-9_]*`。
|
||||
- 缺失/为空的变量会在配置加载时报错。
|
||||
- 缺失 / 为空的变量会在配置加载时抛出错误。
|
||||
- 使用 `$${VAR}` 可转义为字面量 `${VAR}`。
|
||||
- 适用于 `$include`。
|
||||
|
||||
---
|
||||
|
||||
## 密钥
|
||||
## Secrets
|
||||
|
||||
Secret ref 是增量能力:明文值仍然可用。
|
||||
SecretRef 是增量式的:明文值仍然可用。
|
||||
|
||||
### `SecretRef`
|
||||
|
||||
@ -633,15 +644,15 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
- `source: "env"` 的 id 模式:`^[A-Z][A-Z0-9_]{0,127}$`
|
||||
- `source: "file"` 的 id:绝对 JSON pointer(例如 `"/providers/openai/apiKey"`)
|
||||
- `source: "exec"` 的 id 模式:`^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$`
|
||||
- `source: "exec"` 的 id 不能包含 `.` 或 `..` 这样的斜杠分隔路径段(例如 `a/../b` 会被拒绝)
|
||||
- `source: "exec"` 的 id 不能包含 `.` 或 `..` 这样的按斜杠分隔路径段(例如 `a/../b` 会被拒绝)
|
||||
|
||||
### 支持的凭证能力
|
||||
### 支持的凭据面
|
||||
|
||||
- 规范矩阵:[SecretRef 凭证能力](/zh-CN/reference/secretref-credential-surface)
|
||||
- `secrets apply` 会定位受支持的 `openclaw.json` 凭证路径。
|
||||
- `auth-profiles.json` 中的 ref 也包含在运行时解析和审计覆盖范围内。
|
||||
- 规范矩阵:[SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface)
|
||||
- `secrets apply` 会定位受支持的 `openclaw.json` 凭据路径。
|
||||
- `auth-profiles.json` 引用也包含在运行时解析和审计覆盖范围内。
|
||||
|
||||
### Secret providers 配置
|
||||
### Secret 提供商配置
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -671,18 +682,18 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
|
||||
说明:
|
||||
|
||||
- `file` provider 支持 `mode: "json"` 和 `mode: "singleValue"`(在 singleValue 模式下,`id` 必须是 `"value"`)。
|
||||
- 当无法验证 Windows ACL 时,file 和 exec provider 路径会以失败即关闭的方式处理。只有在路径受信任但无法验证时,才设置 `allowInsecurePath: true`。
|
||||
- `exec` provider 要求使用绝对 `command` 路径,并通过 stdin/stdout 传递协议载荷。
|
||||
- 默认情况下,符号链接命令路径会被拒绝。设置 `allowSymlinkCommand: true` 可允许符号链接路径,同时仍验证解析后的目标路径。
|
||||
- 如果配置了 `trustedDirs`,受信任目录检查将作用于解析后的目标路径。
|
||||
- `file` 提供商支持 `mode: "json"` 和 `mode: "singleValue"`(在 singleValue 模式下,`id` 必须为 `"value"`)。
|
||||
- 当 Windows ACL 验证不可用时,文件和 exec 提供商路径会以关闭方式失败。仅当路径可信但无法验证时,才设置 `allowInsecurePath: true`。
|
||||
- `exec` 提供商要求 `command` 为绝对路径,并通过 stdin/stdout 使用协议负载。
|
||||
- 默认情况下,符号链接命令路径会被拒绝。设置 `allowSymlinkCommand: true` 可允许符号链接路径,同时仍验证其解析后的目标路径。
|
||||
- 如果配置了 `trustedDirs`,则受信任目录检查会应用于解析后的目标路径。
|
||||
- 默认情况下,`exec` 子进程环境是最小化的;请通过 `passEnv` 显式传递所需变量。
|
||||
- Secret ref 会在激活时解析到内存快照中,然后请求路径只读取该快照。
|
||||
- 激活期间会应用活动能力过滤:启用能力上的未解析 ref 会导致启动/重载失败,而未激活能力会被跳过并附带诊断信息。
|
||||
- Secret 引用会在激活时解析为内存快照,之后请求路径只读取该快照。
|
||||
- 激活期间会应用活跃面过滤:启用面上的未解析引用会导致启动 / 重载失败,而未激活的面会被跳过并附带诊断信息。
|
||||
|
||||
---
|
||||
|
||||
## Auth 存储
|
||||
## 凭据存储
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -700,13 +711,13 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- 按智能体划分的配置文件存储在 `<agentDir>/auth-profiles.json`。
|
||||
- `auth-profiles.json` 支持静态凭证模式的值级 ref(`api_key` 使用 `keyRef`,`token` 使用 `tokenRef`)。
|
||||
- OAuth 模式配置文件(`auth.profiles.<id>.mode = "oauth"`)不支持基于 SecretRef 的 auth 配置文件凭证。
|
||||
- 静态运行时凭证来自内存中的已解析快照;发现旧版静态 `auth.json` 条目时会进行清理。
|
||||
- 旧版 OAuth 从 `~/.openclaw/credentials/oauth.json` 导入。
|
||||
- 参阅 [OAuth](/zh-CN/concepts/oauth)。
|
||||
- 密钥运行时行为以及 `audit/configure/apply` 工具:参阅[密钥管理](/zh-CN/gateway/secrets)。
|
||||
- 按智能体划分的 profiles 存储在 `<agentDir>/auth-profiles.json`。
|
||||
- `auth-profiles.json` 支持值级引用(静态凭据模式下,`api_key` 使用 `keyRef`,`token` 使用 `tokenRef`)。
|
||||
- OAuth 模式 profile(`auth.profiles.<id>.mode = "oauth"`)不支持由 SecretRef 提供支持的 auth-profile 凭据。
|
||||
- 静态运行时凭据来自内存中的已解析快照;发现旧版静态 `auth.json` 条目时会进行清理。
|
||||
- 旧版 OAuth 会从 `~/.openclaw/credentials/oauth.json` 导入。
|
||||
- 参见 [OAuth](/zh-CN/concepts/oauth)。
|
||||
- Secrets 运行时行为以及 `audit/configure/apply` 工具:参见 [Secrets Management](/zh-CN/gateway/secrets)。
|
||||
|
||||
### `auth.cooldowns`
|
||||
|
||||
@ -728,15 +739,20 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- `billingBackoffHours`:当配置文件因真实的计费/余额不足错误而失败时,使用的基础退避时长(小时)(默认:`5`)。即使在 `401`/`403` 响应上,明确的计费文本仍可能归入这里,但提供商专属文本匹配器仍仅限于其所属提供商(例如 OpenRouter 的 `Key limit exceeded`)。可重试的 HTTP `402` 使用窗口或 organization/workspace 支出限制消息,则仍归入 `rate_limit` 路径。
|
||||
- `billingBackoffHoursByProvider`:计费退避时长的可选按提供商覆盖。
|
||||
- `billingMaxHours`:计费退避指数增长的小时上限(默认:`24`)。
|
||||
- `authPermanentBackoffMinutes`:高置信度 `auth_permanent` 失败的基础退避时长(分钟)(默认:`10`)。
|
||||
- `authPermanentMaxMinutes`:`auth_permanent` 退避增长的分钟上限(默认:`60`)。
|
||||
- `failureWindowHours`:用于退避计数器的滚动时间窗口(小时)(默认:`24`)。
|
||||
- `overloadedProfileRotations`:对于 overloaded 错误,在切换到模型回退之前,允许同一提供商 auth 配置文件轮换的最大次数(默认:`1`)。像 `ModelNotReadyException` 这样的提供商繁忙形态会归入这里。
|
||||
- `overloadedBackoffMs`:在重试 overloaded 提供商/配置文件轮换之前的固定延迟(毫秒)(默认:`0`)。
|
||||
- `rateLimitedProfileRotations`:对于 rate-limit 错误,在切换到模型回退之前,允许同一提供商 auth 配置文件轮换的最大次数(默认:`1`)。该 rate-limit 桶包括提供商形态文本,例如 `Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded` 和 `resource exhausted`。
|
||||
- `billingBackoffHours`:当某个 profile 因真实的
|
||||
计费 / 额度不足错误而失败时,使用的基础退避时间(单位:小时)(默认:`5`)。即使在 `401`/`403` 响应中,
|
||||
明确的计费文本仍可能归入这里,但提供商专属的文本
|
||||
匹配器仍然仅作用于拥有它们的提供商(例如 OpenRouter 的
|
||||
`Key limit exceeded`)。可重试的 HTTP `402` 用量窗口或
|
||||
organization/workspace 支出上限消息则仍归入 `rate_limit` 路径。
|
||||
- `billingBackoffHoursByProvider`:可选的按提供商划分的计费退避小时数覆盖。
|
||||
- `billingMaxHours`:计费退避指数增长的上限小时数(默认:`24`)。
|
||||
- `authPermanentBackoffMinutes`:高置信度 `auth_permanent` 失败的基础退避时间,单位分钟(默认:`10`)。
|
||||
- `authPermanentMaxMinutes`:`auth_permanent` 退避增长的上限分钟数(默认:`60`)。
|
||||
- `failureWindowHours`:用于退避计数器的滚动时间窗口,单位小时(默认:`24`)。
|
||||
- `overloadedProfileRotations`:对于过载错误,在切换到模型回退之前,同一提供商 auth-profile 可轮换的最大次数(默认:`1`)。诸如 `ModelNotReadyException` 这类提供商忙碌形态会归入此项。
|
||||
- `overloadedBackoffMs`:在重试过载的提供商 / profile 轮换前的固定延迟,单位毫秒(默认:`0`)。
|
||||
- `rateLimitedProfileRotations`:对于速率限制错误,在切换到模型回退之前,同一提供商 auth-profile 可轮换的最大次数(默认:`1`)。该速率限制桶包括提供商形态的文本,例如 `Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded` 和 `resource exhausted`。
|
||||
|
||||
---
|
||||
|
||||
@ -756,9 +772,9 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
```
|
||||
|
||||
- 默认日志文件:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`。
|
||||
- 设置 `logging.file` 可使用固定路径。
|
||||
- 设置 `logging.file` 以使用固定路径。
|
||||
- 使用 `--verbose` 时,`consoleLevel` 会提升为 `debug`。
|
||||
- `maxFileBytes`:在抑制写入之前,日志文件允许的最大大小(字节)(正整数;默认:`524288000` = 500 MB)。生产部署请使用外部日志轮转。
|
||||
- `maxFileBytes`:在抑制写入前,日志文件允许的最大字节数(正整数;默认:`524288000` = 500 MB)。生产部署请使用外部日志轮转。
|
||||
|
||||
---
|
||||
|
||||
@ -796,19 +812,19 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
```
|
||||
|
||||
- `enabled`:仪表输出的总开关(默认:`true`)。
|
||||
- `flags`:启用定向日志输出的标志字符串数组(支持通配符,例如 `"telegram.*"` 或 `"*"`)。
|
||||
- `stuckSessionWarnMs`:当会话仍处于处理中状态时,发出会话卡住警告的时长阈值(毫秒)。
|
||||
- `otel.enabled`:启用 OpenTelemetry 导出管道(默认:`false`)。
|
||||
- `otel.endpoint`:用于 OTel 导出的采集器 URL。
|
||||
- `flags`:用于启用定向日志输出的标志字符串数组(支持通配符,如 `"telegram.*"` 或 `"*"`)。
|
||||
- `stuckSessionWarnMs`:当某个会话仍处于处理中状态时,发出卡住会话警告的时长阈值,单位毫秒。
|
||||
- `otel.enabled`:启用 OpenTelemetry 导出管线(默认:`false`)。
|
||||
- `otel.endpoint`:用于 OTel 导出的收集器 URL。
|
||||
- `otel.protocol`:`"http/protobuf"`(默认)或 `"grpc"`。
|
||||
- `otel.headers`:随 OTel 导出请求发送的额外 HTTP/gRPC 元数据头。
|
||||
- `otel.serviceName`:资源属性使用的服务名称。
|
||||
- `otel.serviceName`:资源属性中的服务名。
|
||||
- `otel.traces` / `otel.metrics` / `otel.logs`:启用 trace、metrics 或 log 导出。
|
||||
- `otel.sampleRate`:trace 采样率,范围 `0`–`1`。
|
||||
- `otel.flushIntervalMs`:定期刷新遥测数据的时间间隔(毫秒)。
|
||||
- `otel.flushIntervalMs`:定期刷新遥测数据的时间间隔,单位毫秒。
|
||||
- `cacheTrace.enabled`:为嵌入式运行记录缓存跟踪快照(默认:`false`)。
|
||||
- `cacheTrace.filePath`:缓存跟踪 JSONL 的输出路径(默认:`$OPENCLAW_STATE_DIR/logs/cache-trace.jsonl`)。
|
||||
- `cacheTrace.includeMessages` / `includePrompt` / `includeSystem`:控制缓存跟踪输出中包含的内容(默认全部为 `true`)。
|
||||
- `cacheTrace.includeMessages` / `includePrompt` / `includeSystem`:控制缓存跟踪输出中包含哪些内容(默认全部为 `true`)。
|
||||
|
||||
---
|
||||
|
||||
@ -830,12 +846,12 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- `channel`:npm/git 安装所使用的发布渠道——`"stable"`、`"beta"` 或 `"dev"`。
|
||||
- `channel`:用于 npm/git 安装的发布渠道——`"stable"`、`"beta"` 或 `"dev"`。
|
||||
- `checkOnStart`:Gateway 网关启动时检查 npm 更新(默认:`true`)。
|
||||
- `auto.enabled`:为包安装启用后台自动更新(默认:`false`)。
|
||||
- `auto.stableDelayHours`:stable 渠道自动应用前的最小时延(小时)(默认:`6`;最大:`168`)。
|
||||
- `auto.stableJitterHours`:stable 渠道额外的发布时间分散窗口(小时)(默认:`12`;最大:`168`)。
|
||||
- `auto.betaCheckIntervalHours`:beta 渠道检查运行的频率(小时)(默认:`1`;最大:`24`)。
|
||||
- `auto.stableDelayHours`:stable 渠道自动应用前的最小延迟,单位小时(默认:`6`;最大:`168`)。
|
||||
- `auto.stableJitterHours`:stable 渠道发布额外分散窗口,单位小时(默认:`12`;最大:`168`)。
|
||||
- `auto.betaCheckIntervalHours`:beta 渠道检查运行频率,单位小时(默认:`1`;最大:`24`)。
|
||||
|
||||
---
|
||||
|
||||
@ -868,22 +884,22 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- `enabled`:ACP 功能总开关(默认:`false`)。
|
||||
- `dispatch.enabled`:ACP 会话轮次分发的独立开关(默认:`true`)。设为 `false` 可在保留 ACP 命令可用的同时阻止执行。
|
||||
- `backend`:默认 ACP 运行时后端 id(必须与已注册的 ACP 运行时插件匹配)。
|
||||
- `defaultAgent`:当生成操作未指定显式目标时,ACP 目标智能体 id 的回退值。
|
||||
- `allowedAgents`:允许用于 ACP 运行时会话的智能体 id 列表;空值表示不施加额外限制。
|
||||
- `maxConcurrentSessions`:同时处于活动状态的 ACP 会话最大数量。
|
||||
- `stream.coalesceIdleMs`:流式文本的空闲合并刷新窗口(毫秒)。
|
||||
- `stream.maxChunkChars`:在拆分流式分块投影之前允许的最大分块大小。
|
||||
- `stream.repeatSuppression`:每轮抑制重复的状态/工具行(默认:`true`)。
|
||||
- `stream.deliveryMode`:`"live"` 表示增量流式传输;`"final_only"` 表示缓冲到轮次终止事件后再输出。
|
||||
- `stream.hiddenBoundarySeparator`:隐藏工具事件之后、可见文本之前使用的分隔符(默认:`"paragraph"`)。
|
||||
- `stream.maxOutputChars`:每个 ACP 轮次可投影的助手输出最大字符数。
|
||||
- `stream.maxSessionUpdateChars`:投影 ACP 状态/更新行的最大字符数。
|
||||
- `stream.tagVisibility`:标签名到布尔可见性覆盖的记录,用于流式事件。
|
||||
- `runtime.ttlMinutes`:ACP 会话工作进程在符合清理条件前的空闲 TTL(分钟)。
|
||||
- `runtime.installCommand`:在引导 ACP 运行时环境时执行的可选安装命令。
|
||||
- `enabled`:全局 ACP 功能门控(默认:`false`)。
|
||||
- `dispatch.enabled`:ACP 会话轮次分发的独立门控(默认:`true`)。设为 `false` 可在保留 ACP 命令可用的同时阻止执行。
|
||||
- `backend`:默认 ACP 运行时 backend id(必须匹配已注册的 ACP 运行时插件)。
|
||||
- `defaultAgent`:当生成运行未指定显式目标时,ACP 目标智能体 id 的回退值。
|
||||
- `allowedAgents`:允许用于 ACP 运行时会话的智能体 id 允许列表;为空表示没有额外限制。
|
||||
- `maxConcurrentSessions`:最大并发活跃 ACP 会话数。
|
||||
- `stream.coalesceIdleMs`:流式文本的空闲合并刷新窗口,单位毫秒。
|
||||
- `stream.maxChunkChars`:流式分块投影在拆分前允许的最大块大小。
|
||||
- `stream.repeatSuppression`:按轮次抑制重复的状态 / 工具行(默认:`true`)。
|
||||
- `stream.deliveryMode`:`"live"` 表示增量流式输出;`"final_only"` 表示缓冲至轮次终结事件后再输出。
|
||||
- `stream.hiddenBoundarySeparator`:隐藏工具事件之后、可见文本之前所使用的分隔符(默认:`"paragraph"`)。
|
||||
- `stream.maxOutputChars`:每个 ACP 轮次投影的最大助手输出字符数。
|
||||
- `stream.maxSessionUpdateChars`:投影的 ACP 状态 / 更新行允许的最大字符数。
|
||||
- `stream.tagVisibility`:tag 名称到布尔可见性覆盖的记录,用于流式事件。
|
||||
- `runtime.ttlMinutes`:ACP 会话 worker 在空闲后可被清理前的 TTL,单位分钟。
|
||||
- `runtime.installCommand`:在引导 ACP 运行时环境时可运行的可选安装命令。
|
||||
|
||||
---
|
||||
|
||||
@ -899,11 +915,11 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- `cli.banner.taglineMode` 控制 banner 标语样式:
|
||||
- `"random"`(默认):轮换的有趣/节日标语。
|
||||
- `"default"`:固定的中性标语(`All your chats, one OpenClaw.`)。
|
||||
- `"off"`:不显示标语文本(仍显示 banner 标题/版本)。
|
||||
- 若要隐藏整个 banner(而不仅仅是标语),请设置环境变量 `OPENCLAW_HIDE_BANNER=1`。
|
||||
- `cli.banner.taglineMode` 控制横幅标语样式:
|
||||
- `"random"`(默认):轮换显示有趣 / 季节性标语。
|
||||
- `"default"`:固定中性标语(`All your chats, one OpenClaw.`)。
|
||||
- `"off"`:不显示标语文本(仍显示横幅标题 / 版本)。
|
||||
- 若要隐藏整个横幅(而不仅仅是标语),请设置环境变量 `OPENCLAW_HIDE_BANNER=1`。
|
||||
|
||||
---
|
||||
|
||||
@ -927,13 +943,13 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
|
||||
## 身份
|
||||
|
||||
请参阅[智能体默认值](/zh-CN/gateway/config-agents#agent-defaults)中的 `agents.list` 身份字段。
|
||||
请参见 [智能体默认值](/zh-CN/gateway/config-agents#agent-defaults) 下 `agents.list` 的身份字段。
|
||||
|
||||
---
|
||||
|
||||
## Bridge protocol(旧版节点,历史参考)
|
||||
## Bridge protocol(旧版节点,历史参考)(旧版,已移除)
|
||||
|
||||
当前构建已不再包含 TCP bridge。节点通过 Gateway 网关 WebSocket 连接。`bridge.*` 键已不再属于配置 schema 的一部分(在移除前,验证会失败;`openclaw doctor --fix` 可移除未知键)。
|
||||
当前构建已不再包含 TCP bridge。节点通过 Gateway 网关 WebSocket 连接。`bridge.*` 键已不再属于配置 schema 的一部分(在移除前,验证会失败;可使用 `openclaw doctor --fix` 清理未知键)。
|
||||
|
||||
<Accordion title="旧版 bridge 配置(历史参考)">
|
||||
|
||||
@ -973,11 +989,11 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- `sessionRetention`:从 `sessions.json` 中清理前,已完成的隔离 cron 运行会话应保留多长时间。也控制已归档、已删除的 cron 转录内容的清理。默认:`24h`;设为 `false` 可禁用。
|
||||
- `runLog.maxBytes`:每个运行日志文件(`cron/runs/<jobId>.jsonl`)在触发清理前允许的最大大小。默认:`2_000_000` 字节。
|
||||
- `runLog.keepLines`:触发运行日志清理时保留的最新行数。默认:`2000`。
|
||||
- `webhookToken`:用于 cron webhook POST 投递(`delivery.mode = "webhook"`)的 bearer token;如果省略,则不会发送 auth 头。
|
||||
- `webhook`:已弃用的旧版回退 webhook URL(http/https),仅用于仍带有 `notify: true` 的已存储任务。
|
||||
- `sessionRetention`:完成的隔离 cron 运行会话在从 `sessions.json` 修剪前保留多久。也控制已归档、已删除的 cron 转录内容的清理。默认值:`24h`;设为 `false` 可禁用。
|
||||
- `runLog.maxBytes`:每个运行日志文件(`cron/runs/<jobId>.jsonl`)在触发修剪前允许的最大大小。默认值:`2_000_000` 字节。
|
||||
- `runLog.keepLines`:触发运行日志修剪时保留的最新行数。默认值:`2000`。
|
||||
- `webhookToken`:用于 cron webhook `POST` 投递(`delivery.mode = "webhook"`)的 bearer token;若省略,则不会发送认证头。
|
||||
- `webhook`:已弃用的旧版回退 webhook URL(http/https),仅用于仍然带有 `notify: true` 的已存储任务。
|
||||
|
||||
### `cron.retry`
|
||||
|
||||
@ -993,11 +1009,11 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- `maxAttempts`:一次性任务在瞬时错误上的最大重试次数(默认:`3`;范围:`0`–`10`)。
|
||||
- `backoffMs`:每次重试对应的退避延迟数组,单位为毫秒(默认:`[30000, 60000, 300000]`;1–10 项)。
|
||||
- `retryOn`:触发重试的错误类型——`"rate_limit"`、`"overloaded"`、`"network"`、`"timeout"`、`"server_error"`。省略时将重试所有瞬时类型。
|
||||
- `maxAttempts`:单次任务在瞬时错误下的最大重试次数(默认:`3`;范围:`0`–`10`)。
|
||||
- `backoffMs`:每次重试尝试使用的退避延迟数组,单位毫秒(默认:`[30000, 60000, 300000]`;1–10 个条目)。
|
||||
- `retryOn`:触发重试的错误类型——`"rate_limit"`、`"overloaded"`、`"network"`、`"timeout"`、`"server_error"`。省略则表示对所有瞬时类型都进行重试。
|
||||
|
||||
仅适用于一次性 cron 任务。周期性任务使用单独的失败处理机制。
|
||||
仅适用于单次 cron 任务。周期性任务使用独立的失败处理机制。
|
||||
|
||||
### `cron.failureAlert`
|
||||
|
||||
@ -1015,11 +1031,11 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
}
|
||||
```
|
||||
|
||||
- `enabled`:为 cron 任务启用失败告警(默认:`false`)。
|
||||
- `enabled`:启用 cron 任务失败告警(默认:`false`)。
|
||||
- `after`:连续失败多少次后触发告警(正整数,最小值:`1`)。
|
||||
- `cooldownMs`:同一任务重复告警之间的最小间隔,单位为毫秒(非负整数)。
|
||||
- `mode`:投递模式——`"announce"` 通过渠道消息发送;`"webhook"` 向已配置 webhook 发起 POST。
|
||||
- `accountId`:可选的账号或渠道 id,用于限定告警投递范围。
|
||||
- `cooldownMs`:同一任务重复告警之间的最小毫秒间隔(非负整数)。
|
||||
- `mode`:投递模式——`"announce"` 通过渠道消息发送;`"webhook"` 向已配置的 webhook 发起 `POST`。
|
||||
- `accountId`:用于限定告警投递范围的可选账号或渠道 id。
|
||||
|
||||
### `cron.failureDestination`
|
||||
|
||||
@ -1037,15 +1053,15 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
```
|
||||
|
||||
- 所有任务共用的 cron 失败通知默认目标。
|
||||
- `mode`:`"announce"` 或 `"webhook"`;当存在足够的目标数据时,默认为 `"announce"`。
|
||||
- `channel`:announce 投递的渠道覆盖。`"last"` 会复用最近一次已知的投递渠道。
|
||||
- `to`:显式的 announce 目标或 webhook URL。webhook 模式下为必需。
|
||||
- `mode`:`"announce"` 或 `"webhook"`;当存在足够的目标数据时,默认值为 `"announce"`。
|
||||
- `channel`:announce 投递的渠道覆盖。`"last"` 会复用最后一次已知的投递渠道。
|
||||
- `to`:显式 announce 目标或 webhook URL。webhook 模式下必填。
|
||||
- `accountId`:可选的投递账号覆盖。
|
||||
- 每个任务的 `delivery.failureDestination` 会覆盖该全局默认值。
|
||||
- 当全局和任务级失败目标都未设置时,已通过 `announce` 投递的任务在失败时会回退到其主 announce 目标。
|
||||
- `delivery.failureDestination` 仅支持 `sessionTarget="isolated"` 的任务,除非该任务的主 `delivery.mode` 为 `"webhook"`。
|
||||
- 每个任务的 `delivery.failureDestination` 会覆盖这个全局默认值。
|
||||
- 当全局和按任务失败目标都未设置时,那些已通过 `announce` 投递的任务在失败时会回退到其主要 announce 目标。
|
||||
- 除非任务的主 `delivery.mode` 为 `"webhook"`,否则 `delivery.failureDestination` 仅支持 `sessionTarget="isolated"` 的任务。
|
||||
|
||||
请参阅 [Cron Jobs](/zh-CN/automation/cron-jobs)。隔离的 cron 执行会作为[后台任务](/zh-CN/automation/tasks)进行跟踪。
|
||||
参见 [Cron Jobs](/zh-CN/automation/cron-jobs)。隔离的 cron 执行会作为[后台任务](/zh-CN/automation/tasks)进行跟踪。
|
||||
|
||||
---
|
||||
|
||||
@ -1053,32 +1069,32 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
|
||||
在 `tools.media.models[].args` 中展开的模板占位符:
|
||||
|
||||
| Variable | Description |
|
||||
| ------------------ | ------------------------------------------------- |
|
||||
| `{{Body}}` | 完整的入站消息正文 |
|
||||
| `{{RawBody}}` | 原始正文(无历史记录/发送者包装) |
|
||||
| `{{BodyStripped}}` | 去除群组提及后的正文 |
|
||||
| `{{From}}` | 发送者标识符 |
|
||||
| `{{To}}` | 目标标识符 |
|
||||
| `{{MessageSid}}` | 渠道消息 id |
|
||||
| `{{SessionId}}` | 当前会话 UUID |
|
||||
| `{{IsNewSession}}` | 新建会话时为 `"true"` |
|
||||
| `{{MediaUrl}}` | 入站媒体伪 URL |
|
||||
| `{{MediaPath}}` | 本地媒体路径 |
|
||||
| `{{MediaType}}` | 媒体类型(image/audio/document/…) |
|
||||
| `{{Transcript}}` | 音频转录文本 |
|
||||
| `{{Prompt}}` | CLI 条目的已解析媒体提示 |
|
||||
| `{{MaxChars}}` | CLI 条目的已解析最大输出字符数 |
|
||||
| `{{ChatType}}` | `"direct"` 或 `"group"` |
|
||||
| `{{GroupSubject}}` | 群组主题(尽力而为) |
|
||||
| `{{GroupMembers}}` | 群组成员预览(尽力而为) |
|
||||
| `{{SenderName}}` | 发送者显示名称(尽力而为) |
|
||||
| `{{SenderE164}}` | 发送者电话号码(尽力而为) |
|
||||
| `{{Provider}}` | 提供商提示(whatsapp、telegram、discord 等) |
|
||||
| Variable | Description |
|
||||
| ------------------ | ---------------------------------- |
|
||||
| `{{Body}}` | 完整的入站消息正文 |
|
||||
| `{{RawBody}}` | 原始正文(无历史记录 / 发送者包装) |
|
||||
| `{{BodyStripped}}` | 去除群组提及后的正文 |
|
||||
| `{{From}}` | 发送者标识符 |
|
||||
| `{{To}}` | 目标标识符 |
|
||||
| `{{MessageSid}}` | 渠道消息 id |
|
||||
| `{{SessionId}}` | 当前会话 UUID |
|
||||
| `{{IsNewSession}}` | 新建会话时为 `"true"` |
|
||||
| `{{MediaUrl}}` | 入站媒体伪 URL |
|
||||
| `{{MediaPath}}` | 本地媒体路径 |
|
||||
| `{{MediaType}}` | 媒体类型(image/audio/document/…) |
|
||||
| `{{Transcript}}` | 音频转录文本 |
|
||||
| `{{Prompt}}` | CLI 条目的已解析媒体提示词 |
|
||||
| `{{MaxChars}}` | CLI 条目的已解析最大输出字符数 |
|
||||
| `{{ChatType}}` | `"direct"` 或 `"group"` |
|
||||
| `{{GroupSubject}}` | 群组主题(尽力而为) |
|
||||
| `{{GroupMembers}}` | 群组成员预览(尽力而为) |
|
||||
| `{{SenderName}}` | 发送者显示名称(尽力而为) |
|
||||
| `{{SenderE164}}` | 发送者电话号码(尽力而为) |
|
||||
| `{{Provider}}` | 提供商提示(whatsapp、telegram、discord 等) |
|
||||
|
||||
---
|
||||
|
||||
## 配置包含(`$include`)
|
||||
## 配置 include(`$include`)
|
||||
|
||||
将配置拆分为多个文件:
|
||||
|
||||
@ -1095,20 +1111,20 @@ Secret ref 是增量能力:明文值仍然可用。
|
||||
|
||||
**合并行为:**
|
||||
|
||||
- 单个文件:替换所在的整个对象。
|
||||
- 单文件:替换其所在的容器对象。
|
||||
- 文件数组:按顺序深度合并(后者覆盖前者)。
|
||||
- 同级键:在包含之后合并(覆盖被包含的值)。
|
||||
- 嵌套包含:最多 10 层。
|
||||
- 路径:相对于包含它的文件解析,但必须保持在顶层配置目录(`openclaw.json` 的 `dirname`)内。只有在最终仍解析到该边界内时,才允许绝对路径/`../` 形式。
|
||||
- 当 OpenClaw 拥有的写入仅更改某个由单文件 include 支持的顶层分区时,写入会直通到该被包含文件。例如,`plugins install` 会将 `plugins: { $include: "./plugins.json5" }` 的更新写入 `plugins.json5`,并保持 `openclaw.json` 不变。
|
||||
- 根级 include、include 数组以及带有同级覆盖的 include,对于 OpenClaw 拥有的写入都是只读的;此类写入会以失败即关闭的方式失败,而不会将配置拍平。
|
||||
- 错误:对于缺失文件、解析错误和循环包含,会提供清晰的错误消息。
|
||||
- 同级键:在 include 之后合并(覆盖 include 的值)。
|
||||
- 嵌套 include:最多支持 10 层深度。
|
||||
- 路径:相对于包含它的文件解析,但必须保持在顶层配置目录(`openclaw.json` 的 `dirname`)之内。只有在最终解析结果仍位于该边界内时,才允许使用绝对路径 / `../` 形式。
|
||||
- 当 OpenClaw 自有写入仅更改由单文件 include 支持的某个顶层 section 时,写入会透传到该 include 文件。例如,`plugins install` 会将 `plugins: { $include: "./plugins.json5" }` 更新到 `plugins.json5` 中,而保持 `openclaw.json` 不变。
|
||||
- 根 include、include 数组,以及带有同级覆盖的 include,对于 OpenClaw 自有写入来说是只读的;这类写入会以关闭方式失败,而不会扁平化配置。
|
||||
- 错误:对于缺失文件、解析错误和循环 include,会给出清晰的消息。
|
||||
|
||||
---
|
||||
|
||||
_相关内容:[配置](/zh-CN/gateway/configuration) · [配置示例](/zh-CN/gateway/configuration-examples) · [Doctor](/zh-CN/gateway/doctor)_
|
||||
_相关:[Configuration](/zh-CN/gateway/configuration) · [Configuration Examples](/zh-CN/gateway/configuration-examples) · [Doctor](/zh-CN/gateway/doctor)_
|
||||
|
||||
## 相关内容
|
||||
## 相关
|
||||
|
||||
- [配置](/zh-CN/gateway/configuration)
|
||||
- [配置示例](/zh-CN/gateway/configuration-examples)
|
||||
- [Configuration](/zh-CN/gateway/configuration)
|
||||
- [Configuration examples](/zh-CN/gateway/configuration-examples)
|
||||
|
||||
@ -1,81 +1,81 @@
|
||||
---
|
||||
read_when:
|
||||
- 运行或排查远程 Gateway 网关设置
|
||||
summary: 使用 SSH 隧道(Gateway 网关 WS)和 tailnet 的远程访问
|
||||
- 运行或排查远程 Gateway 网关设置问题
|
||||
summary: 使用 SSH 隧道(Gateway 网关 WS)和 tailnet 进行远程访问
|
||||
title: 远程访问
|
||||
x-i18n:
|
||||
generated_at: "2026-04-24T03:16:26Z"
|
||||
generated_at: "2026-04-24T06:43:47Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 3753f29d6b3cc3f1a2f749cc0fdfdd60dfde8822f0ec6db0e18e5412de0980da
|
||||
source_hash: 66eebbe3762134f29f982201d7e79a789624b96042bd931e07d9855710d64bfe
|
||||
source_path: gateway/remote.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 远程访问(SSH、隧道和 tailnet)
|
||||
|
||||
本仓库通过在专用主机(桌面机 / 服务器)上保持单个 Gateway 网关(主实例)运行,并让客户端连接到它,来支持“通过 SSH 远程访问”。
|
||||
此仓库通过在专用主机(桌面机/服务器)上保持一个正在运行的 Gateway 网关(主节点),并让客户端连接到它,从而支持“通过 SSH 进行远程访问”。
|
||||
|
||||
- 对于**操作员(你 / macOS 应用)**:SSH 隧道是通用回退方案。
|
||||
- 对于**节点(iOS/Android 和未来设备)**:连接到 Gateway 网关 **WebSocket**(按需使用 LAN/tailnet 或 SSH 隧道)。
|
||||
- 对于**操作端(你 / macOS 应用)**:SSH 隧道是通用的兜底方案。
|
||||
- 对于**节点(iOS/Android 和未来的设备)**:连接到 Gateway 网关 **WebSocket**(根据需要使用局域网 / tailnet 或 SSH 隧道)。
|
||||
|
||||
## 核心思路
|
||||
|
||||
- Gateway 网关 WebSocket 会绑定到你配置端口上的**回环地址**(默认是 18789)。
|
||||
- 对于远程使用,你可以通过 SSH 转发这个回环端口(或者使用 tailnet/VPN,以减少隧道依赖)。
|
||||
- Gateway 网关 WebSocket 绑定到你所配置端口的**loopback**(默认是 18789)。
|
||||
- 在远程使用时,你可以通过 SSH 转发这个 loopback 端口(或者使用 tailnet / VPN,以减少对隧道的依赖)。
|
||||
|
||||
## 常见 VPN/tailnet 设置(智能体所在位置)
|
||||
## 常见 VPN / tailnet 设置(智能体所在位置)
|
||||
|
||||
把**Gateway 网关主机**理解为“智能体所在的位置”。它持有会话、认证配置文件、渠道和状态。
|
||||
你的笔记本 / 桌面机(以及节点)会连接到这台主机。
|
||||
把 **Gateway 主机**看作“智能体所在的位置”。它持有会话、认证配置文件、渠道和状态。
|
||||
你的笔记本 / 台式机(以及节点)会连接到这台主机。
|
||||
|
||||
### 1)始终在线的 Gateway 网关 位于你的 tailnet 中(VPS 或家用服务器)
|
||||
### 1)tailnet 中始终在线的 Gateway 网关(VPS 或家用服务器)
|
||||
|
||||
在持久化主机上运行 Gateway 网关,并通过 **Tailscale** 或 SSH 访问它。
|
||||
在持久运行的主机上运行 Gateway 网关,并通过 **Tailscale** 或 SSH 访问它。
|
||||
|
||||
- **最佳体验:** 保持 `gateway.bind: "loopback"`,并对 Control UI 使用 **Tailscale Serve**。
|
||||
- **回退方案:** 保持回环绑定 + 从任何需要访问的机器建立 SSH 隧道。
|
||||
- **示例:** [exe.dev](/zh-CN/install/exe-dev)(简单 VM)或 [Hetzner](/zh-CN/install/hetzner)(生产级 VPS)。
|
||||
- **最佳体验:**保持 `gateway.bind: "loopback"`,并为控制 UI 使用 **Tailscale Serve**。
|
||||
- **兜底方案:**保持 loopback,然后从任何需要访问的机器建立 SSH 隧道。
|
||||
- **示例:**[exe.dev](/zh-CN/install/exe-dev)(简单虚拟机)或 [Hetzner](/zh-CN/install/hetzner)(生产环境 VPS)。
|
||||
|
||||
当你的笔记本经常休眠,但你希望智能体始终在线时,这种方式非常理想。
|
||||
当你的笔记本经常休眠,但你希望智能体始终在线时,这种方式最理想。
|
||||
|
||||
### 2)家里的桌面机运行 Gateway 网关,笔记本作为远程控制端
|
||||
### 2)家用台式机运行 Gateway 网关,笔记本作为远程控制端
|
||||
|
||||
笔记本**不**运行智能体。它通过远程方式连接:
|
||||
|
||||
- 使用 macOS 应用的**通过 SSH 远程访问**模式(设置 → 通用 → “OpenClaw runs”)。
|
||||
- 应用会打开并管理隧道,因此 WebChat + 健康检查“开箱即用”。
|
||||
- 使用 macOS 应用的**通过 SSH 远程连接**模式(设置 → 通用 → “OpenClaw 运行于”)。
|
||||
- 应用会打开并管理隧道,因此 WebChat 和健康检查都能“正常工作”。
|
||||
|
||||
操作手册: [macOS 远程访问](/zh-CN/platforms/mac/remote)。
|
||||
操作手册:[macOS 远程访问](/zh-CN/platforms/mac/remote)。
|
||||
|
||||
### 3)笔记本运行 Gateway 网关,其他机器远程访问
|
||||
### 3)笔记本运行 Gateway 网关,从其他机器远程访问
|
||||
|
||||
保持 Gateway 网关 在本地运行,但以安全方式暴露它:
|
||||
让 Gateway 网关保持本地运行,但以安全方式暴露出来:
|
||||
|
||||
- 从其他机器通过 SSH 隧道连接到笔记本,或
|
||||
- 使用 Tailscale Serve 暴露 Control UI,并让 Gateway 网关 保持仅回环访问。
|
||||
- 从其他机器通过 SSH 隧道连接到笔记本,或者
|
||||
- 使用 Tailscale Serve 暴露控制 UI,同时让 Gateway 网关仅绑定 loopback。
|
||||
|
||||
指南: [Tailscale](/zh-CN/gateway/tailscale) 和 [Web 概览](/zh-CN/web)。
|
||||
指南:[Tailscale](/zh-CN/gateway/tailscale) 和 [Web 概览](/zh-CN/web)。
|
||||
|
||||
## 命令流(哪些内容运行在哪里)
|
||||
## 命令流(哪些组件运行在哪里)
|
||||
|
||||
一个 Gateway 网关服务负责状态 + 渠道。节点是外围设备。
|
||||
一个 Gateway 网关服务持有状态 + 渠道。节点是外围设备。
|
||||
|
||||
流程示例(Telegram → 节点):
|
||||
|
||||
- Telegram 消息到达 **Gateway 网关**。
|
||||
- Gateway 网关 运行**智能体**并决定是否调用节点工具。
|
||||
- Gateway 网关 通过 Gateway 网关 WebSocket(`node.*` RPC)调用**节点**。
|
||||
- 节点返回结果;Gateway 网关 再将回复发回 Telegram。
|
||||
- Gateway 网关运行**智能体**,并决定是否调用某个节点工具。
|
||||
- Gateway 网关通过 Gateway 网关 WebSocket(`node.*` RPC)调用**节点**。
|
||||
- 节点返回结果;Gateway 网关再将回复发回 Telegram。
|
||||
|
||||
说明:
|
||||
|
||||
- **节点不会运行 Gateway 网关服务。** 除非你有意运行隔离配置文件,否则每台主机只应运行一个 Gateway 网关(参见 [多个 Gateway 网关](/zh-CN/gateway/multiple-gateways))。
|
||||
- macOS 应用的“节点模式”本质上只是一个通过 Gateway 网关 WebSocket 连接的节点客户端。
|
||||
- **节点不会运行 gateway 服务。**每台主机通常只应运行一个 gateway,除非你有意运行隔离的配置文件(参见 [多个 gateway](/zh-CN/gateway/multiple-gateways))。
|
||||
- macOS 应用的“节点模式”本质上只是通过 Gateway 网关 WebSocket 连接的节点客户端。
|
||||
|
||||
## SSH 隧道(CLI + 工具)
|
||||
|
||||
为远程 Gateway 网关 WS 创建本地隧道:
|
||||
创建一个指向远程 Gateway 网关 WS 的本地隧道:
|
||||
|
||||
```bash
|
||||
ssh -N -L 18789:127.0.0.1:18789 user@host
|
||||
@ -83,16 +83,16 @@ ssh -N -L 18789:127.0.0.1:18789 user@host
|
||||
|
||||
隧道建立后:
|
||||
|
||||
- `openclaw health` 和 `openclaw status --deep` 现在会通过 `ws://127.0.0.1:18789` 访问远程 Gateway 网关。
|
||||
- `openclaw health` 和 `openclaw status --deep` 现在会通过 `ws://127.0.0.1:18789` 访问远程 gateway。
|
||||
- `openclaw gateway status`、`openclaw gateway health`、`openclaw gateway probe` 和 `openclaw gateway call` 也可以在需要时通过 `--url` 指向转发后的 URL。
|
||||
|
||||
注意:请将 `18789` 替换为你配置的 `gateway.port`(或 `--port`/`OPENCLAW_GATEWAY_PORT`)。
|
||||
注意:当你传入 `--url` 时,CLI 不会回退到配置或环境凭证。
|
||||
请显式传入 `--token` 或 `--password`。缺少显式凭证会报错。
|
||||
注意:请将 `18789` 替换为你配置的 `gateway.port`(或 `--port` / `OPENCLAW_GATEWAY_PORT`)。
|
||||
注意:当你传入 `--url` 时,CLI 不会回退到配置或环境中的凭证。
|
||||
请显式提供 `--token` 或 `--password`。如果未显式提供凭证,将报错。
|
||||
|
||||
## CLI 远程默认值
|
||||
|
||||
你可以持久化一个远程目标,以便 CLI 命令默认使用它:
|
||||
你可以持久化一个远程目标,让 CLI 命令默认使用它:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -106,65 +106,66 @@ ssh -N -L 18789:127.0.0.1:18789 user@host
|
||||
}
|
||||
```
|
||||
|
||||
当 Gateway 网关 仅绑定回环地址时,请将 URL 保持为 `ws://127.0.0.1:18789`,并先建立 SSH 隧道。
|
||||
当 gateway 仅绑定 loopback 时,请将 URL 保持为 `ws://127.0.0.1:18789`,并先建立 SSH 隧道。
|
||||
|
||||
## 凭证优先级
|
||||
|
||||
Gateway 网关凭证解析在 call/probe/status 路径以及 Discord exec-approval 监控中遵循同一套共享契约。节点主机使用相同的基础契约,但有一个本地模式例外(它会有意忽略 `gateway.remote.*`):
|
||||
Gateway 网关凭证解析在 call / probe / status 路径以及 Discord exec-approval 监控中遵循同一套共享约定。节点主机使用相同的基础约定,但有一个本地模式例外(它会有意忽略 `gateway.remote.*`):
|
||||
|
||||
- 显式凭证(`--token`、`--password` 或工具 `gatewayToken`)在接受显式认证的调用路径中始终优先。
|
||||
- 显式凭证(`--token`、`--password` 或工具的 `gatewayToken`)在支持显式认证的调用路径中始终优先。
|
||||
- URL 覆盖安全规则:
|
||||
- CLI URL 覆盖(`--url`)绝不会复用隐式配置 / 环境凭证。
|
||||
- 环境 URL 覆盖(`OPENCLAW_GATEWAY_URL`)只能使用环境凭证(`OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`)。
|
||||
- 本地模式默认值:
|
||||
- token:`OPENCLAW_GATEWAY_TOKEN` -> `gateway.auth.token` -> `gateway.remote.token`(仅当本地认证 token 输入未设置时,才会应用远程回退)
|
||||
- password:`OPENCLAW_GATEWAY_PASSWORD` -> `gateway.auth.password` -> `gateway.remote.password`(仅当本地认证 password 输入未设置时,才会应用远程回退)
|
||||
- token:`OPENCLAW_GATEWAY_TOKEN` -> `gateway.auth.token` -> `gateway.remote.token`(仅当本地认证 token 输入未设置时,才应用远程回退)
|
||||
- password:`OPENCLAW_GATEWAY_PASSWORD` -> `gateway.auth.password` -> `gateway.remote.password`(仅当本地认证 password 输入未设置时,才应用远程回退)
|
||||
- 远程模式默认值:
|
||||
- token:`gateway.remote.token` -> `OPENCLAW_GATEWAY_TOKEN` -> `gateway.auth.token`
|
||||
- password:`OPENCLAW_GATEWAY_PASSWORD` -> `gateway.remote.password` -> `gateway.auth.password`
|
||||
- 节点主机本地模式例外:`gateway.remote.token` / `gateway.remote.password` 会被忽略。
|
||||
- 远程 probe/status token 检查默认是严格的:在面向远程模式时,它们仅使用 `gateway.remote.token`(不会回退到本地 token)。
|
||||
- 节点主机本地模式例外:会忽略 `gateway.remote.token` / `gateway.remote.password`。
|
||||
- 远程 probe / status token 检查默认是严格的:在目标为远程模式时,它们只使用 `gateway.remote.token`(不会回退到本地 token)。
|
||||
- Gateway 网关环境覆盖仅使用 `OPENCLAW_GATEWAY_*`。
|
||||
|
||||
## 通过 SSH 使用聊天 UI
|
||||
|
||||
WebChat 不再使用单独的 HTTP 端口。SwiftUI 聊天 UI 会直接连接到 Gateway 网关 WebSocket。
|
||||
WebChat 不再使用单独的 HTTP 端口。SwiftUI 聊天 UI 直接连接到 Gateway 网关 WebSocket。
|
||||
|
||||
- 通过 SSH 转发 `18789`(见上文),然后让客户端连接到 `ws://127.0.0.1:18789`。
|
||||
- 在 macOS 上,优先使用应用的“通过 SSH 远程访问”模式,它会自动管理隧道。
|
||||
- 在 macOS 上,优先使用应用的“通过 SSH 远程连接”模式,它会自动管理隧道。
|
||||
|
||||
## macOS 应用“通过 SSH 远程访问”
|
||||
## macOS 应用“通过 SSH 远程连接”
|
||||
|
||||
macOS 菜单栏应用可以端到端驱动同一套设置(远程状态检查、WebChat 和 Voice Wake 转发)。
|
||||
|
||||
操作手册: [macOS 远程访问](/zh-CN/platforms/mac/remote)。
|
||||
操作手册:[macOS 远程访问](/zh-CN/platforms/mac/remote)。
|
||||
|
||||
## 安全规则(远程 / VPN)
|
||||
|
||||
简短版本:**除非你确定需要绑定,否则请让 Gateway 网关 保持仅回环访问。**
|
||||
简短版本:**除非你确定需要 bind,否则请让 Gateway 网关仅绑定 loopback。**
|
||||
|
||||
- **回环 + SSH/Tailscale Serve** 是最安全的默认方式(不会公开暴露)。
|
||||
- 明文 `ws://` 默认仅限回环。对于受信任的私有网络,
|
||||
可在客户端进程上设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` 作为紧急放行手段。
|
||||
- **非回环绑定**(`lan`/`tailnet`/`custom`,或当回环不可用时的 `auto`)必须使用 Gateway 网关认证:token、password,或带有 `gateway.auth.mode: "trusted-proxy"` 的身份感知反向代理。
|
||||
- **loopback + SSH / Tailscale Serve** 是最安全的默认方案(不会公开暴露)。
|
||||
- 默认情况下,明文 `ws://` 仅限 loopback。对于受信任的私有网络,
|
||||
在客户端进程上设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` 作为紧急兜底。
|
||||
没有对应的 `openclaw.json` 配置项;这必须设置在建立 WebSocket 连接的客户端进程
|
||||
环境中。
|
||||
- **非 loopback 绑定**(`lan` / `tailnet` / `custom`,或在 loopback 不可用时使用 `auto`)必须启用 gateway 认证:token、password,或使用带有 `gateway.auth.mode: "trusted-proxy"` 的身份感知型反向代理。
|
||||
- `gateway.remote.token` / `.password` 是客户端凭证来源。它们**不会**自行配置服务器认证。
|
||||
- 仅当 `gateway.auth.*` 未设置时,本地调用路径才可将 `gateway.remote.*` 作为回退。
|
||||
- 如果 `gateway.auth.token` / `gateway.auth.password` 通过 SecretRef 显式配置但无法解析,则解析会失败关闭(不会用远程回退进行掩盖)。
|
||||
- `gateway.remote.tlsFingerprint` 会在使用 `wss://` 时固定远程 TLS 证书。
|
||||
- **Tailscale Serve** 可以在 `gateway.auth.allowTailscale: true` 时,通过身份
|
||||
标头为 Control UI/WebSocket 流量提供认证;HTTP API 端点不会
|
||||
使用该 Tailscale 标头认证,而是遵循 Gateway 网关的常规 HTTP
|
||||
认证模式。这种无 token 流程假设 Gateway 网关主机是受信任的。如果你希望所有地方都使用共享密钥认证,请将其设为
|
||||
`false`。
|
||||
- **trusted-proxy** 认证仅适用于非回环、身份感知代理的部署场景。
|
||||
同主机回环反向代理不满足 `gateway.auth.mode: "trusted-proxy"`。
|
||||
- 请将浏览器控制视为操作员访问:仅限 tailnet + 明确的节点配对。
|
||||
- 本地调用路径仅会在 `gateway.auth.*` 未设置时,将 `gateway.remote.*` 作为回退使用。
|
||||
- 如果通过 SecretRef 显式配置了 `gateway.auth.token` / `gateway.auth.password` 但未能解析,解析会以关闭方式失败(不会用远程回退来掩盖问题)。
|
||||
- 使用 `wss://` 时,`gateway.remote.tlsFingerprint` 会固定远程 TLS 证书。
|
||||
- 当 `gateway.auth.allowTailscale: true` 时,**Tailscale Serve** 可以通过身份
|
||||
标头为控制 UI / WebSocket 流量进行认证;HTTP API 端点不会使用这种 Tailscale 标头认证,
|
||||
而是遵循 gateway 的常规 HTTP 认证模式。这个无 token 流程假设 gateway 主机是受信任的。
|
||||
如果你希望所有位置都使用共享密钥认证,请将其设为 `false`。
|
||||
- **trusted-proxy** 认证仅适用于非 loopback 的身份感知型代理设置。
|
||||
同主机的 loopback 反向代理不满足 `gateway.auth.mode: "trusted-proxy"` 的要求。
|
||||
- 请将浏览器控制视为操作端访问:仅限 tailnet + 经过有意的节点配对。
|
||||
|
||||
深入说明: [安全性](/zh-CN/gateway/security)。
|
||||
深入说明:[安全性](/zh-CN/gateway/security)。
|
||||
|
||||
### macOS:通过 LaunchAgent 持久化 SSH 隧道
|
||||
|
||||
对于连接到远程 Gateway 网关的 macOS 客户端,最简单的持久化设置是使用 SSH `LocalForward` 配置项,再配合 LaunchAgent 让隧道在重启和崩溃后保持存活。
|
||||
对于连接到远程 gateway 的 macOS 客户端,最简单的持久化方案是使用 SSH `LocalForward` 配置项,再配合 LaunchAgent 在重启和崩溃后保持隧道存活。
|
||||
|
||||
#### 第 1 步:添加 SSH 配置
|
||||
|
||||
@ -178,7 +179,7 @@ Host remote-gateway
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
```
|
||||
|
||||
将 `<REMOTE_IP>` 和 `<REMOTE_USER>` 替换为你的实际值。
|
||||
请将 `<REMOTE_IP>` 和 `<REMOTE_USER>` 替换为你的实际值。
|
||||
|
||||
#### 第 2 步:复制 SSH 密钥(一次性)
|
||||
|
||||
@ -186,9 +187,9 @@ Host remote-gateway
|
||||
ssh-copy-id -i ~/.ssh/id_rsa <REMOTE_USER>@<REMOTE_IP>
|
||||
```
|
||||
|
||||
#### 第 3 步:配置 Gateway 网关 token
|
||||
#### 第 3 步:配置 gateway token
|
||||
|
||||
将 token 存入配置,以便在重启后依然保留:
|
||||
将 token 存储到配置中,以便它在重启后依然保留:
|
||||
|
||||
```bash
|
||||
openclaw config set gateway.remote.token "<your-token>"
|
||||
@ -225,9 +226,9 @@ openclaw config set gateway.remote.token "<your-token>"
|
||||
launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist
|
||||
```
|
||||
|
||||
该隧道会在登录时自动启动,在崩溃后自动重启,并保持转发端口持续可用。
|
||||
隧道会在登录时自动启动,在崩溃后自动重启,并保持转发端口处于可用状态。
|
||||
|
||||
注意:如果你还有旧设置遗留的 `com.openclaw.ssh-tunnel` LaunchAgent,请先卸载并删除它。
|
||||
注意:如果你仍然保留旧设置遗留的 `com.openclaw.ssh-tunnel` LaunchAgent,请先卸载并删除它。
|
||||
|
||||
#### 故障排除
|
||||
|
||||
@ -250,15 +251,15 @@ launchctl kickstart -k gui/$UID/ai.openclaw.ssh-tunnel
|
||||
launchctl bootout gui/$UID/ai.openclaw.ssh-tunnel
|
||||
```
|
||||
|
||||
| 配置项 | 作用 |
|
||||
| 配置项 | 作用 |
|
||||
| ------------------------------------ | ------------------------------------------------------------ |
|
||||
| `LocalForward 18789 127.0.0.1:18789` | 将本地端口 18789 转发到远程端口 18789 |
|
||||
| `ssh -N` | SSH 连接但不执行远程命令(仅用于端口转发) |
|
||||
| `KeepAlive` | 如果隧道崩溃则自动重启 |
|
||||
| `RunAtLoad` | 在登录时 LaunchAgent 加载时启动隧道 |
|
||||
| `LocalForward 18789 127.0.0.1:18789` | 将本地端口 18789 转发到远程端口 18789 |
|
||||
| `ssh -N` | SSH 连接但不执行远程命令(仅用于端口转发) |
|
||||
| `KeepAlive` | 如果隧道崩溃则自动重启 |
|
||||
| `RunAtLoad` | 在登录时 LaunchAgent 加载后启动隧道 |
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [Tailscale](/zh-CN/gateway/tailscale)
|
||||
- [认证](/zh-CN/gateway/authentication)
|
||||
- [远程 Gateway 网关设置](/zh-CN/gateway/remote-gateway-readme)
|
||||
- [Authentication](/zh-CN/gateway/authentication)
|
||||
- [Remote gateway setup](/zh-CN/gateway/remote-gateway-readme)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,132 +3,134 @@ read_when:
|
||||
- 在本地或 CI 中运行测试
|
||||
- 为模型 / 提供商缺陷添加回归测试
|
||||
- 调试 Gateway 网关 + 智能体行为
|
||||
summary: 测试工具包:单元 / e2e / 实时测试套件、Docker 运行器,以及每项测试覆盖的内容
|
||||
summary: 测试工具包:unit/e2e/live 测试套件、Docker 运行器,以及每类测试涵盖的内容
|
||||
title: 测试
|
||||
x-i18n:
|
||||
generated_at: "2026-04-24T06:14:26Z"
|
||||
generated_at: "2026-04-24T06:43:49Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b825d25da0eb504dfc19e5dcf18b50e8c3bf07e616d0be82d096f3973dbbd785
|
||||
source_hash: 6c88325e0edb49437e7faa2eaf730eb3be59054d8c4bb86e56a42bc39a29a2b1
|
||||
source_path: help/testing.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 有三个 Vitest 测试套件(单元 / 集成、e2e、实时),以及一小组 Docker 运行器。本文档是一份“我们如何测试”的指南:
|
||||
OpenClaw 有三个 Vitest 测试套件(unit/integration、e2e、live)以及一小组 Docker 运行器。本文档是一份“我们如何测试”的指南:
|
||||
|
||||
- 每个测试套件覆盖什么内容(以及它刻意 _不_ 覆盖什么)。
|
||||
- 常见工作流该运行哪些命令(本地、推送前、调试)。
|
||||
- 实时测试如何发现凭证并选择模型 / 提供商。
|
||||
- 每个测试套件涵盖什么内容(以及它刻意 _不_ 涵盖什么)。
|
||||
- 常见工作流(本地、推送前、调试)应运行哪些命令。
|
||||
- live 测试如何发现凭证并选择模型 / 提供商。
|
||||
- 如何为真实世界中的模型 / 提供商问题添加回归测试。
|
||||
|
||||
## 快速开始
|
||||
|
||||
大多数时候:
|
||||
|
||||
- 完整门禁(预期在推送前执行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test`
|
||||
- 在配置充足的机器上更快地运行本地完整测试套件:`pnpm test:max`
|
||||
- 直接使用 Vitest 监听循环:`pnpm test:watch`
|
||||
- 直接按文件定位现在也支持扩展 / 渠道路径:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`
|
||||
- 当你在迭代单个失败用例时,优先使用定向运行。
|
||||
- 完整门禁(预期在 push 前运行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test`
|
||||
- 在配置较高的机器上进行更快的本地全套件运行:`pnpm test:max`
|
||||
- 直接使用 Vitest watch 循环:`pnpm test:watch`
|
||||
- 现在直接按文件定位也会路由到 extension / channel 路径:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`
|
||||
- 当你正在迭代单个失败用例时,优先使用有针对性的运行。
|
||||
- 基于 Docker 的 QA 站点:`pnpm qa:lab:up`
|
||||
- 基于 Linux VM 的 QA 通道:`pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline`
|
||||
|
||||
当你修改了测试,或想要更多信心时:
|
||||
当你修改测试或想要更多信心时:
|
||||
|
||||
- 覆盖率门禁:`pnpm test:coverage`
|
||||
- E2E 测试套件:`pnpm test:e2e`
|
||||
|
||||
当你在调试真实提供商 / 模型时(需要真实凭证):
|
||||
当你调试真实提供商 / 模型时(需要真实凭证):
|
||||
|
||||
- 实时测试套件(模型 + Gateway 网关工具 / 图像探测):`pnpm test:live`
|
||||
- 安静地只跑一个实时测试文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts`
|
||||
- Docker 实时模型扫描:`pnpm test:docker:live-models`
|
||||
- 现在每个选中的模型都会运行一次文本轮次外加一个小型“文件读取风格”探测。元数据声明支持 `image` 输入的模型还会运行一个很小的图像轮次。隔离提供商故障时,可用 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 禁用额外探测。
|
||||
- CI 覆盖:每日的 `OpenClaw Scheduled Live And E2E Checks` 和手动触发的 `OpenClaw Release Checks` 都会调用可复用的实时 / E2E 工作流,并设置 `include_live_suites: true`,其中包含按提供商分片的独立 Docker 实时模型矩阵作业。
|
||||
- 若要有针对性地重跑 CI,可触发 `OpenClaw Live And E2E Checks (Reusable)`,并设置 `include_live_suites: true` 与 `live_models_only: true`。
|
||||
- 添加新的高信号提供商密钥时,同时更新 `scripts/ci-hydrate-live-auth.sh`、`.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 以及其计划 / 发布调用方。
|
||||
- live 测试套件(模型 + Gateway 网关工具 / 图像探测):`pnpm test:live`
|
||||
- 安静地只运行一个 live 文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts`
|
||||
- Docker live 模型扫描:`pnpm test:docker:live-models`
|
||||
- 现在每个选定模型都会运行一次文本轮次加上一个小型的类文件读取探测。元数据声明支持 `image` 输入的模型还会运行一个微型图像轮次。在隔离提供商故障时,可通过 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 禁用这些额外探测。
|
||||
- CI 覆盖:每日的 `OpenClaw Scheduled Live And E2E Checks` 和手动的 `OpenClaw Release Checks` 都会调用可复用的 live / E2E 工作流,并设置 `include_live_suites: true`,其中包括按 provider 分片的独立 Docker live 模型矩阵作业。
|
||||
- 若要聚焦 CI 重跑,可触发 `OpenClaw Live And E2E Checks (Reusable)`,并设置 `include_live_suites: true` 和 `live_models_only: true`。
|
||||
- 将新的高信号 provider 密钥添加到 `scripts/ci-hydrate-live-auth.sh`、`.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 以及其 scheduled / release 调用方中。
|
||||
- 原生 Codex 绑定聊天冒烟测试:`pnpm test:docker:live-codex-bind`
|
||||
- 在 Docker 中针对 Codex app-server 路径运行一个实时测试通道,使用 `/codex bind` 绑定一个合成 Slack 私信,会执行 `/codex fast` 和 `/codex permissions`,然后验证普通回复和图像附件都通过原生插件绑定而不是 ACP 路由。
|
||||
- Moonshot / Kimi 成本冒烟测试:设置 `MOONSHOT_API_KEY` 后,运行 `openclaw models list --provider moonshot --json`,然后针对 `moonshot/kimi-k2.6` 运行一个隔离的 `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json`。验证 JSON 报告的是 Moonshot / K2.6,并且助手转录中存储了规范化的 `usage.cost`。
|
||||
- 针对 Codex app-server 路径运行一个 Docker live 通道,使用 `/codex bind` 绑定一个合成 Slack 私信,执行 `/codex fast` 和 `/codex permissions`,然后验证普通回复和图像附件都通过原生插件绑定而不是 ACP 路由。
|
||||
- Moonshot / Kimi 成本冒烟测试:设置 `MOONSHOT_API_KEY` 后,运行 `openclaw models list --provider moonshot --json`,然后针对 `moonshot/kimi-k2.6` 运行一个隔离的 `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json`。验证 JSON 报告的是 Moonshot / K2.6,且 assistant transcript 存储了规范化的 `usage.cost`。
|
||||
|
||||
提示:如果你只需要一个失败用例,优先通过下文介绍的 allowlist 环境变量来缩小实时测试范围。
|
||||
提示:如果你只需要一个失败用例,优先使用下文描述的 allowlist 环境变量来收窄 live 测试范围。
|
||||
|
||||
## QA 专用运行器
|
||||
|
||||
当你需要 QA-lab 级真实环境时,这些命令与主测试套件并列存在:
|
||||
当你需要 QA-lab 级别的真实感时,这些命令与主测试套件配套使用:
|
||||
|
||||
CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,也可通过手动触发结合模拟提供商运行。`QA-Lab - All Lanes` 会在 `main` 上每夜运行,也可通过手动触发,以模拟 parity gate、实时 Matrix 通道以及由 Convex 管理的实时 Telegram 通道作为并行作业运行。`OpenClaw Release Checks` 会在发布批准前运行相同通道。
|
||||
CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,也可通过手动触发配合 mock 提供商运行。`QA-Lab - All Lanes` 会在 `main` 上每晚运行,也可手动触发;它会将 mock parity gate、live Matrix 通道以及由 Convex 管理的 live Telegram 通道作为并行作业运行。`OpenClaw Release Checks` 会在发布审批前运行相同的通道。
|
||||
|
||||
- `pnpm openclaw qa suite`
|
||||
- 直接在主机上运行基于仓库的 QA 场景。
|
||||
- 默认使用隔离的 Gateway 网关工作进程并行运行多个选定场景。`qa-channel` 默认并发数为 4(受所选场景数量限制)。使用 `--concurrency <count>` 调整工作进程数,或使用 `--concurrency 1` 回退到旧的串行通道。
|
||||
- 任一场景失败时以非零状态退出。若你想获取制品而不让退出码失败,可使用 `--allow-failures`。
|
||||
- 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。`aimock` 会启动一个本地的 AIMock 支持提供商服务器,用于实验性的夹具和协议模拟覆盖,但不会替代具备场景感知能力的 `mock-openai` 通道。
|
||||
- 默认会使用隔离的 Gateway 网关 worker 并行运行多个选定场景。`qa-channel` 默认并发数为 4(受所选场景数量限制)。使用 `--concurrency <count>` 调整 worker 数量,或使用 `--concurrency 1` 回到旧的串行通道。
|
||||
- 任一场景失败时以非零状态退出。若你想保留工件但不希望退出码失败,可使用 `--allow-failures`。
|
||||
- 支持 provider 模式 `live-frontier`、`mock-openai` 和 `aimock`。`aimock` 会启动一个本地的 AIMock 支持的 provider 服务器,用于实验性 fixture 和协议 mock 覆盖,而不会替代面向场景的 `mock-openai` 通道。
|
||||
- `pnpm openclaw qa suite --runner multipass`
|
||||
- 在一次性的 Multipass Linux VM 中运行相同的 QA 套件。
|
||||
- 保持与主机上的 `qa suite` 相同的场景选择行为。
|
||||
- 复用与 `qa suite` 相同的提供商 / 模型选择标志。
|
||||
- 实时运行会转发对访客环境而言实用的受支持 QA 认证输入:基于环境变量的提供商密钥、QA 实时提供商配置路径,以及存在时的 `CODEX_HOME`。
|
||||
- 输出目录必须位于仓库根目录下,以便访客环境可以通过挂载的工作区回写。
|
||||
- 在一次性 Multipass Linux VM 中运行同样的 QA 套件。
|
||||
- 保持与主机上 `qa suite` 相同的场景选择行为。
|
||||
- 复用与 `qa suite` 相同的 provider / model 选择标志。
|
||||
- live 运行会转发对 guest 来说实际可用的 QA 认证输入:基于环境变量的 provider 密钥、QA live provider 配置路径,以及存在时的 `CODEX_HOME`。
|
||||
- 输出目录必须保留在仓库根目录下,以便 guest 能通过挂载的工作区回写。
|
||||
- 在 `.artifacts/qa-e2e/...` 下写入常规 QA 报告 + 摘要,以及 Multipass 日志。
|
||||
- `pnpm qa:lab:up`
|
||||
- 启动基于 Docker 的 QA 站点,用于偏操作员风格的 QA 工作。
|
||||
- 启动基于 Docker 的 QA 站点,供操作员风格的 QA 工作使用。
|
||||
- `pnpm test:docker:npm-onboard-channel-agent`
|
||||
- 从当前检出构建 npm tarball,在 Docker 中全局安装,运行非交互式 OpenAI API 密钥新手引导,默认配置 Telegram,验证启用插件时会按需安装运行时依赖,运行 doctor,并针对一个模拟 OpenAI 端点运行一次本地智能体轮次。
|
||||
- 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可让同一个打包安装通道改用 Discord。
|
||||
- 从当前 checkout 构建一个 npm tarball,在 Docker 中全局安装,以非交互方式运行 OpenAI API key onboarding,默认配置 Telegram,验证启用插件时会按需安装运行时依赖,运行 doctor,并针对一个模拟的 OpenAI 端点执行一次本地 agent 轮次。
|
||||
- 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可用 Discord 运行同样的打包安装通道。
|
||||
- `pnpm test:docker:npm-telegram-live`
|
||||
- 在 Docker 中安装一个已发布的 OpenClaw 包,运行已安装包的新手引导,通过已安装的 CLI 配置 Telegram,然后复用实时 Telegram QA 通道,并将该已安装包作为被测 Gateway 网关。
|
||||
- 默认为 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`。
|
||||
- 使用与 `pnpm openclaw qa telegram` 相同的 Telegram 环境变量凭证或 Convex 凭证来源。
|
||||
- 在 Docker 中安装已发布的 OpenClaw 包,运行已安装包的新手引导,通过已安装的 CLI 配置 Telegram,然后复用 live Telegram QA 通道,并将该已安装包作为 SUT Gateway 网关。
|
||||
- 默认使用 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`。
|
||||
- 使用与 `pnpm openclaw qa telegram` 相同的 Telegram 环境变量凭证或 Convex 凭证来源。对于 CI / 发布自动化,请设置 `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex`,以及 `OPENCLAW_QA_CONVEX_SITE_URL` 和角色密钥。如果在 CI 中存在 `OPENCLAW_QA_CONVEX_SITE_URL` 和 Convex 角色密钥,Docker 包装器会自动选择 Convex。
|
||||
- `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` 会仅对该通道覆盖共享的 `OPENCLAW_QA_CREDENTIAL_ROLE`。
|
||||
- GitHub Actions 将此通道公开为手动维护者工作流 `NPM Telegram Beta E2E`。它不会在合并时运行。该工作流使用 `qa-live-shared` environment 和 Convex CI 凭证租约。
|
||||
- `pnpm test:docker:bundled-channel-deps`
|
||||
- 在 Docker 中打包并安装当前 OpenClaw 构建,启动一个已配置 OpenAI 的 Gateway 网关,然后通过修改配置启用内置渠道 / 插件。
|
||||
- 验证设置发现阶段不会提前安装未配置插件的运行时依赖,第一次配置好的 Gateway 网关或 doctor 运行时会按需安装每个内置插件的运行时依赖,而第二次重启不会重新安装已激活的依赖。
|
||||
- 还会安装一个已知较旧的 npm 基线版本,在运行 `openclaw update --tag <candidate>` 之前启用 Telegram,并验证候选版本更新后的 doctor 会修复内置渠道运行时依赖,而无需测试框架侧的 postinstall 修复。
|
||||
- 在 Docker 中打包并安装当前 OpenClaw 构建,使用已配置的 OpenAI 启动 Gateway 网关,然后通过编辑配置启用内置 channel / plugins。
|
||||
- 验证设置发现过程会让未配置插件的运行时依赖保持未安装状态,第一次配置后的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖,而第二次重启不会重新安装已激活的依赖。
|
||||
- 还会安装一个已知的旧版 npm 基线,在运行 `openclaw update --tag <candidate>` 之前启用 Telegram,并验证候选版本在更新后的 doctor 中会修复内置 channel 运行时依赖,而不需要 harness 侧的 postinstall 修复。
|
||||
- `pnpm openclaw qa aimock`
|
||||
- 仅启动本地 AIMock 支持提供商服务器,用于直接的协议冒烟测试。
|
||||
- 仅启动本地 AIMock provider 服务器,用于直接协议冒烟测试。
|
||||
- `pnpm openclaw qa matrix`
|
||||
- 针对一个基于 Docker 的一次性 Tuwunel homeserver 运行 Matrix 实时 QA 通道。
|
||||
- 这个 QA 主机当前仅供仓库 / 开发使用。打包后的 OpenClaw 安装不包含 `qa-lab`,因此不会暴露 `openclaw qa`。
|
||||
- 仓库检出会直接加载内置运行器;不需要单独安装插件。
|
||||
- 配置三个临时 Matrix 用户(`driver`、`sut`、`observer`)和一个私有房间,然后启动一个使用真实 Matrix 插件作为 SUT 传输层的 QA Gateway 网关子进程。
|
||||
- 默认使用固定稳定版 Tuwunel 镜像 `ghcr.io/matrix-construct/tuwunel:v1.5.1`。如需测试其他镜像,可通过 `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` 覆盖。
|
||||
- Matrix 不暴露共享凭证来源标志,因为该通道会在本地配置一次性用户。
|
||||
- 在 `.artifacts/qa-e2e/...` 下写入 Matrix QA 报告、摘要、observed-events 制品,以及合并的 stdout / stderr 输出日志。
|
||||
- 针对一个一次性的基于 Docker 的 Tuwunel homeserver 运行 Matrix live QA 通道。
|
||||
- 这个 QA 主机目前仅供仓库 / 开发环境使用。打包后的 OpenClaw 安装不会附带 `qa-lab`,因此不会暴露 `openclaw qa`。
|
||||
- 仓库 checkout 会直接加载内置运行器;无需单独安装插件。
|
||||
- 会预配三个临时 Matrix 用户(`driver`、`sut`、`observer`)以及一个私有房间,然后启动一个 QA gateway 子进程,并使用真实的 Matrix 插件作为 SUT 传输层。
|
||||
- 默认使用固定的稳定版 Tuwunel 镜像 `ghcr.io/matrix-construct/tuwunel:v1.5.1`。如果你需要测试不同镜像,可通过 `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` 覆盖。
|
||||
- Matrix 不暴露共享的 credential-source 标志,因为该通道会在本地预配一次性用户。
|
||||
- 会在 `.artifacts/qa-e2e/...` 下写入 Matrix QA 报告、摘要、observed-events 工件,以及合并的 stdout / stderr 输出日志。
|
||||
- `pnpm openclaw qa telegram`
|
||||
- 使用环境变量中的 driver 和 SUT bot token,针对一个真实私有群组运行 Telegram 实时 QA 通道。
|
||||
- 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。群组 id 必须是 Telegram 聊天的数字 id。
|
||||
- 支持 `--credential-source convex` 以使用共享池化凭证。默认使用环境变量模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以启用池化租约。
|
||||
- 任一场景失败时以非零状态退出。若你想获取制品而不让退出码失败,可使用 `--allow-failures`。
|
||||
- 需要同一个私有群组中的两个不同 bot,并且 SUT bot 必须公开 Telegram 用户名。
|
||||
- 为了稳定地观察 bot 之间的通信,请在 `@BotFather` 中为两个 bot 都启用 Bot-to-Bot Communication Mode,并确保 driver bot 可以观察群组中的 bot 流量。
|
||||
- 在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 制品。回复场景包含从 driver 发送请求到观察到 SUT 回复的 RTT。
|
||||
- 使用来自环境变量的 driver 和 SUT bot token,针对真实私有群组运行 Telegram live QA 通道。
|
||||
- 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。group id 必须是 Telegram chat 的数字 id。
|
||||
- 支持 `--credential-source convex` 以使用共享池化凭证。默认使用 env 模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以启用池化租约。
|
||||
- 任一场景失败时以非零状态退出。若你想保留工件但不希望退出码失败,可使用 `--allow-failures`。
|
||||
- 需要同一私有群组中的两个不同 bot,并且 SUT bot 需要公开 Telegram 用户名。
|
||||
- 为了实现稳定的 bot 对 bot 观测,请在 `@BotFather` 中为两个 bot 启用 Bot-to-Bot Communication Mode,并确保 driver bot 能观测群组中的 bot 流量。
|
||||
- 会在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 工件。replying 场景会包含从 driver 发送请求到观测到 SUT 回复的 RTT。
|
||||
|
||||
实时传输通道共享一套标准契约,以避免新传输层发生漂移:
|
||||
live 传输通道共享一个标准契约,以避免新传输出现漂移:
|
||||
|
||||
`qa-channel` 仍然是覆盖面广的合成 QA 套件,不属于实时传输覆盖矩阵的一部分。
|
||||
`qa-channel` 仍然是广义的合成 QA 套件,不属于 live 传输覆盖矩阵的一部分。
|
||||
|
||||
| 通道 | Canary | 提及门控 | allowlist 阻止 | 顶层回复 | 重启恢复 | 线程跟进 | 线程隔离 | 反应观测 | 帮助命令 |
|
||||
| -------- | ------ | -------------- | --------------- | --------------- | -------------- | ---------------- | ---------------- | -------------------- | ------------ |
|
||||
| Matrix | x | x | x | x | x | x | x | x | |
|
||||
| Telegram | x | | | | | | | | x |
|
||||
| 通道 | Canary | Mention gating | Allowlist block | 顶层回复 | 重启恢复 | 线程跟进 | 线程隔离 | 反应观测 | 帮助命令 |
|
||||
| ---- | ------ | -------------- | --------------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
| Matrix | x | x | x | x | x | x | x | x | |
|
||||
| Telegram | x | | | | | | | | x |
|
||||
|
||||
### 通过 Convex 共享 Telegram 凭证(v1)
|
||||
|
||||
当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从一个由 Convex 支持的池中获取独占租约,在通道运行期间为该租约发送心跳,并在关闭时释放租约。
|
||||
当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从一个由 Convex 支持的池中获取独占租约,在通道运行期间对该租约发送 heartbeat,并在关闭时释放该租约。
|
||||
|
||||
参考 Convex 项目脚手架:
|
||||
参考的 Convex 项目脚手架:
|
||||
|
||||
- `qa/convex-credential-broker/`
|
||||
|
||||
必需环境变量:
|
||||
|
||||
- `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`)
|
||||
- 针对所选角色的一个密钥:
|
||||
- 为所选角色提供一个密钥:
|
||||
- `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`,用于 `maintainer`
|
||||
- `OPENCLAW_QA_CONVEX_SECRET_CI`,用于 `ci`
|
||||
- 凭证角色选择:
|
||||
- CLI:`--credential-role maintainer|ci`
|
||||
- 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认是 `ci`,否则为 `maintainer`)
|
||||
- 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认为 `ci`,否则默认为 `maintainer`)
|
||||
|
||||
可选环境变量:
|
||||
|
||||
@ -137,12 +139,12 @@ CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上
|
||||
- `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS`(默认 `90000`)
|
||||
- `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS`(默认 `15000`)
|
||||
- `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX`(默认 `/qa-credentials/v1`)
|
||||
- `OPENCLAW_QA_CREDENTIAL_OWNER_ID`(可选跟踪 id)
|
||||
- `OPENCLAW_QA_CREDENTIAL_OWNER_ID`(可选的追踪 id)
|
||||
- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许在仅限本地开发时使用 loopback `http://` Convex URL。
|
||||
|
||||
正常运行时,`OPENCLAW_QA_CONVEX_SITE_URL` 应使用 `https://`。
|
||||
|
||||
维护者管理命令(池添加 / 删除 / 列表)需要明确使用 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。
|
||||
维护者管理命令(池添加 / 删除 / 列表)需要专门使用 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。
|
||||
|
||||
供维护者使用的 CLI 辅助命令:
|
||||
|
||||
@ -152,14 +154,14 @@ pnpm openclaw qa credentials list --kind telegram
|
||||
pnpm openclaw qa credentials remove --credential-id <credential-id>
|
||||
```
|
||||
|
||||
在脚本和 CI 工具中使用 `--json` 可获得机器可读输出。
|
||||
在脚本和 CI 工具中使用 `--json` 以获得机器可读的输出。
|
||||
|
||||
默认端点契约(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`):
|
||||
|
||||
- `POST /acquire`
|
||||
- 请求:`{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }`
|
||||
- 成功:`{ status: "ok", credentialId, leaseToken, payload, leaseTtlMs?, heartbeatIntervalMs? }`
|
||||
- 资源耗尽 / 可重试:`{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }`
|
||||
- 耗尽 / 可重试:`{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }`
|
||||
- `POST /heartbeat`
|
||||
- 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs }`
|
||||
- 成功:`{ status: "ok" }`(或空的 `2xx`)
|
||||
@ -180,58 +182,59 @@ pnpm openclaw qa credentials remove --credential-id <credential-id>
|
||||
Telegram 类型的 payload 结构:
|
||||
|
||||
- `{ groupId: string, driverToken: string, sutToken: string }`
|
||||
- `groupId` 必须是 Telegram 聊天的数字 id 字符串。
|
||||
- `admin/add` 会对 `kind: "telegram"` 的此结构进行校验,并拒绝格式错误的 payload。
|
||||
- `groupId` 必须是 Telegram chat id 的数字字符串。
|
||||
- `admin/add` 会对 `kind: "telegram"` 验证此结构,并拒绝格式错误的 payload。
|
||||
|
||||
### 向 QA 添加一个渠道
|
||||
|
||||
将一个渠道添加到 Markdown QA 系统中,严格只需要两样东西:
|
||||
向 Markdown QA 系统添加一个渠道,严格来说只需要两样东西:
|
||||
|
||||
1. 该渠道的传输适配器。
|
||||
2. 一个用于验证渠道契约的场景包。
|
||||
2. 一个用于验证该渠道契约的场景包。
|
||||
|
||||
如果共享的 `qa-lab` 主机可以承载该流程,就不要新增顶层 QA 命令根。
|
||||
如果共享的 `qa-lab` 主机能够承载整个流程,就不要新增一个顶层 QA 命令根。
|
||||
|
||||
`qa-lab` 负责共享主机机制:
|
||||
|
||||
- `openclaw qa` 命令根
|
||||
- 套件启动与拆卸
|
||||
- 套件启动与拆除
|
||||
- worker 并发
|
||||
- 制品写入
|
||||
- 工件写入
|
||||
- 报告生成
|
||||
- 场景执行
|
||||
- 对旧 `qa-channel` 场景的兼容别名
|
||||
- 对旧版 `qa-channel` 场景的兼容别名
|
||||
|
||||
运行器插件负责传输契约:
|
||||
|
||||
- `openclaw qa <runner>` 如何挂载到共享 `qa` 根下
|
||||
- `openclaw qa <runner>` 如何挂载到共享 `qa` 根命令之下
|
||||
- 如何为该传输配置 Gateway 网关
|
||||
- 如何检查就绪状态
|
||||
- 如何注入入站事件
|
||||
- 如何观测出站消息
|
||||
- 如何暴露转录和规范化的传输状态
|
||||
- 如何执行基于传输的操作
|
||||
- 如何处理传输专属的重置或清理
|
||||
- 如何暴露 transcript 和规范化后的传输状态
|
||||
- 如何执行由传输支持的动作
|
||||
- 如何处理传输特定的重置或清理
|
||||
|
||||
新渠道的最低采纳门槛是:
|
||||
新渠道的最低接入门槛是:
|
||||
|
||||
1. 保持 `qa-lab` 作为共享 `qa` 根的拥有者。
|
||||
2. 在共享的 `qa-lab` 主机接缝上实现传输运行器。
|
||||
3. 将传输专属机制保留在运行器插件或渠道测试支架内部。
|
||||
4. 将运行器挂载为 `openclaw qa <runner>`,而不是注册一个竞争性的根命令。运行器插件应在 `openclaw.plugin.json` 中声明 `qaRunners`,并从 `runtime-api.ts` 导出匹配的 `qaRunnerCliRegistrations` 数组。
|
||||
保持 `runtime-api.ts` 足够轻量;惰性 CLI 和运行器执行应放在单独的入口点之后。
|
||||
5. 在按主题组织的 `qa/scenarios/` 目录下编写或调整 Markdown 场景。
|
||||
3. 将传输特定机制保留在运行器插件或渠道 harness 内部。
|
||||
4. 将运行器挂载为 `openclaw qa <runner>`,而不是注册一个相互竞争的根命令。
|
||||
运行器插件应在 `openclaw.plugin.json` 中声明 `qaRunners`,并从 `runtime-api.ts` 导出匹配的 `qaRunnerCliRegistrations` 数组。
|
||||
保持 `runtime-api.ts` 轻量;惰性 CLI 和运行器执行应保留在独立入口点之后。
|
||||
5. 在按主题组织的 `qa/scenarios/` 目录下编写或改造 Markdown 场景。
|
||||
6. 为新场景使用通用场景辅助函数。
|
||||
7. 除非仓库正在进行有意的迁移,否则保持现有兼容别名继续可用。
|
||||
|
||||
决策规则是严格的:
|
||||
决策规则很严格:
|
||||
|
||||
- 如果某个行为可以在 `qa-lab` 中统一表达一次,就把它放进 `qa-lab`。
|
||||
- 如果某个行为依赖某一个渠道传输,就把它保留在该运行器插件或插件测试支架中。
|
||||
- 如果某个场景需要一个多个渠道都能使用的新能力,应添加通用辅助函数,而不是在 `suite.ts` 中添加渠道专属分支。
|
||||
- 如果某个行为只对一种传输有意义,就保持该场景为传输专属,并在场景契约中明确说明。
|
||||
- 如果某个行为依赖单一渠道传输,就将其保留在该运行器插件或插件 harness 中。
|
||||
- 如果某个场景需要一个可被多个渠道使用的新能力,请添加通用辅助函数,而不是在 `suite.ts` 中添加渠道特定分支。
|
||||
- 如果某个行为只对一种传输有意义,就让该场景保持传输特定,并在场景契约中明确说明。
|
||||
|
||||
新场景推荐使用的通用辅助函数名称是:
|
||||
新场景推荐使用的通用辅助函数名称:
|
||||
|
||||
- `waitForTransportReady`
|
||||
- `waitForChannelReady`
|
||||
@ -254,18 +257,18 @@ Telegram 类型的 payload 结构:
|
||||
- `formatConversationTranscript`
|
||||
- `resetBus`
|
||||
|
||||
新的渠道工作应使用通用辅助函数名称。
|
||||
兼容别名的存在是为了避免一次性迁移,不应作为新场景编写的范式。
|
||||
新的渠道工作应使用通用辅助函数名称。
|
||||
兼容别名的存在是为了避免一次性迁移日,而不是作为新场景编写的范式。
|
||||
|
||||
## 测试套件(各自运行位置)
|
||||
## 测试套件(哪些内容在哪里运行)
|
||||
|
||||
可以把这些套件理解为“真实度逐步增加”(同时不稳定性 / 成本也逐步增加):
|
||||
可以将这些套件理解为“真实性逐步提升”(同时不稳定性 / 成本也逐步上升):
|
||||
|
||||
### 单元 / 集成(默认)
|
||||
### Unit / integration(默认)
|
||||
|
||||
- 命令:`pnpm test`
|
||||
- 配置:未定向运行使用 `vitest.full-*.config.ts` 分片集合,并且可能会将多项目分片展开为按项目划分的配置,以便并行调度
|
||||
- 文件:核心 / 单元清单位于 `src/**/*.test.ts`、`packages/**/*.test.ts`、`test/**/*.test.ts`,以及由 `vitest.unit.config.ts` 覆盖的白名单 `ui` node 测试
|
||||
- 文件:`src/**/*.test.ts`、`packages/**/*.test.ts`、`test/**/*.test.ts` 下的 core / unit 清单,以及 `vitest.unit.config.ts` 覆盖的白名单 `ui` node 测试
|
||||
- 范围:
|
||||
- 纯单元测试
|
||||
- 进程内集成测试(Gateway 网关认证、路由、工具、解析、配置)
|
||||
@ -275,285 +278,289 @@ Telegram 类型的 payload 结构:
|
||||
- 不需要真实密钥
|
||||
- 应该快速且稳定
|
||||
<AccordionGroup>
|
||||
<Accordion title="项目、分片与定向通道"> - 未定向的 `pnpm test` 运行的是十二个较小的分片配置(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是一个巨大的原生根项目进程。这样可以降低高负载机器上的 RSS 峰值,并避免 auto-reply / 扩展工作拖累无关套件。 - `pnpm test --watch` 仍然使用原生根 `vitest.config.ts` 项目图,因为多分片 watch 循环并不现实。 - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 会优先通过定向通道路由显式文件 / 目录目标,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 无需承担完整根项目启动成本。 - 当变更仅触及可路由的源文件 / 测试文件时,`pnpm test:changed` 会将 git 变更路径展开到相同的定向通道;配置 / 设置修改仍会回退到更广泛的根项目重跑。 - `pnpm check:changed` 是窄范围工作常规使用的智能本地门禁。它会将 diff 分类为核心、核心测试、扩展、扩展测试、应用、文档、发布元数据和工具,然后运行匹配的 typecheck / lint / 测试通道。公共插件 SDK 和插件契约变更会额外包含一次扩展验证,因为扩展依赖这些核心契约。仅发布元数据版本号变更会运行定向的版本 / 配置 / 根依赖检查,而不是完整套件,同时有一个保护措施会拒绝顶层版本字段之外的 `package` 变更。 - 来自智能体、命令、插件、auto-reply 辅助函数、`plugin-sdk` 以及类似纯工具区域的轻导入单元测试会路由到 `unit-fast` 通道,该通道会跳过 `test/setup-openclaw-runtime.ts`;有状态 / 运行时较重的文件仍保留在现有通道中。 - 某些选定的 `plugin-sdk` 和 `commands` 辅助源文件在 changed 模式下也会映射到这些轻量通道中的显式同级测试,因此辅助函数改动无需让该目录重跑完整的重型套件。 - `auto-reply` 有三个专用分桶:顶层核心辅助函数、顶层 `reply.*` 集成测试,以及 `src/auto-reply/reply/**` 子树。这让最重的 reply 测试支架工作不会压到廉价的状态 / 分块 / token 测试上。
|
||||
<Accordion title="项目、分片和作用域通道"> - 未定向的 `pnpm test` 会运行十二个更小的分片配置(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是运行一个庞大的原生根项目进程。这样可以降低高负载机器上的峰值 RSS,并避免 auto-reply / extension 工作拖慢无关套件。 - `pnpm test --watch` 仍然使用原生根 `vitest.config.ts` 项目图,因为多分片 watch 循环并不实际。 - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 会优先通过作用域通道路由显式文件 / 目录目标,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 可以避免承担完整根项目启动开销。 - 当变更只涉及可路由的源文件 / 测试文件时,`pnpm test:changed` 会将变更的 git 路径展开到同样的作用域通道;而配置 / setup 编辑仍会回退到广泛的根项目重跑。 - `pnpm check:changed` 是窄范围工作时常规的智能本地门禁。它会将 diff 分类为 core、core tests、extensions、extension tests、apps、docs、发布元数据和工具,然后运行匹配的 typecheck / lint / test 通道。公共插件 SDK 和插件契约变更会额外包含一次 extension 验证,因为 extensions 依赖这些 core 契约。仅包含发布元数据的版本升级会运行定向的版本 / 配置 / 根依赖检查,而不是完整套件,并带有一个保护机制:若包变更超出顶层版本字段,则会被拒绝。 - 来自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 以及类似纯工具区域的轻导入 unit 测试,会通过 `unit-fast` 通道路由,该通道会跳过 `test/setup-openclaw-runtime.ts`;而有状态 / 运行时较重的文件仍保留在现有通道上。 - 某些 `plugin-sdk` 和 `commands` helper 源文件在 changed-mode 运行中也会映射到轻量通道中的显式同级测试,因此 helper 编辑无需为该目录重跑完整的重型套件。 - `auto-reply` 有三个专用桶:顶层 core helpers、顶层 `reply.*` 集成测试,以及 `src/auto-reply/reply/**` 子树。这样可以让最重的 reply harness 工作脱离廉价的状态 / 分块 / token 测试。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="嵌入式运行器覆盖">
|
||||
- 当你修改消息工具发现输入或压缩运行时上下文时,请同时保持两个层级的覆盖。
|
||||
- 为纯路由和规范化边界添加聚焦的辅助函数回归测试。
|
||||
- 保持嵌入式运行器集成测试套件健康:
|
||||
`src/agents/pi-embedded-runner/compact.hooks.test.ts`、
|
||||
`src/agents/pi-embedded-runner/run.overflow-compaction.test.ts` 和
|
||||
- 当你修改消息工具发现输入或压缩运行时上下文时,请同时保持两层覆盖。
|
||||
- 为纯路由和规范化边界添加聚焦的 helper 回归测试。
|
||||
- 保持嵌入式运行器集成套件健康:
|
||||
`src/agents/pi-embedded-runner/compact.hooks.test.ts`,
|
||||
`src/agents/pi-embedded-runner/run.overflow-compaction.test.ts`,以及
|
||||
`src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`。
|
||||
- 这些套件会验证作用域 id 和压缩行为仍然流经真实的 `run.ts` / `compact.ts` 路径;仅有辅助函数测试并不能充分替代这些集成路径。
|
||||
- 这些套件会验证作用域 id 和压缩行为仍通过真实的 `run.ts` / `compact.ts` 路径流转;仅有 helper 测试不足以替代这些集成路径。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vitest 池与隔离默认值">
|
||||
<Accordion title="Vitest 池和隔离默认值">
|
||||
- 基础 Vitest 配置默认使用 `threads`。
|
||||
- 共享 Vitest 配置固定 `isolate: false`,并在根项目、e2e 和实时配置中使用非隔离运行器。
|
||||
- 根 UI 通道保留其 `jsdom` 设置和优化器,但同样运行在共享的非隔离运行器上。
|
||||
- 共享的 Vitest 配置固定使用 `isolate: false`,并在根项目、e2e 和 live 配置中使用非隔离运行器。
|
||||
- 根 UI 通道保留其 `jsdom` setup 和优化器,但同样运行在共享的非隔离运行器上。
|
||||
- 每个 `pnpm test` 分片都从共享 Vitest 配置继承相同的 `threads` + `isolate: false` 默认值。
|
||||
- `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行中的 V8 编译抖动。设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可以与原生 V8 行为进行对比。
|
||||
- `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可与原生 V8 行为进行对比。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="快速本地迭代">
|
||||
- `pnpm changed:lanes` 会显示一个 diff 会触发哪些架构通道。
|
||||
- pre-commit hook 仅做格式化。它会重新暂存格式化后的文件,但不会运行 lint、typecheck 或测试。
|
||||
- 当你需要智能本地门禁时,请在交接或推送前显式运行 `pnpm check:changed`。公共插件 SDK 和插件契约变更会额外包含一次扩展验证。
|
||||
- `pnpm test:changed` 会在变更路径可以清晰映射到较小套件时通过定向通道执行。
|
||||
- `pnpm changed:lanes` 会显示某个 diff 会触发哪些架构通道。
|
||||
- pre-commit hook 仅负责格式化。它会重新暂存格式化后的文件,不会运行 lint、typecheck 或测试。
|
||||
- 当你需要智能本地门禁时,请在交接或 push 前显式运行 `pnpm check:changed`。公共插件 SDK 和插件契约变更会包含一次 extension 验证。
|
||||
- 当变更路径能清晰映射到更小套件时,`pnpm test:changed` 会通过作用域通道路由。
|
||||
- `pnpm test:max` 和 `pnpm test:changed:max` 保持相同的路由行为,只是使用更高的 worker 上限。
|
||||
- 本地 worker 自动扩缩容刻意较为保守,当主机负载平均值已经较高时会主动回退,因此默认情况下多个并发 Vitest 运行造成的影响更小。
|
||||
- 基础 Vitest 配置会将项目 / 配置文件标记为 `forceRerunTriggers`,从而在测试接线变更时仍能保证 changed 模式重跑的正确性。
|
||||
- 配置会在受支持主机上保持启用 `OPENCLAW_VITEST_FS_MODULE_CACHE`;如果你想为直接分析指定一个明确的缓存位置,可设置 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。
|
||||
- 本地 worker 自动扩缩容有意保持保守;当主机负载平均值已经很高时,会自动降速,因此默认情况下多个并发 Vitest 运行造成的影响更小。
|
||||
- 基础 Vitest 配置会将项目 / 配置文件标记为 `forceRerunTriggers`,以便测试接线变化时 changed-mode 重跑仍然正确。
|
||||
- 在受支持主机上,配置会保持启用 `OPENCLAW_VITEST_FS_MODULE_CACHE`;如果你想为直接性能分析指定一个明确的缓存位置,请设置 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="性能调试">
|
||||
- `pnpm test:perf:imports` 会启用 Vitest 导入耗时报告以及导入明细输出。
|
||||
- `pnpm test:perf:imports:changed` 会将同样的分析视图限定到自 `origin/main` 以来变更的文件。
|
||||
- 如果某个热点测试仍然把大部分时间花在启动导入上,请把重依赖放在一个窄范围的本地 `*.runtime.ts` 接缝之后,并直接 mock 该接缝,而不要仅仅为了通过 `vi.mock(...)` 传递它们就深度导入运行时辅助函数。
|
||||
- `pnpm test:perf:changed:bench -- --ref <git-ref>` 会将定向 `test:changed` 与该提交 diff 的原生根项目路径进行对比,并输出墙钟时间以及 macOS 最大 RSS。
|
||||
- `pnpm test:perf:changed:bench -- --worktree` 会通过 `scripts/test-projects.mjs` 和根 Vitest 配置将当前脏工作树的变更文件列表进行路由,并做基准测试。
|
||||
- `pnpm test:perf:imports` 会启用 Vitest 导入时长报告以及导入拆解输出。
|
||||
- `pnpm test:perf:imports:changed` 会将相同的分析视图限定到自 `origin/main` 以来变更的文件。
|
||||
- 当某个热点测试仍将大部分时间花在启动导入上时,应将重依赖放在狭窄的本地 `*.runtime.ts` 接缝之后,并直接 mock 该接缝,而不是为了通过 `vi.mock(...)` 传递它们就深度导入运行时辅助函数。
|
||||
- `pnpm test:perf:changed:bench -- --ref <git-ref>` 会将已路由的 `test:changed` 与该已提交 diff 的原生根项目路径进行比较,并输出 wall time 以及 macOS 最大 RSS。
|
||||
- `pnpm test:perf:changed:bench -- --worktree` 会通过将变更文件列表路由到 `scripts/test-projects.mjs` 和根 Vitest 配置,对当前未提交工作树进行基准测试。
|
||||
- `pnpm test:perf:profile:main` 会为 Vitest / Vite 启动与 transform 开销写入主线程 CPU profile。
|
||||
- `pnpm test:perf:profile:runner` 会在禁用文件并行的情况下,为单元测试套件写入运行器 CPU + heap profile。
|
||||
- `pnpm test:perf:profile:runner` 会在禁用文件级并行的情况下,为 unit 套件写入 runner CPU + heap profile。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 稳定性(Gateway 网关)
|
||||
|
||||
- 命令:`pnpm test:stability:gateway`
|
||||
- 配置:`vitest.gateway.config.ts`,强制单 worker
|
||||
- 配置:`vitest.gateway.config.ts`,强制使用单个 worker
|
||||
- 范围:
|
||||
- 启动一个默认启用诊断功能的真实 loopback Gateway 网关
|
||||
- 通过诊断事件路径驱动合成的 Gateway 网关消息、内存和大载荷抖动
|
||||
- 启动一个真实的 loopback Gateway 网关,并默认启用诊断
|
||||
- 通过诊断事件路径驱动合成的 gateway 消息、memory 和大负载 churn
|
||||
- 通过 Gateway 网关 WS RPC 查询 `diagnostics.stability`
|
||||
- 覆盖诊断稳定性 bundle 持久化辅助函数
|
||||
- 断言记录器保持有界、合成 RSS 采样保持在压力预算之下,并且每个会话的队列深度最终回落到零
|
||||
- 断言 recorder 保持有界、合成 RSS 样本保持在压力预算之下,以及每个 session 的队列深度会回落到零
|
||||
- 预期:
|
||||
- 对 CI 安全且不需要密钥
|
||||
- 这是用于稳定性回归跟进的窄通道,不可替代完整的 Gateway 网关测试套件
|
||||
- 可安全用于 CI,且不需要密钥
|
||||
- 这是一个用于稳定性回归跟进的窄通道,不可替代完整的 Gateway 网关套件
|
||||
|
||||
### E2E(Gateway 网关冒烟)
|
||||
|
||||
- 命令:`pnpm test:e2e`
|
||||
- 配置:`vitest.e2e.config.ts`
|
||||
- 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的内置插件 E2E 测试
|
||||
- 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下内置插件的 E2E 测试
|
||||
- 运行时默认值:
|
||||
- 使用 Vitest `threads`,并设置 `isolate: false`,与仓库其余部分保持一致。
|
||||
- 使用 Vitest `threads` 并设置 `isolate: false`,与仓库其余部分保持一致。
|
||||
- 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。
|
||||
- 默认以静默模式运行,以减少控制台 I/O 开销。
|
||||
- 常用覆盖项:
|
||||
- `OPENCLAW_E2E_WORKERS=<n>` 用于强制指定 worker 数量(上限为 16)。
|
||||
- `OPENCLAW_E2E_VERBOSE=1` 用于重新启用详细控制台输出。
|
||||
- `OPENCLAW_E2E_WORKERS=<n>` 强制指定 worker 数量(上限为 16)。
|
||||
- `OPENCLAW_E2E_VERBOSE=1` 重新启用详细控制台输出。
|
||||
- 范围:
|
||||
- 多实例 Gateway 网关端到端行为
|
||||
- 多实例 gateway 端到端行为
|
||||
- WebSocket / HTTP 接口、节点配对以及更重的网络行为
|
||||
- 预期:
|
||||
- 会在 CI 中运行(当流水线启用时)
|
||||
- 在 CI 中运行(当流水线启用时)
|
||||
- 不需要真实密钥
|
||||
- 比单元测试涉及更多活动部件(可能更慢)
|
||||
- 比 unit 测试涉及更多活动部件(可能更慢)
|
||||
|
||||
### E2E:OpenShell 后端冒烟
|
||||
|
||||
- 命令:`pnpm test:e2e:openshell`
|
||||
- 文件:`extensions/openshell/src/backend.e2e.test.ts`
|
||||
- 范围:
|
||||
- 通过 Docker 在主机上启动一个隔离的 OpenShell Gateway 网关
|
||||
- 通过 Docker 在主机上启动一个隔离的 OpenShell gateway
|
||||
- 从临时本地 Dockerfile 创建一个沙箱
|
||||
- 通过真实的 `sandbox ssh-config` + SSH exec 运行 OpenClaw 的 OpenShell 后端
|
||||
- 通过真实的 `sandbox ssh-config` + SSH exec 测试 OpenClaw 的 OpenShell 后端
|
||||
- 通过沙箱 fs bridge 验证远端规范文件系统行为
|
||||
- 预期:
|
||||
- 仅按需启用;不属于默认 `pnpm test:e2e` 运行的一部分
|
||||
- 需要本地 `openshell` CLI 和可用的 Docker daemon
|
||||
- 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 Gateway 网关和沙箱
|
||||
- 需要本地 `openshell` CLI 以及可用的 Docker daemon
|
||||
- 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 gateway 和沙箱
|
||||
- 常用覆盖项:
|
||||
- `OPENCLAW_E2E_OPENSHELL=1`,在手动运行更广泛的 e2e 测试套件时启用该测试
|
||||
- `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`,用于指定非默认 CLI 二进制或包装脚本
|
||||
- `OPENCLAW_E2E_OPENSHELL=1`,在手动运行更广泛的 e2e 套件时启用该测试
|
||||
- `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`,指向非默认 CLI 二进制或包装脚本
|
||||
|
||||
### 实时测试(真实提供商 + 真实模型)
|
||||
### Live(真实 provider + 真实模型)
|
||||
|
||||
- 命令:`pnpm test:live`
|
||||
- 配置:`vitest.live.config.ts`
|
||||
- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件实时测试
|
||||
- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下内置插件的 live 测试
|
||||
- 默认:由 `pnpm test:live` **启用**(设置 `OPENCLAW_LIVE_TEST=1`)
|
||||
- 范围:
|
||||
- “这个提供商 / 模型在 _今天_ 搭配真实凭证时真的能工作吗?”
|
||||
- 捕获提供商格式变化、工具调用怪癖、认证问题以及速率限制行为
|
||||
- “这个 provider / 模型 _今天_ 是否真的能在真实凭证下工作?”
|
||||
- 捕获 provider 格式变化、工具调用怪癖、认证问题和限流行为
|
||||
- 预期:
|
||||
- 按设计并不具备 CI 稳定性(真实网络、真实提供商策略、配额、故障)
|
||||
- 会花钱 / 消耗速率限制
|
||||
- 优先运行缩小范围的子集,而不是“全部”
|
||||
- 实时运行会读取 `~/.profile`,以获取缺失的 API 密钥。
|
||||
- 默认情况下,实时运行仍会隔离 `HOME`,并将配置 / 认证材料复制到临时测试 home 中,以便单元测试夹具不会修改你的真实 `~/.openclaw`。
|
||||
- 仅当你有意需要让实时测试使用真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。
|
||||
- `pnpm test:live` 现在默认采用更安静的模式:会保留 `[live] ...` 进度输出,但抑制额外的 `~/.profile` 提示,并静默 Gateway 网关启动日志 / Bonjour 噪声。如果你想恢复完整启动日志,可设置 `OPENCLAW_LIVE_TEST_QUIET=0`。
|
||||
- API 密钥轮换(提供商专属):设置逗号 / 分号格式的 `*_API_KEYS` 或 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),或者通过 `OPENCLAW_LIVE_*_KEY` 进行每次实时运行覆盖;测试在遇到速率限制响应时会重试。
|
||||
- 进度 / 心跳输出:
|
||||
- 实时测试套件现在会将进度行输出到 stderr,因此即使 Vitest 控制台捕获较安静,长时间的提供商调用也能明显显示为仍在活动中。
|
||||
- `vitest.live.config.ts` 禁用了 Vitest 控制台拦截,因此提供商 / Gateway 网关进度行会在实时运行期间立即流式输出。
|
||||
- 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整直接模型心跳。
|
||||
- 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关 / 探测心跳。
|
||||
- 按设计不具有 CI 稳定性(真实网络、真实 provider 策略、配额、故障)
|
||||
- 会花钱 / 使用限流额度
|
||||
- 应优先运行收窄后的子集,而不是“全部”
|
||||
- live 运行会 source `~/.profile`,以获取缺失的 API key。
|
||||
- 默认情况下,live 运行仍会隔离 `HOME`,并将配置 / 认证材料复制到临时测试 home 中,这样 unit fixture 就不会修改你真实的 `~/.openclaw`。
|
||||
- 仅当你有意让 live 测试使用真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。
|
||||
- `pnpm test:live` 现在默认使用更安静的模式:它保留 `[live] ...` 进度输出,但会抑制额外的 `~/.profile` 提示,并静默 gateway 启动日志 / Bonjour 杂讯。如果你想恢复完整启动日志,请设置 `OPENCLAW_LIVE_TEST_QUIET=0`。
|
||||
- API key 轮换(provider 特定):设置 `*_API_KEYS`,使用逗号 / 分号格式,或设置 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),也可以通过 `OPENCLAW_LIVE_*_KEY` 进行每次 live 运行覆盖;测试会在遇到 rate limit 响应时重试。
|
||||
- 进度 / heartbeat 输出:
|
||||
- live 套件现在会将进度行输出到 stderr,因此即使 Vitest 控制台捕获很安静,长时间的 provider 调用也能显示仍在活动中。
|
||||
- `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,以便 provider / gateway 进度行在 live 运行期间立即流式输出。
|
||||
- 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整直接模型 heartbeat。
|
||||
- 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 gateway / probe heartbeat。
|
||||
|
||||
## 我应该运行哪个测试套件?
|
||||
## 我应该运行哪个套件?
|
||||
|
||||
使用这个决策表:
|
||||
使用下面这个决策表:
|
||||
|
||||
- 修改逻辑 / 测试:运行 `pnpm test`(如果你改动很多,再运行 `pnpm test:coverage`)
|
||||
- 触及 Gateway 网关网络 / WS 协议 / 配对:额外运行 `pnpm test:e2e`
|
||||
- 调试“我的 bot 挂了” / 提供商专属故障 / 工具调用问题:运行缩小范围的 `pnpm test:live`
|
||||
- 编辑逻辑 / 测试:运行 `pnpm test`(如果你改动很多,再加上 `pnpm test:coverage`)
|
||||
- 涉及 gateway 网络 / WS 协议 / 配对:加跑 `pnpm test:e2e`
|
||||
- 调试“我的 bot 挂了” / provider 特定故障 / 工具调用:运行收窄后的 `pnpm test:live`
|
||||
|
||||
## 实时测试(触网测试)
|
||||
## Live(触网)测试
|
||||
|
||||
关于实时模型矩阵、CLI 后端冒烟、ACP 冒烟、Codex app-server
|
||||
测试支架,以及所有媒体提供商实时测试(Deepgram、BytePlus(国际版)、ComfyUI、图像、音乐、视频、媒体测试支架)——以及实时运行的凭证处理——请参见
|
||||
[测试——实时测试套件](/zh-CN/help/testing-live)。
|
||||
关于 live 模型矩阵、CLI 后端冒烟、ACP 冒烟、Codex app-server
|
||||
harness,以及所有媒体 provider live 测试(Deepgram、BytePlus(国际版)、ComfyUI、图像、
|
||||
音乐、视频、媒体 harness)——外加 live 运行的凭证处理——请参见
|
||||
[测试 — live 套件](/zh-CN/help/testing-live)。
|
||||
|
||||
## Docker 运行器(可选的“在 Linux 中可工作”检查)
|
||||
|
||||
这些 Docker 运行器分成两类:
|
||||
这些 Docker 运行器分为两类:
|
||||
|
||||
- 实时模型运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只会在仓库 Docker 镜像中运行与之匹配的 profile-key 实时测试文件(`src/agents/models.profiles.live.test.ts` 和 `src/gateway/gateway-models.profiles.live.test.ts`),挂载你的本地配置目录和工作区(如果已挂载,也会读取 `~/.profile`)。对应的本地入口点是 `test:live:models-profiles` 和 `test:live:gateway-profiles`。
|
||||
- Docker 实时运行器默认使用较小的冒烟上限,以便完整 Docker 扫描保持可行:
|
||||
`test:docker:live-models` 默认设置 `OPENCLAW_LIVE_MAX_MODELS=12`,而
|
||||
`test:docker:live-gateway` 默认设置 `OPENCLAW_LIVE_GATEWAY_SMOKE=1`、
|
||||
- live 模型运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只会在仓库 Docker 镜像内运行其对应的 profile-key live 文件(`src/agents/models.profiles.live.test.ts` 和 `src/gateway/gateway-models.profiles.live.test.ts`),并挂载你的本地配置目录和工作区(如果已挂载,则也会 source `~/.profile`)。对应的本地入口点是 `test:live:models-profiles` 和 `test:live:gateway-profiles`。
|
||||
- Docker live 运行器默认采用更小的冒烟上限,以便完整的 Docker 扫描保持可行:
|
||||
`test:docker:live-models` 默认使用 `OPENCLAW_LIVE_MAX_MODELS=12`,而
|
||||
`test:docker:live-gateway` 默认使用 `OPENCLAW_LIVE_GATEWAY_SMOKE=1`、
|
||||
`OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`、
|
||||
`OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000`,以及
|
||||
`OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。只有当你明确想执行更大范围的完整扫描时,才覆盖这些环境变量。
|
||||
- `test:docker:all` 会先通过 `test:docker:live-build` 构建一次实时 Docker 镜像,然后在两个实时 Docker 通道中复用它。它还会通过 `test:docker:e2e-build` 构建一个共享的 `scripts/e2e/Dockerfile` 镜像,并在执行已构建应用的 E2E 容器冒烟运行器中复用该镜像。
|
||||
`OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。当你
|
||||
明确想要更大规模的穷尽扫描时,可覆盖这些环境变量。
|
||||
- `test:docker:all` 会先通过 `test:docker:live-build` 构建一次 live Docker 镜像,然后在两个 live Docker 通道中复用它。它还会通过 `test:docker:e2e-build` 构建一个共享的 `scripts/e2e/Dockerfile` 镜像,并将其复用于测试构建后应用的 E2E 容器冒烟运行器。
|
||||
- 容器冒烟运行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:gateway-network`、`test:docker:mcp-channels`、`test:docker:pi-bundle-mcp-tools`、`test:docker:cron-mcp-cleanup`、`test:docker:plugins`、`test:docker:plugin-update` 和 `test:docker:config-reload` 会启动一个或多个真实容器,并验证更高层级的集成路径。
|
||||
|
||||
实时模型 Docker 运行器还只会 bind-mount 所需的 CLI 认证 home(如果运行未缩小范围,则挂载所有受支持的 home),然后在运行前将它们复制到容器 home 中,以便外部 CLI OAuth 可以刷新 token,同时不会修改主机认证存储:
|
||||
live 模型 Docker 运行器还只会 bind-mount 所需的 CLI 认证 home(如果运行未收窄,则挂载所有受支持的认证 home),然后在运行前将它们复制到容器 home 中,这样外部 CLI OAuth 就可以刷新 token,而不会修改主机认证存储:
|
||||
|
||||
- 直接模型:`pnpm test:docker:live-models`(脚本:`scripts/test-live-models-docker.sh`)
|
||||
- ACP 绑定冒烟:`pnpm test:docker:live-acp-bind`(脚本:`scripts/test-live-acp-bind-docker.sh`)
|
||||
- CLI 后端冒烟:`pnpm test:docker:live-cli-backend`(脚本:`scripts/test-live-cli-backend-docker.sh`)
|
||||
- Codex app-server 测试支架冒烟:`pnpm test:docker:live-codex-harness`(脚本:`scripts/test-live-codex-harness-docker.sh`)
|
||||
- Gateway 网关 + 开发智能体:`pnpm test:docker:live-gateway`(脚本:`scripts/test-live-gateway-models-docker.sh`)
|
||||
- Open WebUI 实时冒烟:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`)
|
||||
- Codex app-server harness 冒烟:`pnpm test:docker:live-codex-harness`(脚本:`scripts/test-live-codex-harness-docker.sh`)
|
||||
- Gateway 网关 + dev 智能体:`pnpm test:docker:live-gateway`(脚本:`scripts/test-live-gateway-models-docker.sh`)
|
||||
- Open WebUI live 冒烟:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`)
|
||||
- 新手引导向导(TTY,完整脚手架):`pnpm test:docker:onboard`(脚本:`scripts/e2e/onboard-docker.sh`)
|
||||
- npm tarball 新手引导 / 渠道 / 智能体冒烟:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装打包后的 OpenClaw tarball,通过环境变量引用式新手引导配置 OpenAI,并默认配置 Telegram,验证 doctor 会修复已激活插件的运行时依赖,然后运行一次模拟的 OpenAI 智能体轮次。可通过 `OPENCLAW_NPM_ONBOARD_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,通过 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机构建,或通过 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换渠道。
|
||||
- Bun 全局安装冒烟:`bash scripts/e2e/bun-global-install-smoke.sh` 会打包当前工作树,在隔离的 home 中使用 `bun install -g` 安装,并验证 `openclaw infer image providers --json` 会返回内置图像提供商而不是卡住。可通过 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,通过 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳过主机构建,或通过 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 从已构建的 Docker 镜像复制 `dist/`。
|
||||
- 安装冒烟 Docker 测试:`bash scripts/test-install-sh-docker.sh` 会在 root、更新和 direct-npm 容器之间共享一个 npm 缓存。更新冒烟默认以 npm `latest` 作为稳定基线,再升级到候选 tarball。非 root 安装器检查会保持隔离的 npm 缓存,以免 root 拥有的缓存条目掩盖用户本地安装行为。设置 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` 可在本地重跑之间复用 root / 更新 / direct-npm 缓存。
|
||||
- Install Smoke CI 会通过 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳过重复的 direct-npm 全局更新;如果你需要直接 `npm install -g` 覆盖,请在本地运行脚本时不要设置该环境变量。
|
||||
- Npm tarball 新手引导 / 渠道 / 智能体冒烟:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装打包后的 OpenClaw tarball,通过 env-ref onboarding 配置 OpenAI,并默认配置 Telegram,验证 doctor 会修复已激活插件的运行时依赖,并运行一次模拟的 OpenAI 智能体轮次。可使用 `OPENCLAW_NPM_ONBOARD_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,使用 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机构建,或使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换渠道。
|
||||
- Bun 全局安装冒烟:`bash scripts/e2e/bun-global-install-smoke.sh` 会打包当前工作树,在隔离的 home 中使用 `bun install -g` 安装,并验证 `openclaw infer image providers --json` 会返回内置图像 provider,而不是卡住。可使用 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,使用 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳过主机构建,或使用 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 从已构建的 Docker 镜像复制 `dist/`。
|
||||
- 安装器 Docker 冒烟:`bash scripts/test-install-sh-docker.sh` 会在其 root、update 和 direct-npm 容器之间共享一个 npm 缓存。更新冒烟默认使用 npm `latest` 作为稳定基线,然后再升级到候选 tarball。非 root 安装器检查会保留独立的 npm 缓存,这样 root 拥有的缓存条目就不会掩盖用户本地安装行为。设置 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` 可在本地重跑之间复用 root / update / direct-npm 缓存。
|
||||
- Install Smoke CI 会通过 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳过重复的 direct-npm 全局更新;当你需要覆盖直接 `npm install -g` 时,请在本地运行脚本且不要设置该环境变量。
|
||||
- Gateway 网关网络(两个容器,WS 认证 + 健康检查):`pnpm test:docker:gateway-network`(脚本:`scripts/e2e/gateway-network-docker.sh`)
|
||||
- OpenAI Responses `web_search` 最小推理回归测试:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)会通过 Gateway 网关运行一个模拟 OpenAI 服务器,验证 `web_search` 会将 `reasoning.effort` 从 `minimal` 提升到 `low`,然后强制提供商 schema 拒绝,并检查原始细节是否出现在 Gateway 网关日志中。
|
||||
- MCP 渠道桥接(带种子 Gateway 网关 + stdio bridge + 原始 Claude notification-frame 冒烟):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`)
|
||||
- OpenAI Responses `web_search` 最小推理回归:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)会通过 Gateway 网关运行一个模拟的 OpenAI 服务器,验证 `web_search` 会将 `reasoning.effort` 从 `minimal` 提升到 `low`,然后强制 provider schema 拒绝,并检查原始细节是否出现在 Gateway 网关日志中。
|
||||
- MCP 渠道桥接(带 seed 的 Gateway 网关 + stdio bridge + 原始 Claude 通知帧冒烟):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`)
|
||||
- Pi bundle MCP 工具(真实 stdio MCP 服务器 + 嵌入式 Pi profile allow / deny 冒烟):`pnpm test:docker:pi-bundle-mcp-tools`(脚本:`scripts/e2e/pi-bundle-mcp-tools-docker.sh`)
|
||||
- Cron / 子智能体 MCP 清理(真实 Gateway 网关 + stdio MCP 子进程在隔离 cron 和一次性子智能体运行后的销毁):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`)
|
||||
- Cron / subagent MCP 清理(真实 Gateway 网关 + 隔离 cron 和一次性 subagent 运行后的 stdio MCP 子进程拆除):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`)
|
||||
- 插件(安装冒烟 + `/plugin` 别名 + Claude bundle 重启语义):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-docker.sh`)
|
||||
- 插件更新未变更冒烟:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-docker.sh`)
|
||||
- 配置热重载元数据冒烟:`pnpm test:docker:config-reload`(脚本:`scripts/e2e/config-reload-source-docker.sh`)
|
||||
- 内置插件运行时依赖:`pnpm test:docker:bundled-channel-deps` 默认会构建一个小型 Docker 运行器镜像,在主机上构建并打包一次 OpenClaw,然后将该 tarball 挂载到每个 Linux 安装场景中。可通过 `OPENCLAW_SKIP_DOCKER_BUILD=1` 复用该镜像,在刚完成本地构建后通过 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 跳过主机重建,或通过 `OPENCLAW_BUNDLED_CHANNEL_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向现有 tarball。
|
||||
- 在迭代时,你可以通过禁用无关场景来缩小内置插件运行时依赖测试范围,例如:
|
||||
- 内置插件运行时依赖:`pnpm test:docker:bundled-channel-deps` 默认会构建一个小型 Docker 运行器镜像,在主机上构建并打包一次 OpenClaw,然后将该 tarball 挂载到每个 Linux 安装场景中。可使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 复用该镜像,在完成一次新的本地构建后使用 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 跳过主机构建,或通过 `OPENCLAW_BUNDLED_CHANNEL_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向现有 tarball。
|
||||
- 在迭代时,通过禁用无关场景来收窄内置插件运行时依赖测试,例如:
|
||||
`OPENCLAW_BUNDLED_CHANNEL_SCENARIOS=0 OPENCLAW_BUNDLED_CHANNEL_UPDATE_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_ROOT_OWNED_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_SETUP_ENTRY_SCENARIO=0 pnpm test:docker:bundled-channel-deps`。
|
||||
|
||||
若要手动预构建并复用共享的已构建应用镜像:
|
||||
要手动预构建并复用共享的 built-app 镜像:
|
||||
|
||||
```bash
|
||||
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e:local pnpm test:docker:e2e-build
|
||||
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels
|
||||
```
|
||||
|
||||
当设置时,诸如 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE` 这样的套件专属镜像覆盖仍然优先生效。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果该镜像尚未存在于本地,脚本会先拉取它。QR 和安装器 Docker 测试保留各自独立的 Dockerfile,因为它们验证的是包 / 安装行为,而不是共享的已构建应用运行时。
|
||||
当设置了套件特定镜像覆盖(例如 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`)时,它们仍然优先生效。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果本地尚不存在,该脚本会拉取它。QR 和安装器 Docker 测试会保留自己的 Dockerfile,因为它们验证的是打包 / 安装行为,而不是共享的 built-app 运行时。
|
||||
|
||||
实时模型 Docker 运行器还会以只读方式 bind-mount 当前检出内容,并将其暂存到容器内的临时工作目录中。这样既能保持运行时镜像精简,又能让 Vitest 针对你本地的精确源代码 / 配置运行。暂存步骤会跳过大型仅本地缓存和应用构建输出,例如 `.pnpm-store`、`.worktrees`、`__openclaw_vitest__` 以及应用本地的 `.build` 或 Gradle 输出目录,因此 Docker 实时运行不会花几分钟去复制机器专属制品。
|
||||
它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,这样 Gateway 网关实时探测就不会在容器内启动真实的 Telegram / Discord / 等渠道 worker。
|
||||
`test:docker:live-models` 仍然运行 `pnpm test:live`,因此当你需要缩小或排除该 Docker 通道中的 Gateway 网关实时覆盖时,也要一并传入 `OPENCLAW_LIVE_GATEWAY_*`。
|
||||
`test:docker:openwebui` 是一个更高层级的兼容性冒烟测试:它会启动一个启用了 OpenAI 兼容 HTTP 端点的 OpenClaw Gateway 网关容器,再针对该 Gateway 网关启动一个固定版本的 Open WebUI 容器,通过 Open WebUI 登录,验证 `/api/models` 暴露了 `openclaw/default`,然后通过 Open WebUI 的 `/api/chat/completions` 代理发送一个真实聊天请求。
|
||||
首次运行可能会明显更慢,因为 Docker 可能需要拉取 Open WebUI 镜像,并且 Open WebUI 可能需要完成自身的冷启动设置。
|
||||
这个通道需要一个可用的实时模型密钥,而 `OPENCLAW_PROFILE_FILE`(默认是 `~/.profile`)是在 Docker 化运行中提供它的主要方式。
|
||||
成功运行会打印一小段 JSON 载荷,例如 `{ "ok": true, "model": "openclaw/default", ... }`。
|
||||
`test:docker:mcp-channels` 刻意设计为确定性测试,不需要真实的 Telegram、Discord 或 iMessage 账号。它会启动一个已播种的 Gateway 网关容器,再启动第二个容器来拉起 `openclaw mcp serve`,然后通过真实的 stdio MCP bridge 验证路由后的会话发现、转录读取、附件元数据、实时事件队列行为、出站发送路由,以及 Claude 风格的渠道 + 权限通知。通知检查会直接检查原始 stdio MCP 帧,因此该冒烟测试验证的是 bridge 实际发出了什么,而不仅仅是某个特定客户端 SDK 恰好暴露了什么。
|
||||
`test:docker:pi-bundle-mcp-tools` 是确定性的,不需要实时模型密钥。它会构建仓库 Docker 镜像,在容器内启动一个真实的 stdio MCP 探测服务器,通过嵌入式 Pi bundle MCP 运行时实例化该服务器,执行工具,然后验证 `coding` 和 `messaging` 会保留 `bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会将其过滤掉。
|
||||
`test:docker:cron-mcp-cleanup` 是确定性的,也不需要实时模型密钥。它会启动一个带真实 stdio MCP 探测服务器的已播种 Gateway 网关,运行一个隔离的 cron 轮次和一个 `/subagents spawn` 一次性子智能体轮次,然后验证 MCP 子进程会在每次运行后退出。
|
||||
live 模型 Docker 运行器还会以只读方式 bind-mount 当前 checkout,并在容器内将其暂存到一个临时 workdir。这样既能保持运行时镜像精简,又仍然能针对你本地的精确 source / 配置运行 Vitest。暂存步骤会跳过大型本地专用缓存和应用构建输出,例如 `.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及应用本地的 `.build` 或 Gradle 输出目录,从而避免 Docker live 运行花费数分钟复制与机器相关的工件。
|
||||
它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,这样 gateway live 探测就不会在容器内启动真实的 Telegram / Discord / 等渠道 worker。
|
||||
`test:docker:live-models` 仍然会运行 `pnpm test:live`,因此当你需要从该 Docker 通道中收窄或排除 gateway live 覆盖时,也要一并传入 `OPENCLAW_LIVE_GATEWAY_*`。
|
||||
`test:docker:openwebui` 是一个更高层的兼容性冒烟测试:它会启动一个启用了 OpenAI 兼容 HTTP 端点的 OpenClaw gateway 容器,启动一个固定版本的 Open WebUI 容器并将其指向该 gateway,通过 Open WebUI 登录,验证 `/api/models` 暴露了 `openclaw/default`,然后通过 Open WebUI 的 `/api/chat/completions` 代理发送一个真实聊天请求。
|
||||
第一次运行可能会明显更慢,因为 Docker 可能需要拉取 Open WebUI 镜像,而且 Open WebUI 可能需要完成自己的冷启动设置。
|
||||
该通道需要一个可用的 live 模型 key,而 `OPENCLAW_PROFILE_FILE`
|
||||
(默认 `~/.profile`)是在 Docker 化运行中提供该 key 的主要方式。
|
||||
成功运行会打印一个小型 JSON payload,例如 `{ "ok": true, "model":
|
||||
"openclaw/default", ... }`。
|
||||
`test:docker:mcp-channels` 是刻意保持确定性的,不需要真实的 Telegram、Discord 或 iMessage 账户。它会启动一个带 seed 的 Gateway 容器,启动第二个容器来运行 `openclaw mcp serve`,然后验证通过真实 stdio MCP bridge 路由的会话发现、transcript 读取、附件元数据、live 事件队列行为、出站发送路由,以及 Claude 风格的渠道 + 权限通知。通知检查会直接检查原始 stdio MCP 帧,因此该冒烟测试验证的是 bridge 实际发出的内容,而不仅仅是某个特定 client SDK 恰好暴露出来的内容。
|
||||
`test:docker:pi-bundle-mcp-tools` 是确定性的,不需要 live 模型 key。它会构建仓库 Docker 镜像,在容器内启动一个真实 stdio MCP 探测服务器,通过嵌入式 Pi bundle MCP 运行时实例化该服务器,执行工具,然后验证 `coding` 和 `messaging` 会保留 `bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会将其过滤掉。
|
||||
`test:docker:cron-mcp-cleanup` 是确定性的,不需要 live 模型 key。它会启动一个带 seed 的 Gateway 网关和一个真实 stdio MCP 探测服务器,运行一次隔离的 cron 轮次和一次 `/subagents spawn` 单次子智能体轮次,然后验证 MCP 子进程会在每次运行后退出。
|
||||
|
||||
手动 ACP 自然语言线程冒烟测试(非 CI):
|
||||
|
||||
- `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel <discord-channel-id> ...`
|
||||
- 保留这个脚本用于回归 / 调试工作流。之后做 ACP 线程路由验证时可能还需要它,因此不要删除它。
|
||||
- 为回归 / 调试工作流保留此脚本。后续可能仍需要它来验证 ACP 线程路由,因此不要删除它。
|
||||
|
||||
常用环境变量:
|
||||
|
||||
- `OPENCLAW_CONFIG_DIR=...`(默认:`~/.openclaw`)挂载到 `/home/node/.openclaw`
|
||||
- `OPENCLAW_WORKSPACE_DIR=...`(默认:`~/.openclaw/workspace`)挂载到 `/home/node/.openclaw/workspace`
|
||||
- `OPENCLAW_PROFILE_FILE=...`(默认:`~/.profile`)挂载到 `/home/node/.profile`,并在运行测试前读取
|
||||
- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 用于仅验证从 `OPENCLAW_PROFILE_FILE` 读取的环境变量,此时使用临时配置 / 工作区目录,并且不挂载外部 CLI 认证
|
||||
- `OPENCLAW_PROFILE_FILE=...`(默认:`~/.profile`)挂载到 `/home/node/.profile`,并在运行测试前 source
|
||||
- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 用于验证仅使用从 `OPENCLAW_PROFILE_FILE` source 的环境变量,采用临时 config / workspace 目录,并且不挂载外部 CLI 认证
|
||||
- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(默认:`~/.cache/openclaw/docker-cli-tools`)挂载到 `/home/node/.npm-global`,用于 Docker 内缓存的 CLI 安装
|
||||
- `$HOME` 下的外部 CLI 认证目录 / 文件会以只读方式挂载到 `/host-auth...` 下,然后在测试开始前复制到 `/home/node/...`
|
||||
- 默认目录:`.minimax`
|
||||
- 默认文件:`~/.codex/auth.json`、`~/.codex/config.toml`、`.claude.json`、`~/.claude/.credentials.json`、`~/.claude/settings.json`、`~/.claude/settings.local.json`
|
||||
- 缩小范围的提供商运行只会挂载根据 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录 / 文件
|
||||
- 可通过 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none`,或类似 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 的逗号列表手动覆盖
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` 用于缩小运行范围
|
||||
- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` 用于在容器内筛选提供商
|
||||
- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于复用现有的 `openclaw:local-live` 镜像,以便在无需重建的重跑中使用
|
||||
- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用于确保凭证来自 profile 存储(而不是环境变量)
|
||||
- `OPENCLAW_OPENWEBUI_MODEL=...` 用于选择 Gateway 网关为 Open WebUI 冒烟测试暴露的模型
|
||||
- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试使用的 nonce 检查提示词
|
||||
- 收窄后的 provider 运行只会挂载根据 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录 / 文件
|
||||
- 可通过 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none` 或类似 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 的逗号列表手动覆盖
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` 用于收窄运行范围
|
||||
- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` 用于在容器内筛选 provider
|
||||
- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于在不需要重建的重跑中复用现有 `openclaw:local-live` 镜像
|
||||
- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用于确保凭证来自 profile 存储(而非 env)
|
||||
- `OPENCLAW_OPENWEBUI_MODEL=...` 用于选择 gateway 为 Open WebUI 冒烟测试暴露的模型
|
||||
- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试使用的 nonce-check 提示词
|
||||
- `OPENWEBUI_IMAGE=...` 用于覆盖固定的 Open WebUI 镜像标签
|
||||
|
||||
## 文档完整性检查
|
||||
|
||||
修改文档后运行文档检查:`pnpm check:docs`。
|
||||
当你还需要检查页内标题时,运行完整的 Mintlify anchor 验证:`pnpm docs:check-links:anchors`。
|
||||
当你还需要完整的 Mintlify 锚点校验(包括页内标题检查)时,运行:`pnpm docs:check-links:anchors`。
|
||||
|
||||
## 离线回归测试(CI 安全)
|
||||
## 离线回归(CI 安全)
|
||||
|
||||
这些是在没有真实提供商的情况下进行的“真实流水线”回归测试:
|
||||
这些是在没有真实 provider 的情况下进行的“真实流水线”回归:
|
||||
|
||||
- Gateway 网关工具调用(模拟 OpenAI,真实 Gateway 网关 + 智能体循环):`src/gateway/gateway.test.ts`(用例:“runs a mock OpenAI tool call end-to-end via gateway agent loop”)
|
||||
- Gateway 网关向导(WS `wizard.start` / `wizard.next`,强制写入配置 + 认证):`src/gateway/gateway.test.ts`(用例:“runs wizard over ws and writes auth token config”)
|
||||
- Gateway 网关工具调用(模拟 OpenAI、真实 gateway + 智能体循环):`src/gateway/gateway.test.ts`(用例:“runs a mock OpenAI tool call end-to-end via gateway agent loop”)
|
||||
- Gateway 网关向导(WS `wizard.start` / `wizard.next`,会写入配置 + 强制写入认证):`src/gateway/gateway.test.ts`(用例:“runs wizard over ws and writes auth token config”)
|
||||
|
||||
## 智能体可靠性评估(Skills)
|
||||
|
||||
我们已经有一些 CI 安全的测试,它们的行为就像“智能体可靠性评估”:
|
||||
我们已经有一些 CI 安全的测试,它们的行为类似“智能体可靠性评估”:
|
||||
|
||||
- 通过真实 Gateway 网关 + 智能体循环的模拟工具调用(`src/gateway/gateway.test.ts`)。
|
||||
- 验证会话接线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。
|
||||
- 通过真实 gateway + 智能体循环进行的模拟工具调用(`src/gateway/gateway.test.ts`)。
|
||||
- 验证 session 接线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。
|
||||
|
||||
对于 Skills(见 [Skills](/zh-CN/tools/skills)),目前仍缺少的是:
|
||||
|
||||
- **决策能力:** 当提示中列出 Skills 时,智能体是否会选择正确的 Skills(或避开无关的 Skills)?
|
||||
- **合规性:** 智能体是否会在使用前读取 `SKILL.md`,并遵循所需步骤 / 参数?
|
||||
- **工作流契约:** 断言工具顺序、会话历史延续和沙箱边界的多轮场景。
|
||||
- **决策能力:** 当提示词中列出 Skills 时,智能体是否会选择正确的 skill(或避免选择无关的 skill)?
|
||||
- **合规性:** 智能体是否会在使用前读取 `SKILL.md`,并遵循要求的步骤 / 参数?
|
||||
- **工作流契约:** 断言工具顺序、session 历史延续以及沙箱边界的多轮场景。
|
||||
|
||||
未来的评估应首先保持确定性:
|
||||
未来的评估应优先保持确定性:
|
||||
|
||||
- 一个使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、skill 文件读取和会话接线。
|
||||
- 一小组聚焦 skill 的场景(使用 vs 避免、门控、提示注入)。
|
||||
- 只有在 CI 安全套件落地之后,才考虑可选的实时评估(按需启用,受环境变量门控)。
|
||||
- 一个使用 mock provider 的场景运行器,用于断言工具调用 + 顺序、skill 文件读取以及 session 接线。
|
||||
- 一小组聚焦于 skill 的场景(使用 vs 避免、门控、提示词注入)。
|
||||
- 可选的 live evals(仅限 opt-in,受环境变量控制),但必须在 CI 安全套件就位之后再添加。
|
||||
|
||||
## 契约测试(插件和渠道形状)
|
||||
|
||||
契约测试会验证每个已注册插件和渠道都符合其接口契约。它们会遍历所有已发现的插件,并运行一组关于形状和行为的断言。默认的 `pnpm test` 单元通道刻意跳过这些共享接缝和冒烟文件;当你修改共享渠道或提供商表面时,请显式运行契约命令。
|
||||
契约测试用于验证每个已注册插件和渠道都符合其接口契约。它们会遍历所有已发现的插件,并运行一组关于形状和行为的断言。默认的 `pnpm test` unit 通道会刻意跳过这些共享接缝和冒烟文件;当你修改共享的 channel 或 provider 接口时,请显式运行这些契约命令。
|
||||
|
||||
### 命令
|
||||
|
||||
- 所有契约测试:`pnpm test:contracts`
|
||||
- 仅渠道契约测试:`pnpm test:contracts:channels`
|
||||
- 仅提供商契约测试:`pnpm test:contracts:plugins`
|
||||
- 所有契约:`pnpm test:contracts`
|
||||
- 仅渠道契约:`pnpm test:contracts:channels`
|
||||
- 仅 provider 契约:`pnpm test:contracts:plugins`
|
||||
|
||||
### 渠道契约测试
|
||||
### 渠道契约
|
||||
|
||||
位于 `src/channels/plugins/contracts/*.contract.test.ts`:
|
||||
|
||||
- **plugin** - 基本插件形状(id、name、capabilities)
|
||||
- **setup** - 设置向导契约
|
||||
- **session-binding** - 会话绑定行为
|
||||
- **outbound-payload** - 消息载荷结构
|
||||
- **outbound-payload** - 消息 payload 结构
|
||||
- **inbound** - 入站消息处理
|
||||
- **actions** - 渠道动作处理器
|
||||
- **threading** - 线程 ID 处理
|
||||
- **directory** - 目录 / roster API
|
||||
- **group-policy** - 群组策略执行
|
||||
|
||||
### 提供商状态契约测试
|
||||
### Provider 状态契约
|
||||
|
||||
位于 `src/plugins/contracts/*.contract.test.ts`。
|
||||
|
||||
- **status** - 渠道状态探测
|
||||
- **registry** - 插件注册表形状
|
||||
|
||||
### 提供商契约测试
|
||||
### Provider 契约
|
||||
|
||||
位于 `src/plugins/contracts/*.contract.test.ts`:
|
||||
|
||||
@ -562,32 +569,32 @@ OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e:local OPENCLAW_SKIP_DOCKER_BUILD=1
|
||||
- **catalog** - 模型目录 API
|
||||
- **discovery** - 插件发现
|
||||
- **loader** - 插件加载
|
||||
- **runtime** - 提供商运行时
|
||||
- **runtime** - provider 运行时
|
||||
- **shape** - 插件形状 / 接口
|
||||
- **wizard** - 设置向导
|
||||
|
||||
### 何时运行
|
||||
|
||||
- 修改插件 SDK 导出或子路径之后
|
||||
- 添加或修改渠道或提供商插件之后
|
||||
- 修改 plugin-sdk 导出或子路径之后
|
||||
- 添加或修改 channel 或 provider 插件之后
|
||||
- 重构插件注册或发现逻辑之后
|
||||
|
||||
契约测试会在 CI 中运行,并且不需要真实 API 密钥。
|
||||
契约测试会在 CI 中运行,并且不需要真实 API key。
|
||||
|
||||
## 添加回归测试(指导)
|
||||
## 添加回归测试(指南)
|
||||
|
||||
当你修复一个在实时测试中发现的提供商 / 模型问题时:
|
||||
当你修复在 live 中发现的 provider / 模型问题时:
|
||||
|
||||
- 如果可能,添加一个 CI 安全的回归测试(模拟 / stub 提供商,或捕获精确的请求形状转换)
|
||||
- 如果它天然只能在实时测试中复现(速率限制、认证策略),就保持实时测试足够窄,并通过环境变量按需启用
|
||||
- 优先定位能捕获该缺陷的最小层级:
|
||||
- 提供商请求转换 / 重放缺陷 → 直接模型测试
|
||||
- Gateway 网关会话 / 历史 / 工具流水线缺陷 → Gateway 网关实时冒烟测试或 CI 安全的 Gateway 网关模拟测试
|
||||
- SecretRef 遍历护栏:
|
||||
- `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言遍历片段 exec id 会被拒绝。
|
||||
- 如果你在 `src/secrets/target-registry-data.ts` 中添加了新的 `includeInPlan` SecretRef 目标族,请更新该测试中的 `classifyTargetClass`。该测试会在遇到未分类目标 id 时故意失败,以确保新类别不会被静默跳过。
|
||||
- 如果可能,添加一个 CI 安全的回归测试(mock / stub provider,或捕获精确的请求形状转换)
|
||||
- 如果它本质上只能在 live 中测试(限流、认证策略),请让 live 测试保持收窄,并通过环境变量启用 opt-in
|
||||
- 优先瞄准能捕获该缺陷的最小层级:
|
||||
- provider 请求转换 / 回放缺陷 → 直接模型测试
|
||||
- gateway 会话 / 历史 / 工具流水线缺陷 → gateway live 冒烟或 CI 安全的 gateway mock 测试
|
||||
- SecretRef 遍历防护栏:
|
||||
- `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言遍历段 exec id 会被拒绝。
|
||||
- 如果你在 `src/secrets/target-registry-data.ts` 中添加了新的 `includeInPlan` SecretRef 目标族,请更新该测试中的 `classifyTargetClass`。该测试会在遇到未分类目标 id 时有意失败,以确保新类别不会被静默跳过。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [实时测试](/zh-CN/help/testing-live)
|
||||
- [Testing live](/zh-CN/help/testing-live)
|
||||
- [CI](/zh-CN/ci)
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
---
|
||||
read_when:
|
||||
- 你希望一个 OpenClaw 智能体加入 Google Meet 通话
|
||||
- 你希望一个 OpenClaw 智能体加入一个 Google Meet 通话
|
||||
- 你正在将 Chrome、Chrome 节点或 Twilio 配置为 Google Meet 传输方式
|
||||
summary: Google Meet 插件:通过 Chrome 或 Twilio 使用实时语音默认设置加入明确指定的 Meet URL
|
||||
summary: Google Meet 插件:通过 Chrome 或 Twilio 加入明确的 Meet URL,并使用实时语音默认设置
|
||||
title: Google Meet 插件
|
||||
x-i18n:
|
||||
generated_at: "2026-04-24T05:28:12Z"
|
||||
generated_at: "2026-04-24T06:43:49Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ab439b777e3043cc647a29e8e17b2794d14f48deceaadf8f81a014dd44583e23
|
||||
source_hash: f0bf06b7ab585bf2dc9dbf6d890e1954e89e4deea148380e350d2d7f4d954f5e
|
||||
source_path: plugins/google-meet.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Google Meet(插件)
|
||||
|
||||
OpenClaw 的 Google Meet 参与者支持。
|
||||
OpenClaw 的 Google Meet 参会支持。
|
||||
|
||||
该插件在设计上是显式的:
|
||||
|
||||
- 它只加入明确指定的 `https://meet.google.com/...` URL。
|
||||
- 它只会加入明确的 `https://meet.google.com/...` URL。
|
||||
- `realtime` 语音是默认模式。
|
||||
- 当需要更深入的推理或工具时,实时语音可以回调到完整的 OpenClaw 智能体。
|
||||
- 认证从个人 Google OAuth 或已登录的 Chrome 配置文件开始。
|
||||
- 不会自动进行同意声明。
|
||||
- 认证起点是个人 Google OAuth 或已登录的 Chrome 配置文件。
|
||||
- 不会自动播报同意声明。
|
||||
- 默认的 Chrome 音频后端是 `BlackHole 2ch`。
|
||||
- Chrome 可以在本地运行,也可以在已配对的节点主机上运行。
|
||||
- Twilio 接受一个拨入号码以及可选的 PIN 或 DTMF 序列。
|
||||
- CLI 命令是 `googlemeet`;`meet` 保留给更广泛的智能体电话会议工作流使用。
|
||||
- Twilio 接受拨入号码以及可选的 PIN 或 DTMF 序列。
|
||||
- CLI 命令是 `googlemeet`;`meet` 保留给更广泛的智能体电话会议工作流。
|
||||
|
||||
## 快速开始
|
||||
|
||||
@ -44,7 +44,7 @@ export OPENAI_API_KEY=sk-...
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
重启后,验证这两项是否都已就绪:
|
||||
重启后,验证这两部分都已就绪:
|
||||
|
||||
```bash
|
||||
system_profiler SPAudioDataType | grep -i BlackHole
|
||||
@ -87,17 +87,17 @@ openclaw googlemeet join https://meet.google.com/abc-defg-hij
|
||||
}
|
||||
```
|
||||
|
||||
Chrome 将以已登录的 Chrome 配置文件身份加入。在 Meet 中,选择 `BlackHole 2ch` 作为 OpenClaw 使用的麦克风/扬声器路径。为了获得干净的双工音频,请使用独立的虚拟设备或类似 Loopback 的音频图;单个 BlackHole 设备足以完成首次冒烟测试,但可能会产生回声。
|
||||
Chrome 会以已登录的 Chrome 配置文件身份加入。在 Meet 中,为 OpenClaw 使用的麦克风/扬声器路径选择 `BlackHole 2ch`。为了获得干净的双工音频,请使用独立的虚拟设备或类似 Loopback 的音频图;单个 BlackHole 设备足以用于第一次冒烟测试,但可能会产生回声。
|
||||
|
||||
### 本地 Gateway 网关 + Parallels Chrome
|
||||
|
||||
你**不**需要在 macOS VM 中运行完整的 OpenClaw Gateway 网关或配置模型 API 密钥,只是为了让 VM 承载 Chrome。你可以在本地运行 Gateway 网关和智能体,然后在 VM 中运行一个节点主机。在 VM 中启用一次内置插件,这样节点就会通告 Chrome 命令:
|
||||
你**不**需要在 macOS VM 中运行完整的 OpenClaw Gateway 网关,也不需要模型 API 密钥,只为了让 VM 承担 Chrome。你可以在本地运行 Gateway 网关和智能体,然后在 VM 中运行一个节点主机。只需在 VM 上启用一次内置插件,这样节点就会通告 Chrome 命令:
|
||||
|
||||
各组件运行位置如下:
|
||||
各组件分别运行在何处:
|
||||
|
||||
- Gateway 网关主机:OpenClaw Gateway 网关、智能体工作区、模型/API 密钥、实时提供商,以及 Google Meet 插件配置。
|
||||
- Parallels macOS VM:OpenClaw CLI/节点主机、Google Chrome、SoX、BlackHole 2ch,以及一个已登录 Google 的 Chrome 配置文件。
|
||||
- VM 中不需要:Gateway 网关服务、智能体配置、OpenAI/GPT 密钥,或模型提供商设置。
|
||||
- VM 中不需要:Gateway 网关服务、智能体配置、OpenAI/GPT 密钥或模型提供商设置。
|
||||
|
||||
安装 VM 依赖:
|
||||
|
||||
@ -111,7 +111,7 @@ brew install blackhole-2ch sox
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
重启后,验证 VM 可以看到该音频设备以及 SoX 命令:
|
||||
重启后,验证 VM 能看到音频设备和 SoX 命令:
|
||||
|
||||
```bash
|
||||
system_profiler SPAudioDataType | grep -i BlackHole
|
||||
@ -130,7 +130,7 @@ openclaw plugins enable google-meet
|
||||
openclaw node run --host <gateway-host> --port 18789 --display-name parallels-macos
|
||||
```
|
||||
|
||||
如果 `<gateway-host>` 是局域网 IP,且你没有使用 TLS,除非你显式允许该受信私有网络,否则节点会拒绝明文 WebSocket:
|
||||
如果 `<gateway-host>` 是局域网 IP,且你未使用 TLS,那么除非你为该受信任的私有网络显式启用明文 WebSocket,否则节点会拒绝连接:
|
||||
|
||||
```bash
|
||||
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1 \
|
||||
@ -145,20 +145,22 @@ OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1 \
|
||||
openclaw node restart
|
||||
```
|
||||
|
||||
从 Gateway 网关主机批准该节点:
|
||||
`OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` 是进程环境变量,不是 `openclaw.json` 设置。若在安装命令中存在该变量,`openclaw node install` 会将其存储到 LaunchAgent 环境中。
|
||||
|
||||
在 Gateway 网关主机上批准该节点:
|
||||
|
||||
```bash
|
||||
openclaw devices list
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
|
||||
确认 Gateway 网关可以看到该节点,并且它通告了 `googlemeet.chrome`:
|
||||
确认 Gateway 网关能看到该节点,并且它通告了 `googlemeet.chrome`:
|
||||
|
||||
```bash
|
||||
openclaw nodes status
|
||||
```
|
||||
|
||||
在 Gateway 网关主机上通过该节点路由 Meet:
|
||||
在 Gateway 网关主机上将 Meet 路由到该节点:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -183,48 +185,48 @@ openclaw nodes status
|
||||
}
|
||||
```
|
||||
|
||||
现在你可以像平常一样从 Gateway 网关主机加入:
|
||||
现在可从 Gateway 网关主机像平常一样加入:
|
||||
|
||||
```bash
|
||||
openclaw googlemeet join https://meet.google.com/abc-defg-hij
|
||||
```
|
||||
|
||||
或者让智能体使用 `google_meet` 工具并设置 `transport: "chrome-node"`。
|
||||
或者让智能体使用 `google_meet` 工具并指定 `transport: "chrome-node"`。
|
||||
|
||||
如果省略 `chromeNode.node`,只有在恰好有一个已连接节点通告 `googlemeet.chrome` 时,OpenClaw 才会自动选择。如果连接了多个具备能力的节点,请将 `chromeNode.node` 设置为节点 ID、显示名称或远程 IP。
|
||||
如果省略 `chromeNode.node`,则仅当恰好有一个已连接节点通告 `googlemeet.chrome` 时,OpenClaw 才会自动选择。如果连接了多个具备该能力的节点,请将 `chromeNode.node` 设置为节点 id、显示名称或远程 IP。
|
||||
|
||||
常见故障检查:
|
||||
|
||||
- `No connected Google Meet-capable node`:在 VM 中启动 `openclaw node run`,批准配对,并确保已在 VM 中运行 `openclaw plugins enable google-meet`。同时确认 Gateway 网关主机通过 `gateway.nodes.allowCommands: ["googlemeet.chrome"]` 允许该节点命令。
|
||||
- `No connected Google Meet-capable node`:在 VM 中启动 `openclaw node run`,批准配对,并确保已在 VM 中运行 `openclaw plugins enable google-meet`。同时确认 Gateway 网关主机允许该节点命令,即设置 `gateway.nodes.allowCommands: ["googlemeet.chrome"]`。
|
||||
- `BlackHole 2ch audio device not found on the node`:在 VM 中安装 `blackhole-2ch` 并重启 VM。
|
||||
- Chrome 已打开但无法加入:在 VM 中登录 Chrome,并确认该配置文件可以手动加入该 Meet URL。
|
||||
- 没有音频:在 Meet 中,将麦克风/扬声器路由到 OpenClaw 使用的虚拟音频设备路径;使用独立虚拟设备或类似 Loopback 的路由以获得干净的双工音频。
|
||||
- Chrome 已打开但无法加入:在 VM 中登录 Chrome,并确认该配置文件可以手动加入 Meet URL。
|
||||
- 没有音频:在 Meet 中,将麦克风/扬声器路由到 OpenClaw 使用的虚拟音频设备路径;为获得干净的双工音频,请使用独立的虚拟设备或类似 Loopback 的路由方式。
|
||||
|
||||
## 安装说明
|
||||
|
||||
Chrome 实时默认路径使用两个外部工具:
|
||||
Chrome realtime 默认路径使用两个外部工具:
|
||||
|
||||
- `sox`:命令行音频工具。该插件使用其 `rec` 和 `play` 命令来实现默认的 8 kHz G.711 mu-law 音频桥接。
|
||||
- `sox`:命令行音频工具。该插件使用它的 `rec` 和 `play` 命令来实现默认的 8 kHz G.711 mu-law 音频桥接。
|
||||
- `blackhole-2ch`:macOS 虚拟音频驱动。它会创建 `BlackHole 2ch` 音频设备,供 Chrome/Meet 路由使用。
|
||||
|
||||
OpenClaw 不会内置或重新分发这两个软件包。文档要求用户通过 Homebrew 将其作为主机依赖安装。SoX 的许可证是 `LGPL-2.0-only AND GPL-2.0-only`;BlackHole 是 GPL-3.0。如果你要构建一个将 BlackHole 与 OpenClaw 一起打包的安装程序或设备,请审查 BlackHole 上游的许可证条款,或从 Existential Audio 获取单独许可。
|
||||
OpenClaw 不会捆绑或重新分发这两个软件包。文档要求用户通过 Homebrew 将其安装为主机依赖。SoX 的许可证为 `LGPL-2.0-only AND GPL-2.0-only`;BlackHole 为 GPL-3.0。如果你要构建一个将 BlackHole 与 OpenClaw 一起打包的安装程序或设备,请审查 BlackHole 上游的许可条款,或从 Existential Audio 获取单独许可。
|
||||
|
||||
## 传输方式
|
||||
|
||||
### Chrome
|
||||
|
||||
Chrome 传输方式会在 Google Chrome 中打开 Meet URL,并以已登录的 Chrome 配置文件身份加入。在 macOS 上,插件会在启动前检查是否存在 `BlackHole 2ch`。如果已配置,它还会在打开 Chrome 之前运行音频桥健康检查命令和启动命令。当 Chrome/音频位于 Gateway 网关主机上时,请使用 `chrome`;当 Chrome/音频位于已配对节点(例如 Parallels macOS VM)上时,请使用 `chrome-node`。
|
||||
Chrome 传输方式会在 Google Chrome 中打开 Meet URL,并以已登录的 Chrome 配置文件身份加入。在 macOS 上,插件会在启动前检查是否存在 `BlackHole 2ch`。如果已配置,它还会在打开 Chrome 前运行音频桥接健康检查命令和启动命令。当 Chrome/音频位于 Gateway 网关主机上时,使用 `chrome`;当 Chrome/音频位于已配对节点(如 Parallels macOS VM)上时,使用 `chrome-node`。
|
||||
|
||||
```bash
|
||||
openclaw googlemeet join https://meet.google.com/abc-defg-hij --transport chrome
|
||||
openclaw googlemeet join https://meet.google.com/abc-defg-hij --transport chrome-node
|
||||
```
|
||||
|
||||
将 Chrome 的麦克风和扬声器音频通过本地 OpenClaw 音频桥进行路由。如果未安装 `BlackHole 2ch`,加入操作会以设置错误失败,而不是在没有音频路径的情况下静默加入。
|
||||
通过本地 OpenClaw 音频桥接来路由 Chrome 的麦克风和扬声器音频。如果未安装 `BlackHole 2ch`,加入操作会以设置错误失败,而不是在没有音频路径的情况下静默加入。
|
||||
|
||||
### Twilio
|
||||
|
||||
Twilio 传输方式是委托给 Voice Call 插件的严格拨号方案。它不会解析 Meet 页面中的电话号码。
|
||||
Twilio 传输方式是一个严格的拨号计划,并委托给 Voice Call 插件。它不会从 Meet 页面中解析电话号码。
|
||||
|
||||
```bash
|
||||
openclaw googlemeet join https://meet.google.com/abc-defg-hij \
|
||||
@ -233,7 +235,7 @@ openclaw googlemeet join https://meet.google.com/abc-defg-hij \
|
||||
--pin 123456
|
||||
```
|
||||
|
||||
当会议需要自定义序列时,使用 `--dtmf-sequence`:
|
||||
如果会议需要自定义序列,请使用 `--dtmf-sequence`:
|
||||
|
||||
```bash
|
||||
openclaw googlemeet join https://meet.google.com/abc-defg-hij \
|
||||
@ -252,14 +254,13 @@ openclaw googlemeet auth login --json
|
||||
|
||||
该命令会打印一个包含刷新令牌的 `oauth` 配置块。它使用 PKCE、位于 `http://localhost:8085/oauth2callback` 的 localhost 回调,以及通过 `--manual` 进行的手动复制/粘贴流程。
|
||||
|
||||
以下环境变量可作为回退值使用:
|
||||
以下环境变量可作为后备:
|
||||
|
||||
- `OPENCLAW_GOOGLE_MEET_CLIENT_ID` 或 `GOOGLE_MEET_CLIENT_ID`
|
||||
- `OPENCLAW_GOOGLE_MEET_CLIENT_SECRET` 或 `GOOGLE_MEET_CLIENT_SECRET`
|
||||
- `OPENCLAW_GOOGLE_MEET_REFRESH_TOKEN` 或 `GOOGLE_MEET_REFRESH_TOKEN`
|
||||
- `OPENCLAW_GOOGLE_MEET_ACCESS_TOKEN` 或 `GOOGLE_MEET_ACCESS_TOKEN`
|
||||
- `OPENCLAW_GOOGLE_MEET_ACCESS_TOKEN_EXPIRES_AT` 或
|
||||
`GOOGLE_MEET_ACCESS_TOKEN_EXPIRES_AT`
|
||||
- `OPENCLAW_GOOGLE_MEET_ACCESS_TOKEN_EXPIRES_AT` 或 `GOOGLE_MEET_ACCESS_TOKEN_EXPIRES_AT`
|
||||
- `OPENCLAW_GOOGLE_MEET_DEFAULT_MEETING` 或 `GOOGLE_MEET_DEFAULT_MEETING`
|
||||
- `OPENCLAW_GOOGLE_MEET_PREVIEW_ACK` 或 `GOOGLE_MEET_PREVIEW_ACK`
|
||||
|
||||
@ -269,17 +270,17 @@ openclaw googlemeet auth login --json
|
||||
openclaw googlemeet resolve-space --meeting https://meet.google.com/abc-defg-hij
|
||||
```
|
||||
|
||||
在进行媒体工作前运行预检:
|
||||
在进行媒体工作之前运行预检:
|
||||
|
||||
```bash
|
||||
openclaw googlemeet preflight --meeting https://meet.google.com/abc-defg-hij
|
||||
```
|
||||
|
||||
只有在确认你的 Cloud 项目、OAuth 主体以及会议参与者都已加入 Google Workspace Developer Preview Program 的 Meet media APIs 预览后,才设置 `preview.enrollmentAcknowledged: true`。
|
||||
只有在确认你的 Cloud 项目、OAuth 主体以及会议参与者都已加入 Meet media API 的 Google Workspace Developer Preview Program 后,才设置 `preview.enrollmentAcknowledged: true`。
|
||||
|
||||
## 配置
|
||||
|
||||
常见的 Chrome 实时路径只需要启用插件、安装 BlackHole、SoX,以及一个 OpenAI 密钥:
|
||||
常见的 Chrome realtime 路径只需要启用插件、BlackHole、SoX 和一个 OpenAI 密钥:
|
||||
|
||||
```bash
|
||||
brew install blackhole-2ch sox
|
||||
@ -305,7 +306,7 @@ export OPENAI_API_KEY=sk-...
|
||||
|
||||
- `defaultTransport: "chrome"`
|
||||
- `defaultMode: "realtime"`
|
||||
- `chromeNode.node`:`chrome-node` 的可选节点 ID/名称/IP
|
||||
- `chromeNode.node`:`chrome-node` 的可选节点 id/名称/IP
|
||||
- `chrome.audioBackend: "blackhole-2ch"`
|
||||
- `chrome.audioInputCommand`:将 8 kHz G.711 mu-law 音频写入 stdout 的 SoX `rec` 命令
|
||||
- `chrome.audioOutputCommand`:从 stdin 读取 8 kHz G.711 mu-law 音频的 SoX `play` 命令
|
||||
@ -332,7 +333,7 @@ export OPENAI_API_KEY=sk-...
|
||||
}
|
||||
```
|
||||
|
||||
仅 Twilio 配置:
|
||||
仅用于 Twilio 的配置:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -360,36 +361,36 @@ export OPENAI_API_KEY=sk-...
|
||||
}
|
||||
```
|
||||
|
||||
当 Chrome 运行在 Gateway 网关主机上时,使用 `transport: "chrome"`。当 Chrome 运行在已配对节点(例如 Parallels VM)上时,使用 `transport: "chrome-node"`。在这两种情况下,实时模型和 `openclaw_agent_consult` 都运行在 Gateway 网关主机上,因此模型凭证会保留在那里。
|
||||
当 Chrome 运行在 Gateway 网关主机上时,使用 `transport: "chrome"`。当 Chrome 运行在已配对节点(如 Parallels VM)上时,使用 `transport: "chrome-node"`。在这两种情况下,realtime 模型和 `openclaw_agent_consult` 都运行在 Gateway 网关主机上,因此模型凭证会保留在那里。
|
||||
|
||||
使用 `action: "status"` 列出活动会话或检查某个会话 ID。使用 `action: "leave"` 将某个会话标记为已结束。
|
||||
使用 `action: "status"` 列出活动会话或检查某个会话 ID。使用 `action: "leave"` 将会话标记为已结束。
|
||||
|
||||
## 实时智能体咨询
|
||||
|
||||
Chrome 实时模式针对实时语音循环进行了优化。实时语音提供商会听取会议音频,并通过已配置的音频桥发声。当实时模型需要更深入的推理、当前信息或常规 OpenClaw 工具时,它可以调用 `openclaw_agent_consult`。
|
||||
Chrome realtime 模式针对实时语音循环进行了优化。实时语音提供商会听取会议音频,并通过已配置的音频桥接进行发声。当实时模型需要更深入的推理、最新信息或常规 OpenClaw 工具时,它可以调用 `openclaw_agent_consult`。
|
||||
|
||||
咨询工具会在后台运行常规 OpenClaw 智能体,并带上最近会议转录的上下文,随后向实时语音会话返回简明的口语回答。然后语音模型可以将该回答再说回会议中。
|
||||
该咨询工具会在后台运行常规 OpenClaw 智能体,携带最近的会议转录上下文,并向实时语音会话返回简洁的口语答复。然后语音模型就可以将该答复说回会议中。
|
||||
|
||||
`realtime.toolPolicy` 控制咨询运行方式:
|
||||
`realtime.toolPolicy` 控制咨询运行:
|
||||
|
||||
- `safe-read-only`:暴露咨询工具,并将常规智能体限制为只能使用 `read`、`web_search`、`web_fetch`、`x_search`、`memory_search` 和 `memory_get`。
|
||||
- `owner`:暴露咨询工具,并让常规智能体使用正常的智能体工具策略。
|
||||
- `none`:不向实时语音模型暴露咨询工具。
|
||||
- `safe-read-only`:暴露咨询工具,并将常规智能体限制为使用 `read`、`web_search`、`web_fetch`、`x_search`、`memory_search` 和 `memory_get`。
|
||||
- `owner`:暴露咨询工具,并允许常规智能体使用正常的智能体工具策略。
|
||||
- `none`:不要向 realtime 语音模型暴露咨询工具。
|
||||
|
||||
咨询会话键按每个 Meet 会话进行作用域划分,因此在同一场会议期间,后续的咨询调用可以复用先前的咨询上下文。
|
||||
咨询会话键按每个 Meet 会话进行作用域隔离,因此在同一场会议期间,后续咨询调用可以复用先前的咨询上下文。
|
||||
|
||||
## 说明
|
||||
|
||||
Google Meet 的官方媒体 API 偏向接收,因此要在 Meet 通话中发言,仍然需要一个参与者路径。该插件将这一边界保持为可见状态:Chrome 负责浏览器参与和本地音频路由;Twilio 负责电话拨入参与。
|
||||
Google Meet 的官方媒体 API 是面向接收的,因此要在 Meet 通话中发声,仍然需要一个参与者路径。该插件会保持这条边界清晰可见:Chrome 负责浏览器参与和本地音频路由;Twilio 负责电话拨入参与。
|
||||
|
||||
Chrome 实时模式需要以下两者之一:
|
||||
Chrome realtime 模式需要以下两者之一:
|
||||
|
||||
- `chrome.audioInputCommand` 加 `chrome.audioOutputCommand`:OpenClaw 拥有实时模型桥,并在这些命令与所选实时语音提供商之间传输 8 kHz G.711 mu-law 音频。
|
||||
- `chrome.audioBridgeCommand`:一个外部桥接命令拥有整个本地音频路径,并且必须在启动或验证其守护进程后退出。
|
||||
- `chrome.audioInputCommand` 加 `chrome.audioOutputCommand`:OpenClaw 拥有 realtime 模型桥接,并在这些命令与所选 realtime 语音提供商之间传输 8 kHz G.711 mu-law 音频。
|
||||
- `chrome.audioBridgeCommand`:一个外部桥接命令拥有完整的本地音频路径,并且必须在启动或验证其守护进程后退出。
|
||||
|
||||
为了获得干净的双工音频,请将 Meet 输出和 Meet 麦克风通过独立的虚拟设备或类似 Loopback 的虚拟设备图进行路由。单个共享的 BlackHole 设备可能会将其他参与者的声音回声回通话中。
|
||||
为了获得干净的双工音频,请将 Meet 输出和 Meet 麦克风分别路由到独立的虚拟设备,或使用类似 Loopback 的虚拟设备图。单个共享的 BlackHole 设备可能会将其他参与者的声音回送到通话中。
|
||||
|
||||
`googlemeet leave` 会停止用于 Chrome 会话的命令对实时音频桥。对于通过 Voice Call 插件委托的 Twilio 会话,它还会挂断底层语音通话。
|
||||
`googlemeet leave` 会停止用于 Chrome 会话的命令对 realtime 音频桥接。对于通过 Voice Call 插件委派的 Twilio 会话,它也会挂断底层语音通话。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -1,61 +1,62 @@
|
||||
---
|
||||
read_when:
|
||||
- 查找公开发布渠道定义
|
||||
- 查找版本命名和发布节奏
|
||||
- 正在查找公开发布渠道定义
|
||||
- 正在查找版本命名和发布节奏
|
||||
summary: 公开发布渠道、版本命名和发布节奏
|
||||
title: 发布策略
|
||||
x-i18n:
|
||||
generated_at: "2026-04-24T05:03:01Z"
|
||||
generated_at: "2026-04-24T06:43:47Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 32c6d904e21f6d4150cf061ae27594bc2364f0927c48388362b16d8bf97491dc
|
||||
source_hash: 2cba6cd02c6fb2380abd8d46e10567af2f96c7c6e45236689d69289348b829ce
|
||||
source_path: reference/RELEASING.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 有三个公开发布渠道:
|
||||
|
||||
- stable:带标签的发布版本,默认发布到 npm `beta`,或在明确要求时发布到 npm `latest`
|
||||
- stable:带标签的发布版本,默认发布到 npm `beta`,或在明确指定时发布到 npm `latest`
|
||||
- beta:预发布标签,发布到 npm `beta`
|
||||
- dev:`main` 的持续最新版本
|
||||
- dev:`main` 的最新移动头部版本
|
||||
|
||||
## 版本命名
|
||||
|
||||
- Stable 发布版本:`YYYY.M.D`
|
||||
- 稳定版发布版本:`YYYY.M.D`
|
||||
- Git 标签:`vYYYY.M.D`
|
||||
- Stable 修正版发布版本:`YYYY.M.D-N`
|
||||
- 稳定版修正发布版本:`YYYY.M.D-N`
|
||||
- Git 标签:`vYYYY.M.D-N`
|
||||
- Beta 预发布版本:`YYYY.M.D-beta.N`
|
||||
- Git 标签:`vYYYY.M.D-beta.N`
|
||||
- 月和日不要补零
|
||||
- `latest` 表示当前已提升为正式版的 stable npm 发布版本
|
||||
- `latest` 表示当前已提升为正式的稳定 npm 发布版本
|
||||
- `beta` 表示当前 beta 安装目标
|
||||
- Stable 和 stable 修正版发布默认发布到 npm `beta`;发布操作人员可以显式指定目标为 `latest`,或者稍后再将经过验证的 beta 构建提升过去
|
||||
- 每个 stable OpenClaw 发布都会同时交付 npm 包和 macOS 应用;
|
||||
beta 发布通常会先验证并发布 npm/package 路径,而 mac 应用的构建/签名/公证默认保留给 stable,除非另有明确要求
|
||||
- 稳定版和稳定版修正发布默认发布到 npm `beta`;发布操作人员可以明确指定目标为 `latest`,或者稍后再提升经过验证的 beta 构建
|
||||
- 每个稳定版 OpenClaw 发布都会同时交付 npm 包和 macOS 应用;
|
||||
beta 发布通常会先验证并发布 npm/package 路径,而 mac 应用的构建/签名/公证除非明确要求,否则保留给稳定版
|
||||
|
||||
## 发布节奏
|
||||
|
||||
- 发布采用 beta 优先
|
||||
- 只有在最新 beta 验证通过后,才会跟进 stable
|
||||
- 发布先走 beta
|
||||
- 只有在最新 beta 验证通过后,才会跟进稳定版
|
||||
- 维护者通常会从当前 `main` 创建 `release/YYYY.M.D` 分支来切发布,
|
||||
这样发布验证和修复就不会阻塞 `main` 上的新开发
|
||||
- 如果某个 beta 标签已经推送或发布后还需要修复,维护者会切下一个
|
||||
- 如果某个 beta 标签已经推送或发布后需要修复,维护者会切下一个
|
||||
`-beta.N` 标签,而不是删除或重建旧的 beta 标签
|
||||
- 详细的发布流程、审批、凭证和恢复说明仅对维护者开放
|
||||
|
||||
## 发布预检
|
||||
## 发布前检查
|
||||
|
||||
- 在发布预检前运行 `pnpm check:test-types`,这样测试 TypeScript 也能继续
|
||||
被覆盖,而不只是依赖更快的本地 `pnpm check` 检查
|
||||
- 在发布预检前运行 `pnpm check:architecture`,这样更广泛的导入环和架构
|
||||
边界检查也会通过,而不是只依赖更快的本地检查
|
||||
- 在 `pnpm release:check` 之前运行 `pnpm build && pnpm ui:build`,这样打包
|
||||
验证步骤所需的 `dist/*` 发布产物和 Control UI bundle 才会存在
|
||||
- 每次带标签发布前都要运行 `pnpm release:check`
|
||||
- 在发布前检查前运行 `pnpm check:test-types`,这样测试 TypeScript 仍会被覆盖,
|
||||
不会遗漏在更快的本地 `pnpm check` 检查之外
|
||||
- 在发布前检查前运行 `pnpm check:architecture`,这样更广泛的导入循环和架构边界检查会保持绿色,
|
||||
不会遗漏在更快的本地检查之外
|
||||
- 在 `pnpm release:check` 之前运行 `pnpm build && pnpm ui:build`,这样预期的
|
||||
`dist/*` 发布产物和 Control UI 打包结果会存在,供 pack
|
||||
验证步骤使用
|
||||
- 每次带标签发布前都运行 `pnpm release:check`
|
||||
- 发布检查现在在单独的手动工作流中运行:
|
||||
`OpenClaw Release Checks`
|
||||
- `OpenClaw Release Checks` 还会在发布审批前运行 QA Lab mock 对齐检查,以及实时
|
||||
- `OpenClaw Release Checks` 还会在发布审批前运行 QA Lab 模拟一致性检查,以及实时的
|
||||
Matrix 和 Telegram QA 通道。实时通道使用
|
||||
`qa-live-shared` 环境;Telegram 还会使用 Convex CI 凭证租约。
|
||||
- 跨操作系统的安装和升级运行时验证由私有调用方工作流
|
||||
@ -63,129 +64,135 @@ OpenClaw 有三个公开发布渠道:
|
||||
发起,它会调用可复用的公开工作流
|
||||
`.github/workflows/openclaw-cross-os-release-checks-reusable.yml`
|
||||
- 这种拆分是有意为之:让真正的 npm 发布路径保持简短、
|
||||
可预测且聚焦于产物,而把较慢的实时检查放在单独通道中,
|
||||
以免拖慢或阻塞发布
|
||||
可预测,并且聚焦产物;同时把较慢的实时检查放在它们自己的通道中,
|
||||
这样它们就不会拖慢或阻塞发布
|
||||
- 发布检查必须从 `main` 工作流引用或
|
||||
`release/YYYY.M.D` 工作流引用发起,这样工作流逻辑和密钥才能保持受控
|
||||
- 该工作流接受现有发布标签,或当前完整的
|
||||
40 字符工作流分支提交 SHA
|
||||
- 在提交 SHA 模式下,它只接受当前工作流分支 HEAD;如果要验证更早的发布提交,
|
||||
请使用发布标签
|
||||
- `OpenClaw NPM Release` 的仅验证预检也接受当前完整的
|
||||
40 字符工作流分支提交 SHA,而不要求已有推送的标签
|
||||
- 该工作流接受已有的发布标签,或当前工作流分支完整的
|
||||
40 字符提交 SHA
|
||||
- 在提交 SHA 模式下,它只接受当前工作流分支的 HEAD;较旧的发布提交请使用
|
||||
发布标签
|
||||
- `OpenClaw NPM Release` 的仅验证前检查也接受当前工作流分支完整的
|
||||
40 字符提交 SHA,而不要求已推送标签
|
||||
- 该 SHA 路径仅用于验证,不能提升为真实发布
|
||||
- 在 SHA 模式下,工作流仅为包元数据检查临时构造 `v<package.json version>`;
|
||||
真正发布仍然需要真实的发布标签
|
||||
- 这两个工作流都将真实发布和提升路径保留在 GitHub 托管运行器上,
|
||||
而非变更性的验证路径则可以使用更大的
|
||||
Blacksmith Linux 运行器
|
||||
- 在 SHA 模式下,该工作流只为包元数据检查合成
|
||||
`v<package.json version>`;真实发布仍然需要真实的发布标签
|
||||
- 这两个工作流都将真实发布和提升路径保留在 GitHub 托管的
|
||||
runner 上,而非变更型验证路径则可以使用更大的
|
||||
Blacksmith Linux runner
|
||||
- 该工作流会运行
|
||||
`OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache`
|
||||
,并使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 两个工作流密钥
|
||||
- npm 发布预检不再等待单独的发布检查通道
|
||||
- 审批前运行
|
||||
并使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 两个工作流密钥
|
||||
- npm 发布前检查不再等待单独的发布检查通道
|
||||
- 在审批前运行
|
||||
`RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts`
|
||||
(或对应的 beta/修正标签)
|
||||
- npm 发布后,运行
|
||||
`node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`
|
||||
(或对应的 beta/修正版本),在全新的临时前缀中验证已发布注册表的安装路径
|
||||
- beta 发布后,运行 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N pnpm test:docker:npm-telegram-live`
|
||||
,以针对已发布的 npm 包验证已安装包的新手引导、Telegram 设置,以及真实 Telegram E2E。
|
||||
- 维护者发布自动化现在采用“先预检、后提升”:
|
||||
- 真实 npm 发布必须通过成功的 npm `preflight_run_id`
|
||||
- 真实 npm 发布必须从与成功预检运行相同的 `main` 或
|
||||
(或对应的 beta/修正版本),在全新的临时前缀中验证已发布的注册表
|
||||
安装路径
|
||||
- beta 发布后,运行 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-live`
|
||||
以验证已安装包的新手引导、Telegram 设置,以及针对已发布 npm 包的真实 Telegram 端到端流程,
|
||||
并使用共享租赁的 Telegram 凭证池。本地维护者的一次性检查可以省略 Convex 变量,
|
||||
直接传入三个 `OPENCLAW_QA_TELEGRAM_*` 环境变量凭证。
|
||||
- 维护者也可以通过 GitHub Actions 中手动触发的
|
||||
`NPM Telegram Beta E2E` 工作流运行同样的发布后检查。它有意只支持手动触发,
|
||||
不会在每次合并时运行。
|
||||
- 维护者发布自动化现在采用“先前检查后提升”:
|
||||
- 真正的 npm 发布必须通过成功的 npm `preflight_run_id`
|
||||
- 真正的 npm 发布必须从与成功前检查运行相同的 `main` 或
|
||||
`release/YYYY.M.D` 分支发起
|
||||
- stable npm 发布默认指向 `beta`
|
||||
- stable npm 发布可以通过工作流输入显式指定目标为 `latest`
|
||||
- 稳定版 npm 发布默认目标为 `beta`
|
||||
- 稳定版 npm 发布可以通过工作流输入明确指定目标为 `latest`
|
||||
- 基于令牌的 npm dist-tag 变更现在位于
|
||||
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
|
||||
中,以提高安全性,因为 `npm dist-tag add` 仍需要 `NPM_TOKEN`,而公开仓库
|
||||
仅保留基于 OIDC 的发布
|
||||
中,以提高安全性,因为 `npm dist-tag add` 仍然需要 `NPM_TOKEN`,而公开仓库
|
||||
保持仅使用 OIDC 发布
|
||||
- 公开的 `macOS Release` 仅用于验证
|
||||
- 真实的私有 mac 发布必须通过成功的私有 mac
|
||||
- 真正的私有 mac 发布必须通过成功的私有 mac
|
||||
`preflight_run_id` 和 `validate_run_id`
|
||||
- 真正发布路径会提升已准备好的产物,而不是再次重新构建
|
||||
- 对于像 `YYYY.M.D-N` 这样的 stable 修正版发布,发布后验证器
|
||||
还会检查从 `YYYY.M.D` 升级到 `YYYY.M.D-N` 的同一临时前缀升级路径,
|
||||
这样发布修正就不会悄悄让旧的全局安装继续停留在基础 stable 载荷上
|
||||
- npm 发布预检默认采用失败即阻止的策略,除非 tarball 同时包含
|
||||
`dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 内容,
|
||||
这样我们就不会再次发布一个空的浏览器仪表盘
|
||||
- 发布后验证还会检查已发布的注册表安装是否在根 `dist/*`
|
||||
布局下包含非空的内置插件运行时依赖。若某个发布带着缺失或空的内置插件
|
||||
依赖内容发出,发布后验证器会判定失败,并且不能被提升到 `latest`。
|
||||
- 真正的发布路径会提升已准备好的产物,而不是再次重新构建
|
||||
- 对于像 `YYYY.M.D-N` 这样的稳定版修正发布,发布后验证器
|
||||
还会检查从 `YYYY.M.D` 到 `YYYY.M.D-N` 的相同临时前缀升级路径,
|
||||
这样发布修正就不会悄悄让旧的全局安装仍停留在基础稳定版载荷上
|
||||
- npm 发布前检查会以默认拒绝方式失败,除非 tarball 同时包含
|
||||
`dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 载荷,
|
||||
这样我们就不会再次发布一个空的浏览器仪表板
|
||||
- 发布后验证还会检查已发布的注册表安装中,根级 `dist/*`
|
||||
布局下是否包含非空的内置插件运行时依赖。若某个发布带有缺失或为空的内置插件
|
||||
依赖载荷,则发布后验证器会失败,且该版本不能被提升
|
||||
到 `latest`。
|
||||
- `pnpm test:install:smoke` 还会对候选更新 tarball 的 npm pack `unpackedSize` 预算进行强制检查,
|
||||
这样安装器 e2e 就能在发布路径之前捕获意外的打包膨胀
|
||||
- 如果发布工作涉及 CI 规划、扩展计时清单或扩展测试矩阵,
|
||||
请在审批前重新生成并审查由规划器负责的
|
||||
`checks-node-extensions` 工作流矩阵输出,来源于 `.github/workflows/ci.yml`,
|
||||
这样安装器端到端流程就能在发布路径之前捕获意外的打包膨胀
|
||||
- 如果发布工作涉及 CI 规划、扩展计时清单或
|
||||
扩展测试矩阵,请在审批前重新生成并审查由规划器负责的
|
||||
`.github/workflows/ci.yml` 中 `checks-node-extensions` 工作流矩阵输出,
|
||||
这样发布说明就不会描述过时的 CI 布局
|
||||
- Stable macOS 发布就绪还包括更新器相关界面:
|
||||
- 稳定版 macOS 发布就绪还包括更新器相关界面:
|
||||
- GitHub 发布最终必须包含打包好的 `.zip`、`.dmg` 和 `.dSYM.zip`
|
||||
- 发布后,`main` 上的 `appcast.xml` 必须指向新的 stable zip
|
||||
- 打包应用必须继续使用非调试 bundle id、非空的 Sparkle feed
|
||||
URL,以及不低于该发布版本规范 Sparkle 构建下限的 `CFBundleVersion`
|
||||
- 发布后,`main` 上的 `appcast.xml` 必须指向新的稳定版 zip
|
||||
- 打包后的应用必须保持非调试 bundle id、非空的 Sparkle feed
|
||||
URL,并且 `CFBundleVersion` 至少达到该发布版本对应的规范 Sparkle 构建下限
|
||||
|
||||
## NPM 工作流输入
|
||||
|
||||
`OpenClaw NPM Release` 接受这些由操作人员控制的输入:
|
||||
`OpenClaw NPM Release` 接受以下由操作人员控制的输入:
|
||||
|
||||
- `tag`:必填的发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或
|
||||
- `tag`:必填发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或
|
||||
`v2026.4.2-beta.1`;当 `preflight_only=true` 时,也可以是当前
|
||||
完整的 40 字符工作流分支提交 SHA,用于仅验证的预检
|
||||
- `preflight_only`:`true` 表示仅验证/构建/打包,`false` 表示
|
||||
工作流分支完整的 40 字符提交 SHA,用于仅验证的前检查
|
||||
- `preflight_only`:`true` 表示只做验证/构建/打包,`false` 表示走
|
||||
真实发布路径
|
||||
- `preflight_run_id`:真实发布路径下必填,这样工作流就能复用成功预检运行中
|
||||
- `preflight_run_id`:真实发布路径必填,这样工作流才能复用成功前检查运行中
|
||||
准备好的 tarball
|
||||
- `npm_dist_tag`:发布路径的 npm 目标标签;默认值为 `beta`
|
||||
- `npm_dist_tag`:发布路径的 npm 目标标签;默认是 `beta`
|
||||
|
||||
`OpenClaw Release Checks` 接受这些由操作人员控制的输入:
|
||||
`OpenClaw Release Checks` 接受以下由操作人员控制的输入:
|
||||
|
||||
- `ref`:现有发布标签,或从 `main` 发起时要验证的当前完整
|
||||
40 字符 `main` 提交 SHA;如果从发布分支发起,则使用现有发布标签或
|
||||
当前完整的 40 字符发布分支提交 SHA
|
||||
- `ref`:已有发布标签,或从 `main` 发起时当前完整的 40 字符 `main` 提交
|
||||
SHA;若从发布分支发起,请使用已有发布标签或当前完整的 40 字符
|
||||
发布分支提交 SHA
|
||||
|
||||
规则:
|
||||
|
||||
- Stable 和修正标签可以发布到 `beta` 或 `latest`
|
||||
- 稳定版和修正标签可以发布到 `beta` 或 `latest`
|
||||
- Beta 预发布标签只能发布到 `beta`
|
||||
- 对于 `OpenClaw NPM Release`,仅当
|
||||
- 对于 `OpenClaw NPM Release`,只有在
|
||||
`preflight_only=true` 时才允许输入完整提交 SHA
|
||||
- `OpenClaw Release Checks` 始终仅用于验证,并且也接受
|
||||
- `OpenClaw Release Checks` 始终只用于验证,并且也接受
|
||||
当前工作流分支提交 SHA
|
||||
- 发布检查的提交 SHA 模式还要求必须是当前工作流分支 HEAD
|
||||
- 真实发布路径必须使用预检时使用的同一个 `npm_dist_tag`;
|
||||
- 发布检查的提交 SHA 模式还要求必须是当前工作流分支的 HEAD
|
||||
- 真正的发布路径必须使用与前检查相同的 `npm_dist_tag`;
|
||||
工作流会在继续发布前验证该元数据
|
||||
|
||||
## Stable npm 发布顺序
|
||||
## 稳定版 npm 发布顺序
|
||||
|
||||
在切 stable npm 发布时:
|
||||
切稳定版 npm 发布时:
|
||||
|
||||
1. 运行 `OpenClaw NPM Release`,并设置 `preflight_only=true`
|
||||
- 在标签尚不存在时,你可以使用当前完整工作流分支提交
|
||||
SHA,对预检工作流做一次仅验证的干运行
|
||||
2. 对于正常的 beta 优先流程,选择 `npm_dist_tag=beta`;只有在你
|
||||
明确希望直接发布 stable 时才使用 `latest`
|
||||
3. 单独运行 `OpenClaw Release Checks`,使用相同标签,或者
|
||||
当前完整工作流分支提交 SHA,以便获得实时 prompt cache、
|
||||
QA Lab 对齐、Matrix 和 Telegram 覆盖
|
||||
- 这样刻意分开,是为了让实时覆盖保持可用,而不会再次把长时间运行或不稳定的检查
|
||||
耦合回发布工作流
|
||||
- 在标签尚不存在时,你可以使用当前完整的工作流分支提交
|
||||
SHA,对前检查工作流进行一次仅验证的演练
|
||||
2. 正常的先 beta 后正式流程请选择 `npm_dist_tag=beta`,只有在你明确想直接发布稳定版时
|
||||
才选择 `latest`
|
||||
3. 使用相同标签单独运行 `OpenClaw Release Checks`,或者在你希望获得实时 prompt cache、
|
||||
QA Lab 一致性、Matrix 和 Telegram 覆盖时,使用当前完整的工作流分支提交 SHA
|
||||
- 这一步故意单独分离,这样实时覆盖仍然可用,而不会把长时间运行或不稳定的检查
|
||||
重新耦合进发布工作流
|
||||
4. 保存成功的 `preflight_run_id`
|
||||
5. 再次运行 `OpenClaw NPM Release`,并设置 `preflight_only=false`,使用相同的
|
||||
`tag`、相同的 `npm_dist_tag`,以及保存下来的 `preflight_run_id`
|
||||
6. 如果该发布先落在 `beta`,使用私有工作流
|
||||
5. 再次运行 `OpenClaw NPM Release`,设置 `preflight_only=false`,并使用相同的
|
||||
`tag`、相同的 `npm_dist_tag` 以及保存下来的 `preflight_run_id`
|
||||
6. 如果该发布先落在 `beta`,请使用私有工作流
|
||||
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
|
||||
将该 stable 版本从 `beta` 提升到 `latest`
|
||||
7. 如果该发布是有意直接发布到 `latest`,并且希望 `beta`
|
||||
立即跟随同一个 stable 构建,使用同一个私有工作流将这两个 dist-tag
|
||||
都指向该 stable 版本,或者让其计划任务式的自愈同步稍后再移动 `beta`
|
||||
将该稳定版从 `beta` 提升到 `latest`
|
||||
7. 如果该发布有意直接发布到 `latest`,并且希望 `beta`
|
||||
立即跟随同一个稳定构建,请使用同一个私有工作流将两个 dist-tag
|
||||
都指向该稳定版本,或者让它的定时自愈同步稍后再移动 `beta`
|
||||
|
||||
dist-tag 变更位于私有仓库中以提高安全性,因为它仍然
|
||||
需要 `NPM_TOKEN`,而公开仓库仅保留基于 OIDC 的发布。
|
||||
出于安全原因,dist-tag 变更位于私有仓库中,因为它仍然
|
||||
需要 `NPM_TOKEN`,而公开仓库保持仅使用 OIDC 发布。
|
||||
|
||||
这样可以让直接发布路径和 beta 优先提升路径都保持文档化,
|
||||
并且对操作人员可见。
|
||||
这样既保留了直接发布路径,也保留了先 beta 后提升路径,并且两者都已文档化、
|
||||
对操作人员可见。
|
||||
|
||||
## 公开参考
|
||||
|
||||
@ -198,7 +205,7 @@ dist-tag 变更位于私有仓库中以提高安全性,因为它仍然
|
||||
|
||||
维护者会使用私有发布文档
|
||||
[`openclaw/maintainers/release/README.md`](https://github.com/openclaw/maintainers/blob/main/release/README.md)
|
||||
作为实际运行手册。
|
||||
作为实际操作手册。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user