chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
9fff8ff68c
commit
b5919cf475
172
docs/zh-CN/ci.md
172
docs/zh-CN/ci.md
File diff suppressed because one or more lines are too long
@ -3,47 +3,47 @@ read_when:
|
||||
- 在本地或 CI 中运行测试
|
||||
- 为模型 / 提供商缺陷添加回归测试
|
||||
- 调试 Gateway 网关 + 智能体行为
|
||||
summary: 测试工具包:单元 / e2e / 实时测试套件、Docker 运行器,以及每类测试涵盖的内容
|
||||
summary: 测试工具包:单元 / e2e / 实时测试套件、Docker 运行器,以及各项测试的覆盖范围
|
||||
title: 测试
|
||||
x-i18n:
|
||||
generated_at: "2026-04-27T17:44:01Z"
|
||||
generated_at: "2026-04-27T19:38:38Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 37dbd2dd294a4a97850cd9a3ff13bb680e612380115fc660d0b8e0d8dbf1c5e0
|
||||
source_hash: 142d45ff5b05c38c6a8220752ac683b9b0f4492eaa3f41dc9507f1d0d885c364
|
||||
source_path: help/testing.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 有三个 Vitest 测试套件(单元 / 集成、e2e、实时)和一小组 Docker 运行器。本文档是一份“我们如何测试”的指南:
|
||||
OpenClaw 有三个 Vitest 测试套件(单元 / 集成、e2e、实时)以及一小组 Docker 运行器。本文档是一份“我们如何测试”的指南:
|
||||
|
||||
- 每个测试套件涵盖什么内容(以及它刻意**不**涵盖什么)。
|
||||
- 常见工作流(本地、推送前、调试)应运行哪些命令。
|
||||
- 各个测试套件覆盖什么(以及它们刻意 _不_ 覆盖什么)。
|
||||
- 常见工作流应运行哪些命令(本地、推送前、调试)。
|
||||
- 实时测试如何发现凭证并选择模型 / 提供商。
|
||||
- 如何为真实世界中的模型 / 提供商问题添加回归测试。
|
||||
|
||||
<Note>
|
||||
**QA stack(qa-lab、qa-channel、实时传输通道)**另有单独文档:
|
||||
**QA 栈(qa-lab、qa-channel、实时传输协议通道)** 另有单独文档说明:
|
||||
|
||||
- [QA overview](/zh-CN/concepts/qa-e2e-automation) — 架构、命令入口、场景编写。
|
||||
- [Matrix QA](/zh-CN/concepts/qa-matrix) — `pnpm openclaw qa matrix` 的参考文档。
|
||||
- [QA channel](/zh-CN/channels/qa-channel) — 仓库场景使用的合成传输插件。
|
||||
- [QA overview](/zh-CN/concepts/qa-e2e-automation) —— 架构、命令界面、场景编写。
|
||||
- [Matrix QA](/zh-CN/concepts/qa-matrix) —— `pnpm openclaw qa matrix` 的参考文档。
|
||||
- [QA channel](/zh-CN/channels/qa-channel) —— 仓库支持场景所使用的合成传输协议插件。
|
||||
|
||||
本页介绍如何运行常规测试套件以及 Docker / Parallels 运行器。下面的 QA 专用运行器部分([QA 专用运行器](#qa-specific-runners))列出了具体的 `qa` 调用方式,并回指以上参考文档。
|
||||
本页介绍如何运行常规测试套件以及 Docker / Parallels 运行器。下面的 QA 专用运行器部分([QA-specific runners](#qa-specific-runners))列出了具体的 `qa` 调用方式,并回指上述参考文档。
|
||||
</Note>
|
||||
|
||||
## 快速开始
|
||||
|
||||
大多数时候:
|
||||
|
||||
- 完整门禁(推送前的预期要求):`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`
|
||||
- 当你在迭代单个失败用例时,优先使用定向运行。
|
||||
- 完整门禁(预期在推送前运行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test`
|
||||
- 在配置较高的机器上更快地运行本地完整测试套件:`pnpm test:max`
|
||||
- 直接使用 Vitest 监听循环:`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`
|
||||
- 基于 Linux VM 的 QA 通道:`pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline`
|
||||
|
||||
当你修改了测试,或者想获得更多信心时:
|
||||
当你修改了测试或想获得更多信心时:
|
||||
|
||||
- 覆盖率门禁:`pnpm test:coverage`
|
||||
- E2E 测试套件:`pnpm test:e2e`
|
||||
@ -53,60 +53,123 @@ OpenClaw 有三个 Vitest 测试套件(单元 / 集成、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` 及其定时 / 发布调用工作流中。
|
||||
- 现在每个选中的模型都会运行一次文本轮次和一个小型的类文件读取探测。元数据声明支持 `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` 和其
|
||||
scheduled / release 调用方中。
|
||||
- 原生 Codex 绑定聊天冒烟测试:`pnpm test:docker:live-codex-bind`
|
||||
- 在 Docker 中针对 Codex app-server 路径运行实时测试通道,绑定一个合成 Slack 私信 `/codex bind`,执行 `/codex fast` 和 `/codex permissions`,然后验证普通回复和图像附件都通过原生插件绑定路由,而不是 ACP。
|
||||
- 在 Codex app-server 路径上运行一个 Docker 实时通道,使用 `/codex bind`
|
||||
绑定一个合成 Slack 私信,会执行 `/codex fast` 和
|
||||
`/codex permissions`,然后验证普通回复和图像附件会通过原生插件绑定路由,
|
||||
而不是 ACP。
|
||||
- Codex app-server harness 冒烟测试:`pnpm test:docker:live-codex-harness`
|
||||
- 通过插件拥有的 Codex app-server harness 运行 Gateway 网关智能体轮次,验证 `/codex status` 和 `/codex models`,并默认执行图像、cron MCP、子智能体和 Guardian 探测。排查其他 Codex app-server 故障时,可使用 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` 禁用子智能体探测。若只想聚焦子智能体检查,请禁用其他探测:`OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harness`。
|
||||
除非设置了 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`,否则该命令会在子智能体探测后退出。
|
||||
- 通过插件所属的 Codex app-server harness 运行 Gateway 网关智能体轮次,
|
||||
验证 `/codex status` 和 `/codex models`,并默认执行图像、
|
||||
cron MCP、sub-agent 和 Guardian 探测。若要在隔离其他 Codex
|
||||
app-server 故障时禁用 sub-agent 探测,可设置
|
||||
`OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0`。若要只做一次聚焦的
|
||||
sub-agent 检查,请禁用其他探测:
|
||||
`OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harness`。
|
||||
除非设置了 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`,
|
||||
否则它会在 sub-agent 探测后退出。
|
||||
- Crestodian 救援命令冒烟测试:`pnpm test:live:crestodian-rescue-channel`
|
||||
- 对消息渠道救援命令入口面的可选双重保险检查。它会执行 `/crestodian status`、排队一个持久化模型变更、回复 `/crestodian yes`,并验证审计 / 配置写入路径。
|
||||
- Crestodian 规划器 Docker 冒烟测试:`pnpm test:docker:crestodian-planner`
|
||||
- 在无配置容器中运行 Crestodian,并在 `PATH` 上放置一个假的 Claude CLI,验证模糊规划器回退会转换为带审计记录的类型化配置写入。
|
||||
- 针对消息渠道救援命令界面的可选双保险检查。它会执行 `/crestodian status`,
|
||||
排入一个持久模型变更,回复 `/crestodian yes`,并验证审计 / 配置写入路径。
|
||||
- Crestodian planner Docker 冒烟测试:`pnpm test:docker:crestodian-planner`
|
||||
- 在一个没有配置的容器中运行 Crestodian,并在 `PATH` 上提供一个假的 Claude CLI,
|
||||
验证模糊 planner 回退会转换为一条带审计的类型化配置写入。
|
||||
- Crestodian 首次运行 Docker 冒烟测试:`pnpm test:docker:crestodian-first-run`
|
||||
- 从空的 OpenClaw 状态目录启动,将裸 `openclaw` 路由到 Crestodian,应用 setup / model / agent / Discord 插件 + SecretRef 写入,验证配置,并检查审计条目。同一 Ring 0 设置路径也在 QA Lab 中由 `pnpm openclaw qa suite --scenario crestodian-ring-zero-setup` 覆盖。
|
||||
- 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`。
|
||||
- 从一个空的 OpenClaw 状态目录启动,将裸 `openclaw` 路由到
|
||||
Crestodian,应用 setup / model / agent / Discord 插件 + SecretRef 写入,
|
||||
验证配置,并检查审计条目。相同的 Ring 0 设置路径也在 QA Lab 中通过
|
||||
`pnpm openclaw qa suite --scenario crestodian-ring-zero-setup`
|
||||
得到覆盖。
|
||||
- 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`。
|
||||
|
||||
<Tip>
|
||||
当你只需要一个失败用例时,优先使用下面描述的 allowlist 环境变量来缩小实时测试范围。
|
||||
当你只需要一个失败用例时,优先通过下面描述的 allowlist 环境变量来缩小实时测试范围。
|
||||
</Tip>
|
||||
|
||||
## QA 专用运行器
|
||||
|
||||
当你需要 qa-lab 级别的真实环境时,这些命令与主测试套件并列存在:
|
||||
当你需要 qa-lab 级别的真实性时,这些命令与主测试套件并列使用:
|
||||
|
||||
CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,也可通过手动触发使用模拟提供商运行。`QA-Lab - All Lanes` 会在 `main` 上每晚运行,也可通过手动触发,以并行任务方式运行模拟 parity gate、实时 Matrix 通道、Convex 托管的实时 Telegram 通道和 Convex 托管的实时 Discord 通道。定时 QA 和发布检查会显式传递 Matrix `--profile fast`,而 Matrix CLI 和手动工作流输入的默认值仍是 `all`;手动触发可以将 `all` 分片为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作业。`OpenClaw Release Checks` 会在发布批准前运行 parity 以及快速 Matrix 和 Telegram 通道。
|
||||
CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,
|
||||
也可以通过手动派发、使用 mock 提供商来运行。`QA-Lab - All Lanes` 会在
|
||||
`main` 上每晚运行,也可以通过手动派发运行,包含 mock parity gate、实时 Matrix 通道、
|
||||
Convex 管理的实时 Telegram 通道以及 Convex 管理的实时 Discord 通道,
|
||||
这些都会作为并行作业执行。定时 QA 和发布检查会显式传递 Matrix `--profile fast`,
|
||||
而 Matrix CLI 和手动工作流输入的默认值仍然是 `all`;手动派发可以将 `all`
|
||||
拆分为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作业。
|
||||
`OpenClaw Release Checks` 会在发布批准前运行 parity,以及 fast Matrix 和 Telegram 通道。
|
||||
|
||||
- `pnpm openclaw qa suite`
|
||||
- 直接在主机上运行基于仓库的 QA 场景。
|
||||
- 默认会以隔离的 Gateway 网关工作进程并行运行多个已选场景。`qa-channel` 默认并发度为 4(受所选场景数量限制)。使用 `--concurrency <count>` 调整工作进程数量,或使用 `--concurrency 1` 切换回旧的串行通道。
|
||||
- 当任一场景失败时,以非零状态退出。如果你想要产物但不希望以失败退出码结束,请使用 `--allow-failures`。
|
||||
- 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。`aimock` 会启动一个本地 AIMock 支持的提供商服务器,用于实验性的夹具和协议模拟覆盖,但不会替代具备场景感知能力的 `mock-openai` 通道。
|
||||
- 直接在主机上运行仓库支持的 QA 场景。
|
||||
- 默认会以隔离的 Gateway 网关工作进程并行运行多个选定场景。`qa-channel`
|
||||
默认并发数为 4(受所选场景数量限制)。使用 `--concurrency <count>` 调整工作进程数量,
|
||||
或使用 `--concurrency 1` 运行旧式串行通道。
|
||||
- 任一场景失败时会以非零状态退出。若你希望保留工件但不以失败退出,可使用 `--allow-failures`。
|
||||
- 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。
|
||||
`aimock` 会启动一个本地 AIMock 支持的 provider 服务,用于实验性的
|
||||
固定装置和协议 mock 覆盖,而不会替代具备场景感知的 `mock-openai` 通道。
|
||||
- `pnpm openclaw qa suite --runner multipass`
|
||||
- 在一次性 Multipass Linux VM 中运行相同的 QA 套件。
|
||||
- 在一个一次性的 Multipass Linux VM 中运行相同的 QA 测试套件。
|
||||
- 保持与主机上 `qa suite` 相同的场景选择行为。
|
||||
- 复用与 `qa suite` 相同的提供商 / 模型选择标志。
|
||||
- 实时运行会转发适合访客机使用的受支持 QA 认证输入:基于环境变量的提供商密钥、QA 实时提供商配置路径,以及存在时的 `CODEX_HOME`。
|
||||
- 输出目录必须保留在仓库根目录下,以便访客机能够通过挂载的工作区回写。
|
||||
- 会将常规 QA 报告 + 摘要以及 Multipass 日志写入 `.artifacts/qa-e2e/...`。
|
||||
- 实时运行会转发适合宾客环境的受支持 QA 认证输入:
|
||||
基于环境变量的 provider 密钥、QA 实时 provider 配置路径,以及存在时的 `CODEX_HOME`。
|
||||
- 输出目录必须保留在仓库根目录下,以便宾客环境能够通过挂载的工作区回写内容。
|
||||
- 会将常规 QA 报告 + 摘要以及 Multipass 日志写入
|
||||
`.artifacts/qa-e2e/...`。
|
||||
- `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 运行同一打包安装通道。
|
||||
- 从当前检出构建一个 npm tarball,在 Docker 中全局安装它,运行非交互式 OpenAI API-key 新手引导,
|
||||
默认配置 Telegram,验证启用插件时会按需安装运行时依赖,运行 doctor,
|
||||
并针对一个 mock 的 OpenAI 端点运行一次本地智能体轮次。
|
||||
- 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可在 Discord 上运行相同的打包安装通道。
|
||||
- `pnpm test:docker:session-runtime-context`
|
||||
- 运行一个确定性的、基于已构建应用的 Docker 冒烟测试,用于嵌入式运行时上下文转录。它会验证隐藏的 OpenClaw 运行时上下文被保存为非显示的自定义消息,而不是泄漏到可见的用户轮次中;随后注入一个受影响的损坏会话 JSONL,并验证 `openclaw doctor --fix` 会将其重写到当前分支并生成备份。
|
||||
- 针对嵌入式运行时上下文 transcript 运行一个确定性的 built-app Docker 冒烟测试。
|
||||
它会验证隐藏的 OpenClaw 运行时上下文被持久化为一条非展示型自定义消息,
|
||||
而不是泄漏到可见的用户轮次中;随后会植入一个受影响的损坏 session JSONL,
|
||||
并验证 `openclaw doctor --fix` 会将其重写为当前活动分支,同时保留备份。
|
||||
- `pnpm test:docker:npm-telegram-live`
|
||||
- 在 Docker 中安装一个 OpenClaw 候选包,运行已安装包的新手引导,通过已安装的 CLI 配置 Telegram,然后复用实时 Telegram QA 通道,并将该已安装包作为 SUT Gateway 网关。
|
||||
- 默认使用 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`;设置 `OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` 或 `OPENCLAW_CURRENT_PACKAGE_TGZ` 可测试已解析的本地 tarball,而不是从注册表安装。
|
||||
- 使用与 `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` 环境和 Convex CI 凭证租约。
|
||||
- GitHub Actions 还提供 `Package Acceptance`,用于针对单个候选包进行旁路产品验证。它接受受信任的 ref、已发布的 npm 规范、带 SHA-256 的 HTTPS tarball URL,或来自另一个运行的 tarball 产物;然后将规范化后的 `openclaw-current.tgz` 上传为 `package-under-test`,再运行现有 Docker E2E 调度器,支持 smoke、package、product、full 或自定义通道配置。设置 `telegram_mode=mock-openai` 或 `live-frontier`,即可让 Telegram QA 工作流针对相同的 `package-under-test` 产物运行。
|
||||
- 在 Docker 中安装一个 OpenClaw 包候选版本,运行已安装包的新手引导,
|
||||
通过已安装的 CLI 配置 Telegram,然后复用实时 Telegram QA 通道,
|
||||
将该已安装包作为被测 Gateway 网关。
|
||||
- 默认使用 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`;设置
|
||||
`OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` 或
|
||||
`OPENCLAW_CURRENT_PACKAGE_TGZ`,即可测试一个解析后的本地 tarball,
|
||||
而不是从 registry 安装。
|
||||
- 使用与 `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` 环境和 Convex CI 凭证租约。
|
||||
- GitHub Actions 还提供 `Package Acceptance`,用于针对单个候选包进行额外产品验证。
|
||||
它接受一个受信任的 ref、已发布的 npm spec、带 SHA-256 的 HTTPS tarball URL,
|
||||
或来自其他运行的 tarball artifact;随后将标准化后的 `openclaw-current.tgz`
|
||||
作为 `package-under-test` 上传,并使用 smoke、package、product、full 或 custom
|
||||
通道配置运行现有的 Docker E2E 调度器。设置 `telegram_mode=mock-openai`
|
||||
或 `live-frontier`,可让 Telegram QA 工作流针对同一个 `package-under-test`
|
||||
artifact 运行。
|
||||
- 最新 beta 产品验证:
|
||||
|
||||
```bash
|
||||
@ -117,7 +180,7 @@ gh workflow run package-acceptance.yml --ref main \
|
||||
-f telegram_mode=mock-openai
|
||||
```
|
||||
|
||||
- 精确 tarball URL 验证需要摘要:
|
||||
- 精确的 tarball URL 验证需要摘要:
|
||||
|
||||
```bash
|
||||
gh workflow run package-acceptance.yml --ref main \
|
||||
@ -127,7 +190,7 @@ gh workflow run package-acceptance.yml --ref main \
|
||||
-f suite_profile=package
|
||||
```
|
||||
|
||||
- 产物验证会从另一个 Actions 运行中下载 tarball 产物:
|
||||
- Artifact 验证会从另一个 Actions 运行下载一个 tarball artifact:
|
||||
|
||||
```bash
|
||||
gh workflow run package-acceptance.yml --ref main \
|
||||
@ -138,58 +201,58 @@ gh workflow run package-acceptance.yml --ref main \
|
||||
```
|
||||
|
||||
- `pnpm test:docker:bundled-channel-deps`
|
||||
- 在 Docker 中打包并安装当前 OpenClaw 构建,使用已配置的 OpenAI 启动 Gateway 网关,然后通过配置编辑启用内置渠道 / 插件。
|
||||
- 验证设置发现流程会让未配置插件的运行时依赖保持缺失状态;首次已配置的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖;第二次重启不会重新安装已经激活过的依赖。
|
||||
- 还会安装一个已知的较旧 npm 基线版本,在运行 `openclaw update --tag <candidate>` 之前启用 Telegram,并验证候选版本更新后的 doctor 会修复内置渠道运行时依赖,而不依赖 harness 侧的 postinstall 修复。
|
||||
- 在 Docker 中打包并安装当前的 OpenClaw 构建版本,以配置好的 OpenAI 启动 Gateway 网关,然后通过编辑配置启用内置的渠道 / 插件。
|
||||
- 验证 setup 发现过程会让未配置插件的运行时依赖保持缺失状态;首次已配置的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖;第二次重启不会重新安装已经激活的依赖。
|
||||
- 还会安装一个已知的旧 npm 基线版本,在运行 `openclaw update --tag <candidate>` 之前启用 Telegram,并验证候选版本在更新后的 doctor 会修复内置渠道运行时依赖,而无需 harness 侧的 postinstall 修复。
|
||||
- `pnpm test:parallels:npm-update`
|
||||
- 在 Parallels 来宾机上运行原生打包安装更新冒烟测试。每个选定平台都会先安装指定的基线包,然后在同一个来宾机中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新状态、gateway 就绪情况以及一次本地智能体轮次。
|
||||
- 在针对单个来宾机迭代时,使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 可获取摘要产物路径和每个通道状态。
|
||||
- OpenAI 通道默认使用 `openai/gpt-5.5` 作为实时智能体轮次验证模型。如需有意验证其他 OpenAI 模型,请传入 `--model <provider/model>` 或设置 `OPENCLAW_PARALLELS_OPENAI_MODEL`。
|
||||
- 将较长的本地运行包装在主机超时中,以避免 Parallels 传输停滞耗尽剩余测试窗口:
|
||||
- 在 Parallels 来宾环境中运行原生打包安装更新冒烟测试。每个选定平台都会先安装所请求的基线包,然后在同一个来宾环境中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新状态、Gateway 网关就绪情况,以及一次本地智能体轮次。
|
||||
- 在迭代单个来宾环境时,使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 可获取摘要 artifact 路径和每个通道状态。
|
||||
- 默认情况下,OpenAI 通道会使用 `openai/gpt-5.5` 作为实时智能体轮次验证模型。若要有意验证其他 OpenAI 模型,请传入 `--model <provider/model>` 或设置 `OPENCLAW_PARALLELS_OPENAI_MODEL`。
|
||||
- 在本地长时间运行时,请在主机侧加上超时包装,以避免 Parallels 传输卡顿耗尽剩余测试窗口:
|
||||
|
||||
```bash
|
||||
timeout --foreground 150m pnpm test:parallels:npm-update -- --json
|
||||
timeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json
|
||||
```
|
||||
|
||||
- 脚本会将嵌套通道日志写入 `/tmp/openclaw-parallels-npm-update.*`。在认定外层包装器卡住之前,请先检查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`。
|
||||
- 在冷启动来宾机上,Windows 更新后的 doctor / 运行时依赖修复可能需要 10 到 15 分钟;只要嵌套的 npm 调试日志仍在推进,这仍属正常。
|
||||
- 不要将这个聚合包装器与单独的 Parallels macOS、Windows 或 Linux 冒烟通道并行运行。它们共享 VM 状态,可能会在快照恢复、包提供或来宾 gateway 状态上发生冲突。
|
||||
- 更新后的验证会运行常规内置插件入口面,因为语音、图像生成和媒体理解等能力外观层即使在智能体轮次本身只检查简单文本响应时,也仍然通过内置运行时 API 加载。
|
||||
- 脚本会将嵌套通道日志写入 `/tmp/openclaw-parallels-npm-update.*`。在假设外层包装器卡住之前,先检查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`。
|
||||
- 在冷启动的来宾环境中,Windows 更新可能会在更新后的 doctor / 运行时依赖修复阶段耗时 10 到 15 分钟;只要嵌套的 npm 调试日志仍在推进,这仍然是健康状态。
|
||||
- 不要将这个聚合包装器与单独的 Parallels macOS、Windows 或 Linux 冒烟通道并行运行。它们共享 VM 状态,可能会在快照恢复、包服务或来宾 Gateway 网关状态上发生冲突。
|
||||
- 更新后的验证会运行常规的内置插件界面,因为语音、图像生成和媒体理解等能力门面即使在智能体轮次本身只检查简单文本响应时,也仍会通过内置运行时 API 加载。
|
||||
|
||||
- `pnpm openclaw qa aimock`
|
||||
- 仅启动本地 AIMock 提供商服务器,用于直接协议冒烟测试。
|
||||
- 仅启动本地 AIMock provider 服务,用于直接协议冒烟测试。
|
||||
- `pnpm openclaw qa matrix`
|
||||
- 针对一次性 Docker 支持的 Tuwunel homeserver 运行 Matrix 实时 QA 通道。仅支持源码检出——打包安装不附带 `qa-lab`。
|
||||
- 完整 CLI、profile / 场景目录、环境变量和产物布局:参见 [Matrix QA](/zh-CN/concepts/qa-matrix)。
|
||||
- 针对一次性的 Docker 支持 Tuwunel homeserver 运行 Matrix 实时 QA 通道。仅适用于源代码检出 —— 打包安装版本不包含 `qa-lab`。
|
||||
- 完整 CLI、profile / 场景目录、环境变量和 artifact 布局:见 [Matrix QA](/zh-CN/concepts/qa-matrix)。
|
||||
- `pnpm openclaw qa telegram`
|
||||
- 使用来自环境变量的 driver 和 SUT 机器人令牌,针对真实私有群组运行 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`。
|
||||
- 需要同一私有群组中的两个不同机器人,并且 SUT 机器人需要公开 Telegram 用户名。
|
||||
- 为了实现稳定的机器人对机器人观测,请在 `@BotFather` 中为两个机器人启用 Bot-to-Bot Communication Mode,并确保 driver 机器人能够观测群组中的机器人流量。
|
||||
- 会在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 产物。回复类场景包含从 driver 发送请求到观测到 SUT 回复的 RTT。
|
||||
- 使用来自环境变量的驱动器和 SUT bot token,针对真实私有群组运行 Telegram 实时 QA 通道。
|
||||
- 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。群组 id 必须是 Telegram chat 的数字 id。
|
||||
- 支持 `--credential-source convex` 以使用共享池化凭证。默认使用环境变量模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以启用池化租约。
|
||||
- 任一场景失败时会以非零状态退出。若你希望保留 artifact 但不以失败退出,可使用 `--allow-failures`。
|
||||
- 需要同一个私有群组中的两个不同 bot,且 SUT bot 必须暴露一个 Telegram 用户名。
|
||||
- 为了稳定观察 bot 与 bot 之间的通信,请在 `@BotFather` 中为两个 bot 启用 Bot-to-Bot Communication Mode,并确保驱动 bot 可以观察群组中的 bot 流量。
|
||||
- 会在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要以及 observed-messages artifact。回复类场景会包含从驱动发送请求到观察到 SUT 回复之间的 RTT。
|
||||
|
||||
实时传输通道共享一套标准契约,以避免新传输协议出现偏移;每个通道的覆盖矩阵位于 [QA overview → Live transport coverage](/zh-CN/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是覆盖范围更广的合成测试套件,不属于该矩阵的一部分。
|
||||
实时传输协议通道共享一份标准契约,因此新传输协议不会发生漂移;每个通道的覆盖矩阵位于 [QA overview → Live transport coverage](/zh-CN/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是范围更广的合成测试套件,不属于该矩阵的一部分。
|
||||
|
||||
### 通过 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 支持的凭证池中获取独占租约,在通道运行期间为该租约发送心跳,并在关闭时释放租约。
|
||||
|
||||
参考 Convex 项目脚手架:
|
||||
|
||||
- `qa/convex-credential-broker/`
|
||||
|
||||
必需环境变量:
|
||||
必需的环境变量:
|
||||
|
||||
- `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`)
|
||||
- 所选角色对应的一个密钥:
|
||||
- `maintainer` 使用 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`
|
||||
- `ci` 使用 `OPENCLAW_QA_CONVEX_SECRET_CI`
|
||||
- 为所选角色提供一个密钥:
|
||||
- `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`)
|
||||
|
||||
可选环境变量:
|
||||
|
||||
@ -203,10 +266,10 @@ gh workflow run package-acceptance.yml --ref main \
|
||||
|
||||
正常运行时,`OPENCLAW_QA_CONVEX_SITE_URL` 应使用 `https://`。
|
||||
|
||||
维护者管理命令(池添加 / 删除 / 列表)必须明确使用
|
||||
维护者管理命令(池添加 / 删除 / 列表)需要专门使用
|
||||
`OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。
|
||||
|
||||
面向维护者的 CLI 辅助命令:
|
||||
供维护者使用的 CLI 辅助命令:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa credentials doctor
|
||||
@ -215,54 +278,56 @@ pnpm openclaw qa credentials list --kind telegram
|
||||
pnpm openclaw qa credentials remove --credential-id <credential-id>
|
||||
```
|
||||
|
||||
在实时运行前使用 `doctor`,可检查 Convex 站点 URL、broker 密钥、端点前缀、HTTP 超时和管理 / 列表可达性,同时不会打印密钥值。在脚本和 CI 工具中使用 `--json` 可获得机器可读输出。
|
||||
在实时运行前使用 `doctor`,可检查 Convex 站点 URL、broker 密钥、
|
||||
端点前缀、HTTP 超时以及管理 / 列表可达性,同时不会打印密钥值。使用 `--json`
|
||||
可在脚本和 CI 工具中获得机器可读输出。
|
||||
|
||||
默认端点契约(`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`)
|
||||
- `POST /release`
|
||||
- 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken }`
|
||||
- 成功:`{ status: "ok" }`(或空的 `2xx`)
|
||||
- `POST /admin/add`(仅 maintainer 密钥)
|
||||
- `POST /admin/add`(仅维护者密钥)
|
||||
- 请求:`{ kind, actorId, payload, note?, status? }`
|
||||
- 成功:`{ status: "ok", credential }`
|
||||
- `POST /admin/remove`(仅 maintainer 密钥)
|
||||
- `POST /admin/remove`(仅维护者密钥)
|
||||
- 请求:`{ credentialId, actorId }`
|
||||
- 成功:`{ status: "ok", changed, credential }`
|
||||
- 活跃租约保护:`{ status: "error", code: "LEASE_ACTIVE", ... }`
|
||||
- `POST /admin/list`(仅 maintainer 密钥)
|
||||
- `POST /admin/list`(仅维护者密钥)
|
||||
- 请求:`{ kind?, status?, includePayload?, limit? }`
|
||||
- 成功:`{ status: "ok", credentials, count }`
|
||||
|
||||
Telegram 类型的负载结构:
|
||||
Telegram 类型的 payload 结构:
|
||||
|
||||
- `{ groupId: string, driverToken: string, sutToken: string }`
|
||||
- `groupId` 必须是 Telegram 聊天数字 id 字符串。
|
||||
- `admin/add` 会在 `kind: "telegram"` 时验证此结构,并拒绝格式错误的负载。
|
||||
- `groupId` 必须是 Telegram chat 的数字 id 字符串。
|
||||
- `admin/add` 会为 `kind: "telegram"` 验证此结构,并拒绝格式错误的 payload。
|
||||
|
||||
### 向 QA 添加一个渠道
|
||||
|
||||
新渠道适配器的架构和场景辅助函数名称位于 [QA overview → Adding a channel](/zh-CN/concepts/qa-e2e-automation#adding-a-channel)。最低要求是:在共享的 `qa-lab` 主机接缝上实现传输运行器、在插件清单中声明 `qaRunners`、挂载为 `openclaw qa <runner>`,并在 `qa/scenarios/` 下编写场景。
|
||||
新渠道适配器的架构和场景辅助函数名称位于 [QA overview → Adding a channel](/zh-CN/concepts/qa-e2e-automation#adding-a-channel)。最低要求是:在共享 `qa-lab` 主机接缝上实现传输协议运行器,在插件清单中声明 `qaRunners`,将其挂载为 `openclaw qa <runner>`,并在 `qa/scenarios/` 下编写场景。
|
||||
|
||||
## 测试套件(各自运行位置)
|
||||
|
||||
可以把这些测试套件理解为“真实度逐步增加”(同时波动性 / 成本也逐步增加):
|
||||
可以将这些测试套件理解为“真实性逐步提高”(同时不稳定性 / 成本也逐步增加):
|
||||
|
||||
### 单元 / 集成(默认)
|
||||
|
||||
- 命令:`pnpm test`
|
||||
- 配置:非定向运行使用 `vitest.full-*.config.ts` 分片集,并且可以将多项目分片展开为按项目划分的配置,以便并行调度
|
||||
- 配置:未定向运行使用 `vitest.full-*.config.ts` 分片集合,并且可能会将多项目分片展开为按项目划分的配置,以便并行调度
|
||||
- 文件:核心 / 单元清单位于 `src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts`;UI 单元测试在专用的 `unit-ui` 分片中运行
|
||||
- 范围:
|
||||
- 纯单元测试
|
||||
- 进程内集成测试(gateway 认证、路由、工具、解析、配置)
|
||||
- 已知缺陷的确定性回归测试
|
||||
- 进程内集成测试(Gateway 网关认证、路由、工具、解析、配置)
|
||||
- 针对已知缺陷的确定性回归测试
|
||||
- 预期:
|
||||
- 在 CI 中运行
|
||||
- 不需要真实密钥
|
||||
@ -271,35 +336,35 @@ Telegram 类型的负载结构:
|
||||
<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` 项目图,因为多分片监听循环并不现实。
|
||||
- `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 会优先通过带作用域的通道处理显式文件 / 目录目标,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 不必承担完整根项目启动开销。
|
||||
- `pnpm test:changed` 默认会将 Git 变更路径展开为低成本的带作用域通道:直接测试编辑、同级 `*.test.ts` 文件、显式源码映射和本地导入图依赖方。除非你显式使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`,否则配置 / setup / package 编辑不会广泛运行测试。
|
||||
- `pnpm check:changed` 是针对窄范围工作的标准智能本地检查门禁。它会将 diff 分类为核心、核心测试、扩展、扩展测试、应用、文档、发布元数据、实时 Docker 工具和工具链,然后运行匹配的类型检查、lint 和守卫命令。它不会运行 Vitest 测试;测试证明请调用 `pnpm test:changed` 或显式 `pnpm test <target>`。仅发布元数据的版本升级会运行有针对性的版本 / 配置 / 根依赖检查,并带有一个守卫,用于拒绝顶层版本字段以外的 package 变更。
|
||||
- 实时 Docker ACP harness 编辑会运行聚焦检查:对实时 Docker 认证脚本进行 shell 语法检查,以及实时 Docker 调度器 dry-run。只有当 diff 仅限于 `scripts["test:docker:live-*"]` 时才包含 `package.json` 变更;依赖、导出、版本和其他 package 入口面编辑仍然使用更广泛的守卫。
|
||||
- 来自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 以及类似纯工具区域的轻量导入单元测试会路由到 `unit-fast` 通道,该通道会跳过 `test/setup-openclaw-runtime.ts`;有状态 / 运行时较重的文件仍保留在现有通道上。
|
||||
- 选定的 `plugin-sdk` 和 `commands` 辅助源码文件也会将 changed 模式运行映射到这些轻量通道中的显式同级测试,因此辅助函数编辑无需重新运行该目录下完整的重型套件。
|
||||
- `auto-reply` 为顶层核心辅助函数、顶层 `reply.*` 集成测试以及 `src/auto-reply/reply/**` 子树设置了专用分桶。CI 还会进一步将 reply 子树拆分为 agent-runner、dispatch 和 commands / state-routing 分片,以避免某个导入较重的分桶独占整个 Node 尾部时间。
|
||||
- 未定向的 `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` 项目图,因为多分片监听循环并不实际。
|
||||
- `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 会优先通过有作用域的通道来路由显式文件 / 目录目标,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 不需要承担完整根项目启动开销。
|
||||
- `pnpm test:changed` 默认会将 Git 变更路径展开为廉价的作用域通道:直接测试编辑、同级 `*.test.ts` 文件、显式源码映射以及本地导入图依赖项。除非你显式使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`,否则配置 / setup / 包编辑不会广泛运行测试。
|
||||
- `pnpm check:changed` 是常规狭窄工作范围下的智能本地检查门禁。它会将 diff 分类为 core、core tests、extensions、extension tests、apps、docs、release metadata、实时 Docker 工具和 tooling,然后运行对应的类型检查、lint 和 guard 命令。它不会运行 Vitest 测试;测试验证请调用 `pnpm test:changed` 或显式的 `pnpm test <target>`。仅发布元数据的版本升级会运行有针对性的版本 / 配置 / 根依赖检查,并带有一项保护:拒绝顶层 version 字段之外的 package 变更。
|
||||
- 实时 Docker ACP harness 编辑会运行聚焦检查:实时 Docker 认证脚本的 shell 语法检查,以及实时 Docker 调度器的 dry-run。只有当 diff 仅限于 `scripts["test:docker:live-*"]` 时才包含 `package.json` 更改;依赖、导出、版本以及其他 package 表面编辑仍会使用更广泛的 guard。
|
||||
- 来自 agents、commands、plugins、auto-reply 辅助工具、`plugin-sdk` 以及类似纯工具区域的轻导入单元测试,会通过 `unit-fast` 通道运行,该通道会跳过 `test/setup-openclaw-runtime.ts`;有状态 / 运行时较重的文件则保留在现有通道中。
|
||||
- 某些选定的 `plugin-sdk` 和 `commands` 辅助源码文件,也会在 changed 模式运行时映射到这些轻量通道中的显式同级测试,因此辅助工具编辑不必为该目录重新运行完整的重型测试套件。
|
||||
- `auto-reply` 为顶层 core 辅助工具、顶层 `reply.*` 集成测试以及 `src/auto-reply/reply/**` 子树设置了专用桶。CI 还会进一步将 reply 子树拆分为 agent-runner、dispatch 和 commands / state-routing 分片,以避免某个导入较重的桶独占整个 Node 尾部耗时。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="嵌入式运行器覆盖范围">
|
||||
|
||||
- 当你修改消息工具发现输入或压缩运行时上下文时,要同时保留这两个层级的覆盖。
|
||||
- 为纯路由和归一化边界添加聚焦的辅助函数回归测试。
|
||||
- 保持嵌入式运行器集成套件处于健康状态:
|
||||
- 当你修改消息工具发现输入或 compaction 运行时上下文时,要同时保留这两个层级的覆盖。
|
||||
- 为纯路由和标准化边界添加聚焦的辅助函数回归测试。
|
||||
- 保持嵌入式运行器集成测试套件处于健康状态:
|
||||
`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 和 compaction 行为仍然通过真实的 `run.ts` / `compact.ts` 路径流转;仅有辅助函数测试并不足以替代这些集成路径。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vitest 池和隔离默认值">
|
||||
|
||||
- 基础 Vitest 配置默认使用 `threads`。
|
||||
- 共享 Vitest 配置固定为 `isolate: false`,并在根项目、e2e 和实时配置中使用非隔离运行器。
|
||||
- 根 UI 通道保留其 `jsdom` 设置和优化器,但也运行在共享的非隔离运行器上。
|
||||
- 共享 Vitest 配置固定设置 `isolate: false`,并在根项目、e2e 和实时配置中使用非隔离运行器。
|
||||
- 根 UI 通道保留其 `jsdom` setup 和优化器,但也运行在共享的非隔离运行器上。
|
||||
- 每个 `pnpm test` 分片都从共享 Vitest 配置继承相同的 `threads` + `isolate: false` 默认值。
|
||||
- `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可与原生 V8 行为进行对比。
|
||||
|
||||
@ -307,81 +372,82 @@ Telegram 类型的负载结构:
|
||||
|
||||
<Accordion title="快速本地迭代">
|
||||
|
||||
- `pnpm changed:lanes` 会显示某个 diff 会触发哪些架构通道。
|
||||
- pre-commit 钩子只负责格式化。它会重新暂存格式化后的文件,不会运行 lint、类型检查或测试。
|
||||
- 在你需要智能本地检查门禁时,请在交接或推送前显式运行 `pnpm check:changed`。
|
||||
- `pnpm test:changed` 默认通过低成本的带作用域通道运行。只有当智能体判断 harness、配置、package 或契约编辑确实需要更广泛的 Vitest 覆盖时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 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`。
|
||||
- `pnpm changed:lanes` 会显示一个 diff 触发了哪些架构通道。
|
||||
- pre-commit 钩子仅负责格式化。它会重新暂存已格式化的文件,不会运行 lint、类型检查或测试。
|
||||
- 在交接或推送前,如果你需要智能本地检查门禁,请显式运行 `pnpm check:changed`。
|
||||
- `pnpm test:changed` 默认通过廉价的作用域通道来路由。只有当智能体判断 harness、配置、package 或契约编辑确实需要更广的 Vitest 覆盖时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。
|
||||
- `pnpm test:max` 和 `pnpm test:changed:max` 保持相同的路由行为,只是使用更高的工作进程上限。
|
||||
- 本地工作进程自动伸缩是有意保守的;当主机平均负载已经较高时会回退,因此默认情况下多个并发 Vitest 运行造成的影响会更小。
|
||||
- 基础 Vitest 配置会将项目 / 配置文件标记为 `forceRerunTriggers`,因此当测试接线发生变化时,changed 模式重跑仍然能保持正确。
|
||||
- 该配置会在受支持主机上保持启用 `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` 以来变更的文件。
|
||||
- 分片计时数据会写入 `.artifacts/vitest-shard-timings.json`。整套配置运行使用配置路径作为键;基于 include-pattern 的 CI 分片会追加分片名,以便分别跟踪过滤后的分片。
|
||||
- 当某个热点测试仍然把大部分时间花在启动导入上时,应将重型依赖放在狭窄的本地 `*.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:profile:main` 会为 Vitest / Vite 启动和 transform 开销写入主线程 CPU profile。
|
||||
- `pnpm test:perf:profile:runner` 会在禁用文件并行的情况下,为单元测试套件写入运行器 CPU + 堆 profile。
|
||||
- `pnpm test:perf:imports` 会启用 Vitest 导入耗时报告以及导入分解输出。
|
||||
- `pnpm test:perf:imports:changed` 会将相同的分析视图限定到自 `origin/main` 以来发生变化的文件。
|
||||
- 分片耗时数据会写入 `.artifacts/vitest-shard-timings.json`。
|
||||
整个配置运行使用配置路径作为键;include-pattern CI 分片会附加分片名称,以便分别跟踪经过过滤的分片。
|
||||
- 当某个热点测试的大部分时间仍然耗费在启动导入上时,应将重依赖放在狭窄的本地 `*.runtime.ts` 接缝之后,并直接 mock 该接缝,而不是仅为了通过 `vi.mock(...)` 传递它们就深度导入运行时辅助工具。
|
||||
- `pnpm test:perf:changed:bench -- --ref <git-ref>` 会针对该已提交 diff,将路由后的 `test:changed` 与原生根项目路径进行比较,并输出墙钟时间以及 macOS 最大 RSS。
|
||||
- `pnpm test:perf:changed:bench -- --worktree` 会对当前脏工作树进行基准测试,方法是通过 `scripts/test-projects.mjs` 和根 Vitest 配置来路由变更文件列表。
|
||||
- `pnpm test:perf:profile:main` 会为 Vitest / Vite 启动和转换开销写入主线程 CPU profile。
|
||||
- `pnpm test:perf:profile:runner` 会在禁用文件并行的情况下,为单元测试套件写入运行器 CPU + heap profile。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 稳定性(gateway)
|
||||
### 稳定性(Gateway 网关)
|
||||
|
||||
- 命令:`pnpm test:stability:gateway`
|
||||
- 配置:`vitest.gateway.config.ts`,强制单 worker
|
||||
- 配置:`vitest.gateway.config.ts`,强制使用单个工作进程
|
||||
- 范围:
|
||||
- 启动一个默认启用诊断的真实 loopback Gateway 网关
|
||||
- 通过诊断事件路径驱动合成的 gateway 消息、memory 和大负载抖动
|
||||
- 启动一个真实的 loopback Gateway 网关,并默认启用诊断
|
||||
- 通过诊断事件路径驱动合成的 gateway message、memory 和 large-payload 抖动
|
||||
- 通过 Gateway 网关 WS RPC 查询 `diagnostics.stability`
|
||||
- 覆盖诊断稳定性 bundle 持久化辅助函数
|
||||
- 断言记录器保持有界、合成 RSS 采样保持在压力预算以内,并且每个会话的队列深度会回落到零
|
||||
- 覆盖诊断稳定性 bundle 持久化辅助工具
|
||||
- 断言记录器保持有界、合成 RSS 样本低于压力预算,并且每个 session 的队列深度会回落到零
|
||||
- 预期:
|
||||
- 对 CI 安全且无需密钥
|
||||
- 这是用于稳定性回归跟进的窄范围通道,不可替代完整 Gateway 网关套件
|
||||
- 这是用于稳定性回归跟进的狭窄通道,不可替代完整的 Gateway 网关测试套件
|
||||
|
||||
### E2E(gateway 冒烟)
|
||||
### E2E(Gateway 网关冒烟测试)
|
||||
|
||||
- 命令:`pnpm test:e2e`
|
||||
- 配置:`vitest.e2e.config.ts`
|
||||
- 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的内置插件 E2E 测试
|
||||
- 运行时默认值:
|
||||
- 使用 Vitest `threads` 且 `isolate: false`,与仓库其余部分保持一致。
|
||||
- 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。
|
||||
- 使用自适应工作进程(CI:最多 2 个,本地:默认 1 个)。
|
||||
- 默认以静默模式运行,以减少控制台 I/O 开销。
|
||||
- 常用覆盖方式:
|
||||
- `OPENCLAW_E2E_WORKERS=<n>` 强制指定 worker 数量(上限为 16)。
|
||||
- `OPENCLAW_E2E_VERBOSE=1` 重新启用详细控制台输出。
|
||||
- 常用覆盖项:
|
||||
- `OPENCLAW_E2E_WORKERS=<n>`:强制设置工作进程数量(上限为 16)。
|
||||
- `OPENCLAW_E2E_VERBOSE=1`:重新启用详细控制台输出。
|
||||
- 范围:
|
||||
- 多实例 gateway 端到端行为
|
||||
- WebSocket / HTTP 入口面、节点配对和更重的网络行为
|
||||
- 多实例 Gateway 网关端到端行为
|
||||
- WebSocket / HTTP 界面、节点配对和更重型的网络行为
|
||||
- 预期:
|
||||
- 在 CI 中运行(当管道中启用时)
|
||||
- 会在 CI 中运行(当流水线启用时)
|
||||
- 不需要真实密钥
|
||||
- 比单元测试包含更多活动部件(可能更慢)
|
||||
- 比单元测试涉及更多运动部件(可能更慢)
|
||||
|
||||
### E2E:OpenShell 后端冒烟
|
||||
### E2E:OpenShell 后端冒烟测试
|
||||
|
||||
- 命令:`pnpm test:e2e:openshell`
|
||||
- 文件:`extensions/openshell/src/backend.e2e.test.ts`
|
||||
- 范围:
|
||||
- 通过 Docker 在主机上启动一个隔离的 OpenShell gateway
|
||||
- 从临时本地 Dockerfile 创建一个沙箱
|
||||
- 通过 Docker 在主机上启动一个隔离的 OpenShell Gateway 网关
|
||||
- 从一个临时本地 Dockerfile 创建沙箱
|
||||
- 通过真实的 `sandbox ssh-config` + SSH exec 运行 OpenClaw 的 OpenShell 后端
|
||||
- 通过沙箱 fs bridge 验证远程规范化文件系统行为
|
||||
- 通过沙箱文件系统桥接验证远程规范文件系统行为
|
||||
- 预期:
|
||||
- 仅显式启用;不属于默认 `pnpm test:e2e` 运行的一部分
|
||||
- 仅按需启用;不属于默认 `pnpm test:e2e` 运行的一部分
|
||||
- 需要本地 `openshell` CLI 和可用的 Docker daemon
|
||||
- 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 gateway 和沙箱
|
||||
- 常用覆盖方式:
|
||||
- `OPENCLAW_E2E_OPENSHELL=1`,在手动运行更广泛的 e2e 套件时启用该测试
|
||||
- `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`,指向非默认 CLI 二进制文件或包装脚本
|
||||
- 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 Gateway 网关和沙箱
|
||||
- 常用覆盖项:
|
||||
- `OPENCLAW_E2E_OPENSHELL=1`:在手动运行更广泛的 e2e 测试套件时启用该测试
|
||||
- `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`:指向非默认 CLI 二进制文件或包装脚本
|
||||
|
||||
### 实时(真实提供商 + 真实模型)
|
||||
|
||||
@ -390,83 +456,84 @@ Telegram 类型的负载结构:
|
||||
- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件实时测试
|
||||
- 默认:由 `pnpm test:live` **启用**(设置 `OPENCLAW_LIVE_TEST=1`)
|
||||
- 范围:
|
||||
- “这个提供商 / 模型在今天、使用真实凭证时,是否真的能工作?”
|
||||
- “这个提供商 / 模型 _今天_ 用真实凭证是否真的可用?”
|
||||
- 捕获提供商格式变化、工具调用怪癖、认证问题和速率限制行为
|
||||
- 预期:
|
||||
- 按设计不具备 CI 稳定性(真实网络、真实提供商策略、配额、故障)
|
||||
- 设计上不保证 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` 做每次实时运行覆盖;测试在遇到速率限制响应时会重试。
|
||||
- 优先运行缩小范围的子集,而不是“全部运行”
|
||||
- 实时运行会读取 `~/.profile`,以获取缺失的 API key。
|
||||
- 默认情况下,实时运行仍会隔离 `HOME`,并将配置 / 认证材料复制到一个临时测试 home 中,这样单元测试固定装置就无法修改你真实的 `~/.openclaw`。
|
||||
- 仅当你明确需要实时测试使用真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。
|
||||
- `pnpm test:live` 现在默认使用更安静的模式:它会保留 `[live] ...` 进度输出,但会抑制额外的 `~/.profile` 提示,并静默 Gateway 网关启动日志 / Bonjour 噪声。如果你想恢复完整启动日志,请设置 `OPENCLAW_LIVE_TEST_QUIET=0`。
|
||||
- API key 轮换(按提供商):设置逗号 / 分号格式的 `*_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 / 探测心跳。
|
||||
- 实时测试套件现在会将进度行输出到 stderr,因此即使 Vitest 控制台捕获较安静,长时间的提供商调用也能明显显示仍在活动。
|
||||
- `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,因此提供商 / Gateway 网关进度行会在实时运行期间立即流式输出。
|
||||
- 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整 direct-model 心跳。
|
||||
- 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关 / probe 心跳。
|
||||
|
||||
## 我应该运行哪个测试套件?
|
||||
|
||||
使用下面这个决策表:
|
||||
使用下面这张决策表:
|
||||
|
||||
- 编辑逻辑 / 测试:运行 `pnpm test`(如果你改动很多,也运行 `pnpm test:coverage`)
|
||||
- 修改 gateway 网络 / WS 协议 / 配对:再加上 `pnpm test:e2e`
|
||||
- 调试“我的机器人挂了” / 提供商特定故障 / 工具调用:运行收窄后的 `pnpm test:live`
|
||||
- 编辑逻辑 / 测试:运行 `pnpm test`(如果你改动很多,再运行 `pnpm test:coverage`)
|
||||
- 触及 Gateway 网关网络 / WS 协议 / 配对:额外运行 `pnpm test:e2e`
|
||||
- 调试“我的 bot 挂了” / 提供商特定故障 / 工具调用:运行一个缩小范围的 `pnpm test:live`
|
||||
|
||||
## 实时(触网)测试
|
||||
|
||||
关于实时模型矩阵、CLI 后端冒烟、ACP 冒烟、Codex app-server
|
||||
harness,以及所有媒体提供商实时测试(Deepgram、BytePlus(国际版)、ComfyUI、图像、音乐、视频、媒体 harness)——以及实时运行的凭证处理——请参见
|
||||
有关实时模型矩阵、CLI 后端冒烟测试、ACP 冒烟测试、Codex app-server
|
||||
harness,以及所有媒体提供商实时测试(Deepgram、BytePlus(国际版)、ComfyUI、图像、
|
||||
音乐、视频、media harness)—— 以及实时运行的凭证处理 —— 请参阅
|
||||
[Testing — live suites](/zh-CN/help/testing-live)。
|
||||
|
||||
## Docker 运行器(可选的“在 Linux 上能工作”检查)
|
||||
## Docker 运行器(可选的“在 Linux 中可用”检查)
|
||||
|
||||
这些 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` 和 `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`、
|
||||
`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 镜像,再通过 `scripts/package-openclaw-for-docker.mjs` 将 OpenClaw 打包为一个 npm tarball,然后构建 / 复用两个 `scripts/e2e/Dockerfile` 镜像。基础镜像仅包含用于安装 / 更新 / 插件依赖通道的 Node / Git 运行器;这些通道会挂载预构建 tarball。功能镜像则会把同一个 tarball 安装到 `/app`,供基于已构建应用的功能通道使用。Docker 通道定义位于 `scripts/lib/docker-e2e-scenarios.mjs`;规划逻辑位于 `scripts/lib/docker-e2e-plan.mjs`;`scripts/test-docker-all.mjs` 负责执行选定计划。该聚合器使用加权本地调度器:`OPENCLAW_DOCKER_ALL_PARALLELISM` 控制进程槽位,而资源上限会阻止重型实时、npm 安装和多服务通道同时全部启动。如果某个单独通道比当前上限还重,调度器在池为空时仍可启动它,然后让它单独运行,直到再次有可用容量。默认值为 10 个槽位、`OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` 和 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`;只有当 Docker 主机有更多余量时,才调整 `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` 或 `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT`。该运行器默认执行 Docker 预检,移除陈旧的 OpenClaw E2E 容器,每 30 秒打印一次状态,将成功通道的耗时存储到 `.artifacts/docker-tests/lane-timings.json`,并在后续运行中利用这些耗时优先启动更长的通道。使用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 可在不构建或运行 Docker 的情况下打印加权通道清单,或者使用 `node scripts/test-docker-all.mjs --plan-json` 打印所选通道、包 / 镜像需求和凭证的 CI 计划。
|
||||
- `Package Acceptance` 是 GitHub 原生的包门禁,用于回答“这个可安装 tarball 作为产品是否可用?”。它会从 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 解析出一个候选包,将其上传为 `package-under-test`,然后针对这个精确 tarball 运行可复用的 Docker E2E 通道,而不是重新打包所选 ref。`workflow_ref` 用于选择受信任的工作流 / harness 脚本,而 `package_ref` 用于在 `source=ref` 时选择要打包的源提交 / 分支 / 标签;这样当前的验收逻辑也能验证较旧的受信任提交。各 profile 按覆盖范围排序:`smoke` 是快速安装 / 渠道 / 智能体加 gateway / 配置,`package` 是包 / 更新 / 插件契约,也是大多数 Parallels 包 / 更新覆盖的默认原生替代方案,`product` 会增加 MCP 渠道、cron / 子智能体清理、OpenAI Web 搜索和 OpenWebUI,而 `full` 会运行包含 OpenWebUI 的发布路径 Docker 分块。发布验证会运行一个自定义包差异集(`bundled-channel-deps-compat plugins-offline`)加 Telegram 包 QA,因为发布路径 Docker 分块已经覆盖了重叠的包 / 更新 / 插件通道。由产物生成的定向 GitHub Docker 重跑命令在可用时会包含先前的包产物和准备好的镜像输入,因此失败通道可以避免重新构建包和镜像。
|
||||
- 构建和发布检查会在 tsdown 之后运行 `scripts/check-cli-bootstrap-imports.mjs`。该守卫会从 `dist/entry.js` 和 `dist/cli/run-main.js` 遍历静态构建图,如果在命令分发之前的启动导入阶段就引入了 Commander、提示 UI、undici 或日志等包依赖,则会失败。打包后的 CLI 冒烟测试还会覆盖根帮助、onboard 帮助、doctor 帮助、status、配置 schema 和模型列表命令。
|
||||
- `Package Acceptance` 的旧版兼容性上限为 `2026.4.25`(包含 `2026.4.25-beta.*`)。在该截止版本及之前,harness 仅容忍已发布包元数据缺口:省略的私有 QA 清单条目、缺失的 `gateway install --wrapper`、tarball 派生 git 夹具中缺失的补丁文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。对于 `2026.4.25` 之后的包,这些路径都会被视为严格失败。
|
||||
`OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。只有当你明确希望进行更大范围的穷举扫描时,才覆盖这些环境变量。
|
||||
- `test:docker:all` 会先通过 `test:docker:live-build` 构建一次实时 Docker 镜像,再通过 `scripts/package-openclaw-for-docker.mjs` 将 OpenClaw 打包一次为 npm tarball,然后构建 / 复用两个 `scripts/e2e/Dockerfile` 镜像。裸镜像仅包含用于安装 / 更新 / 插件依赖通道的 Node / Git 运行器;这些通道会挂载预构建的 tarball。功能镜像则会将同一个 tarball 安装到 `/app` 中,用于 built-app 功能通道。Docker 通道定义位于 `scripts/lib/docker-e2e-scenarios.mjs`;planner 逻辑位于 `scripts/lib/docker-e2e-plan.mjs`;`scripts/test-docker-all.mjs` 负责执行所选计划。该聚合运行器使用加权本地调度器:`OPENCLAW_DOCKER_ALL_PARALLELISM` 控制进程槽位,而资源上限会阻止重量级实时、npm 安装和多服务通道同时启动。如果某个单独通道比当前上限更重,调度器在池为空时仍可启动它,然后让它单独持续运行,直到再次有可用容量。默认值为 10 个槽位、`OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` 和 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`;只有当 Docker 主机有更多余量时,才调整 `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` 或 `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT`。该运行器默认执行 Docker 预检、删除陈旧的 OpenClaw E2E 容器、每 30 秒打印一次状态、将成功通道的耗时存入 `.artifacts/docker-tests/lane-timings.json`,并在后续运行中利用这些耗时优先启动更长的通道。使用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 可在不构建或运行 Docker 的情况下打印加权通道清单,或使用 `node scripts/test-docker-all.mjs --plan-json` 打印所选通道、包 / 镜像需求和凭证的 CI 计划。
|
||||
- `Package Acceptance` 是 GitHub 原生的包门禁,用于回答“这个可安装 tarball 作为产品是否可用?”它会从 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 中解析一个候选包,将其作为 `package-under-test` 上传,然后针对这个精确 tarball 运行可复用的 Docker E2E 通道,而不是重新打包所选 ref。`workflow_ref` 选择受信任的工作流 / harness 脚本,而 `package_ref` 选择在 `source=ref` 时用于打包的源提交 / 分支 / 标签;这使当前的 acceptance 逻辑能够验证较旧的受信任提交。各配置文件按覆盖范围排序:`smoke` 是快速的安装 / 渠道 / 智能体加上 gateway / config,`package` 是包 / 更新 / 插件契约,也是大多数 Parallels 包 / 更新覆盖的默认原生替代,`product` 会增加 MCP 渠道、cron / subagent 清理、OpenAI Web 搜索 和 OpenWebUI,而 `full` 会运行带有 OpenWebUI 的发布路径 Docker 分块。发布验证会运行一个自定义 package delta(`bundled-channel-deps-compat plugins-offline`)加上 Telegram package QA,因为发布路径 Docker 分块已经覆盖了重叠的 package / update / plugin 通道。根据 artifact 生成的定向 GitHub Docker 重跑命令会在可用时包含先前的 package artifact 和准备好的镜像输入,因此失败的通道可以避免重新构建包和镜像。
|
||||
- 构建和发布检查会在 tsdown 之后运行 `scripts/check-cli-bootstrap-imports.mjs`。该保护会从 `dist/entry.js` 和 `dist/cli/run-main.js` 开始遍历静态构建图,并在命令分发之前的启动导入阶段发现 Commander、prompt UI、undici 或日志记录等包依赖时失败。打包后的 CLI 冒烟测试还覆盖根帮助、onboard 帮助、doctor 帮助、status、配置 schema 和模型列表命令。
|
||||
- `Package Acceptance` 的旧版兼容性上限为 `2026.4.25`(包含 `2026.4.25-beta.*`)。在该截止版本之前,harness 仅容忍已发布包中的元数据缺口:省略的私有 QA inventory 条目、缺失的 `gateway install --wrapper`、tarball 派生 git fixture 中缺失的 patch 文件、缺失的持久化 `update.channel`、旧版插件 install-record 位置、缺失的 marketplace install-record 持久化,以及 `plugins update` 期间的配置元数据迁移。对于 `2026.4.25` 之后的包,这些路径都会被视为严格失败。
|
||||
- 容器冒烟运行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:update-channel-switch`、`test:docker:session-runtime-context`、`test:docker:agents-delete-shared-workspace`、`test:docker:gateway-network`、`test:docker:browser-cdp-snapshot`、`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 运行器还会只绑定挂载所需的 CLI 认证 home(若运行未缩小范围,则挂载所有受支持的认证 home),然后在运行前将它们复制到容器 home 中,这样外部 CLI OAuth 就可以刷新令牌,而不会修改主机认证存储:
|
||||
实时模型 Docker 运行器还会仅绑定挂载所需的 CLI 认证 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`;默认覆盖 Claude、Codex 和 Gemini,并可通过 `pnpm test:docker:live-acp-bind:droid` 和 `pnpm test:docker:live-acp-bind:opencode` 启用严格的 Droid / OpenCode 覆盖)
|
||||
- CLI 后端冒烟:`pnpm test:docker:live-cli-backend`(脚本:`scripts/test-live-cli-backend-docker.sh`)
|
||||
- Codex app-server harness 冒烟:`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`)
|
||||
- 可观测性冒烟:`pnpm qa:otel:smoke` 是一个私有 QA 源码检出通道。它刻意不属于包级 Docker 发布通道的一部分,因为 npm tarball 不包含 QA Lab。
|
||||
- Open WebUI 实时冒烟:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`)
|
||||
- ACP 绑定冒烟测试:`pnpm test:docker:live-acp-bind`(脚本:`scripts/test-live-acp-bind-docker.sh`;默认覆盖 Claude、Codex 和 Gemini,若需严格的 Droid / OpenCode 覆盖,可使用 `pnpm test:docker:live-acp-bind:droid` 和 `pnpm test:docker:live-acp-bind:opencode`)
|
||||
- CLI 后端冒烟测试:`pnpm test:docker:live-cli-backend`(脚本:`scripts/test-live-cli-backend-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`)
|
||||
- 可观测性冒烟测试:`pnpm qa:otel:smoke` 是私有的 QA 源代码检出通道。它故意不属于 package Docker 发布通道的一部分,因为 npm tarball 不包含 QA Lab。
|
||||
- Open WebUI 实时冒烟测试:`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,通过 env-ref 新手引导配置 OpenAI,并默认配置 Telegram,验证 doctor 会修复已激活插件的运行时依赖,然后运行一次模拟的 OpenAI 智能体轮次。可使用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,使用 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机构建,或使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换渠道。
|
||||
- 更新渠道切换冒烟:`pnpm test:docker:update-channel-switch` 会在 Docker 中全局安装打包好的 OpenClaw tarball,从 package `stable` 切换到 git `dev`,验证持久化渠道和插件在更新后可正常工作,然后再切回 package `stable` 并检查更新状态。
|
||||
- 会话运行时上下文冒烟:`pnpm test:docker:session-runtime-context` 会验证隐藏运行时上下文转录的持久化,以及 doctor 对受影响的重复 prompt-rewrite 分支的修复。
|
||||
- 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、update 和 direct-npm 容器之间共享一个 npm 缓存。更新冒烟默认使用 npm `latest` 作为稳定基线,然后再升级到候选 tarball。本地可通过 `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` 覆盖,或在 GitHub 上通过 Install Smoke 工作流的 `update_baseline_version` 输入覆盖。非 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` 覆盖,请在本地运行该脚本时不要设置这个环境变量。
|
||||
- Agents 删除共享工作区 CLI 冒烟:`pnpm test:docker:agents-delete-shared-workspace`(脚本:`scripts/e2e/agents-delete-shared-workspace-docker.sh`)默认构建根 Dockerfile 镜像,在隔离容器 home 中注入两个共享同一工作区的智能体,运行 `agents delete --json`,并验证 JSON 合法以及工作区保留行为。可使用 `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1` 复用 install-smoke 镜像。
|
||||
- Npm tarball 新手引导 / 渠道 / 智能体冒烟测试:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装打包后的 OpenClaw tarball,通过 env-ref 新手引导配置 OpenAI,并默认配置 Telegram,验证 doctor 会修复已激活插件的运行时依赖,并运行一次 mock 的 OpenAI 智能体轮次。可使用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,使用 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机构建,或使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换渠道。
|
||||
- 更新渠道切换冒烟测试:`pnpm test:docker:update-channel-switch` 会在 Docker 中全局安装打包后的 OpenClaw tarball,将渠道从 package `stable` 切换到 git `dev`,验证持久化的渠道和插件在更新后仍可工作,然后再切换回 package `stable` 并检查更新状态。
|
||||
- 会话运行时上下文冒烟测试:`pnpm test:docker:session-runtime-context` 会验证隐藏运行时上下文 transcript 的持久化,以及 doctor 对受影响的重复 prompt-rewrite 分支的修复。
|
||||
- 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、update 和 direct-npm 容器之间共享一个 npm 缓存。更新冒烟测试默认使用 npm `latest` 作为稳定基线,然后升级到候选 tarball。本地可通过 `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` 覆盖,或在 GitHub 上通过 Install Smoke 工作流的 `update_baseline_version` 输入覆盖。非 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` 覆盖时,请在本地运行脚本且不要设置该环境变量。
|
||||
- Agents 删除共享工作区 CLI 冒烟测试:`pnpm test:docker:agents-delete-shared-workspace`(脚本:`scripts/e2e/agents-delete-shared-workspace-docker.sh`)默认会构建根 Dockerfile 镜像,在隔离的容器 home 中为两个智能体植入一个工作区,运行 `agents delete --json`,并验证 JSON 有效以及工作区保留行为。可使用 `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1` 复用 install-smoke 镜像。
|
||||
- Gateway 网关网络(两个容器,WS 认证 + 健康检查):`pnpm test:docker:gateway-network`(脚本:`scripts/e2e/gateway-network-docker.sh`)
|
||||
- 浏览器 CDP 快照冒烟:`pnpm test:docker:browser-cdp-snapshot`(脚本:`scripts/e2e/browser-cdp-snapshot-docker.sh`)会构建源码 E2E 镜像和一个 Chromium 层,以原始 CDP 启动 Chromium,运行 `browser doctor --deep`,并验证 CDP 角色快照覆盖链接 URL、由光标提升的可点击元素、iframe 引用和 frame 元数据。
|
||||
- OpenAI Responses `web_search` 最小 reasoning 回归测试:`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 通知帧冒烟):`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 网关 + 在隔离 cron 和一次性子智能体运行后回收 stdio MCP 子进程):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`)
|
||||
- 插件(安装冒烟、ClawHub 安装 / 卸载、marketplace 更新,以及 Claude bundle 启用 / 检查):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-docker.sh`)
|
||||
设置 `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` 可跳过实时 ClawHub 模块,或通过 `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` 和 `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID` 覆盖默认包。
|
||||
- 插件更新未变化冒烟:`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_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向现有 tarball。完整 Docker 聚合和发布路径 `bundled-channels` 分块会先统一预打包一次这个 tarball,然后将内置渠道检查切分为独立通道,包括 Telegram、Discord、Slack、Feishu、memory-lancedb 和 ACPX 的独立更新通道。旧版 `plugins-integrations` 分块仍保留为手动重跑时的聚合别名。直接运行内置通道时,可使用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 缩小渠道矩阵,或使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 缩小更新场景。该通道还会验证 `channels.<id>.enabled=false` 和 `plugins.entries.<id>.enabled=false` 会抑制 doctor / 运行时依赖修复。
|
||||
- 迭代时可通过禁用无关场景来缩小内置插件运行时依赖范围,例如:
|
||||
- 浏览器 CDP 快照冒烟测试:`pnpm test:docker:browser-cdp-snapshot`(脚本:`scripts/e2e/browser-cdp-snapshot-docker.sh`)会构建源码 E2E 镜像和一个 Chromium 层,以原始 CDP 启动 Chromium,运行 `browser doctor --deep`,并验证 CDP 角色快照覆盖链接 URL、由光标提升的可点击元素、iframe 引用和 frame 元数据。
|
||||
- OpenAI Responses `web_search` 最小推理回归测试:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)会通过 Gateway 网关运行一个 mock 的 OpenAI 服务器,验证 `web_search` 会将 `reasoning.effort` 从 `minimal` 提升到 `low`,然后强制 provider schema 拒绝,并检查原始细节会出现在 Gateway 网关日志中。
|
||||
- MCP 渠道桥接(已植入的 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 / subagent MCP 清理(真实 Gateway 网关 + stdio MCP 子进程在隔离 cron 和一次性 subagent 运行后关闭):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`)
|
||||
- 插件(安装冒烟测试、ClawHub 安装 / 卸载、marketplace 更新,以及 Claude bundle 启用 / 检查):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-docker.sh`)
|
||||
设置 `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` 可跳过实时 ClawHub 区块,或使用 `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` 和 `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID` 覆盖默认 package。
|
||||
- 插件更新未变更冒烟测试:`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_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向现有 tarball。完整的 Docker 聚合运行器和发布路径 `bundled-channels` 分块会预先打包该 tarball 一次,然后将内置渠道检查拆分为独立通道,包括 Telegram、Discord、Slack、Feishu、memory-lancedb 和 ACPX 的独立更新通道。发布工作流还会拆分 provider 安装器分块以及内置插件安装 / 卸载分块;旧版 `package-update`、`plugins-runtime` 和 `plugins-integrations` 分块仍保留为手动重跑的聚合别名。直接运行内置通道时,可使用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 缩小渠道矩阵,或使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 缩小更新场景。该通道还会验证 `channels.<id>.enabled=false` 和 `plugins.entries.<id>.enabled=false` 会抑制 doctor / 运行时依赖修复。
|
||||
- 在迭代时,如需缩小内置插件运行时依赖覆盖范围,可禁用无关场景,例如:
|
||||
`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`。
|
||||
|
||||
如需手动预构建并复用共享功能镜像:
|
||||
@ -476,142 +543,109 @@ OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:
|
||||
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional: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,因为它们验证的是 package / 安装行为,而不是共享的 built-app 运行时。
|
||||
|
||||
实时模型 Docker 运行器还会以只读方式绑定挂载当前检出内容,
|
||||
并将其注入到容器内的临时工作目录中。这样既能保持运行时
|
||||
镜像精简,又仍可针对你当前本地的源码 / 配置运行 Vitest。
|
||||
注入步骤会跳过大型本地专用缓存和应用构建输出,例如
|
||||
`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及应用本地 `.build` 或
|
||||
Gradle 输出目录,因此 Docker 实时运行不会花数分钟复制
|
||||
机器特定产物。
|
||||
它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,这样 gateway 实时探测就不会在容器内
|
||||
启动真实的 Telegram / Discord / 等渠道工作进程。
|
||||
`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`
|
||||
实时模型 Docker 运行器还会以只读方式绑定挂载当前检出内容,并在容器内将其暂存到一个临时工作目录中。这样既能保持运行时镜像精简,又仍然可以针对你精确的本地源码 / 配置运行 Vitest。暂存步骤会跳过大型本地专用缓存和应用构建输出,例如 `.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及应用本地 `.build` 或 Gradle 输出目录,因此 Docker 实时运行不会花数分钟复制特定于机器的 artifact。
|
||||
它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,这样 Gateway 网关实时探测就不会在容器内启动真实的 Telegram / Discord / 等渠道工作进程。
|
||||
`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":
|
||||
成功运行会打印一小段 JSON payload,例如 `{ "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 子进程会在每次运行后退出。
|
||||
`test:docker:mcp-channels` 是有意设计为确定性的,不需要真实的 Telegram、Discord 或 iMessage 账号。它会启动一个已植入的 Gateway 网关容器,再启动第二个容器来生成 `openclaw mcp serve`,然后通过真实的 stdio MCP bridge 验证路由后的会话发现、transcript 读取、附件元数据、实时事件队列行为、出站发送路由,以及 Claude 风格的渠道 + 权限通知。通知检查会直接检查原始 stdio MCP 帧,因此该冒烟测试验证的是 bridge 实际发出的内容,而不仅仅是某个特定客户端 SDK 恰好暴露的内容。
|
||||
`test:docker:pi-bundle-mcp-tools` 是确定性的,不需要实时模型密钥。它会构建仓库 Docker 镜像,在容器内启动一个真实的 stdio MCP probe 服务,通过嵌入式 Pi bundle MCP 运行时将该服务实体化,执行该工具,然后验证 `coding` 和 `messaging` 会保留 `bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会将其过滤掉。
|
||||
`test:docker:cron-mcp-cleanup` 是确定性的,不需要实时模型密钥。它会启动一个带有真实 stdio MCP probe 服务的已植入 Gateway 网关,运行一个隔离的 cron 轮次和一个 `/subagents spawn` 一次性子智能体轮次,然后验证 MCP 子进程会在每次运行后退出。
|
||||
|
||||
手动 ACP 自然语言线程冒烟测试(非 CI):
|
||||
手动 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_DOCKER_CLI_TOOLS_DIR=...`(默认:`~/.cache/openclaw/docker-cli-tools`)挂载到 `/home/node/.npm-global`,用于 Docker 内缓存的 CLI 安装
|
||||
- `$HOME` 下的外部 CLI 认证目录 / 文件会以只读方式挂载到 `/host-auth...`,然后在测试开始前复制到 `/home/node/...`
|
||||
- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 用于仅验证从 `OPENCLAW_PROFILE_FILE` 读取的环境变量,使用临时配置 / 工作区目录,并且不挂载外部 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` 推断出的所需目录 / 文件
|
||||
- 缩小范围的 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=...` 用于在容器内筛选提供商
|
||||
- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于复用现有 `openclaw:local-live` 镜像,以便在无需重建的情况下重跑
|
||||
- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` 用于在容器内筛选 provider
|
||||
- `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 检查提示词
|
||||
- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试所使用的 nonce 检查提示词
|
||||
- `OPENWEBUI_IMAGE=...` 用于覆盖固定的 Open WebUI 镜像标签
|
||||
|
||||
## 文档完整性检查
|
||||
|
||||
修改文档后运行文档检查:`pnpm check:docs`。
|
||||
当你还需要检查页内标题锚点时,运行完整的 Mintlify 锚点校验:`pnpm docs:check-links:anchors`。
|
||||
在编辑文档后运行文档检查:`pnpm check:docs`。
|
||||
当你还需要检查页内标题时,运行完整的 Mintlify 锚点验证:`pnpm docs:check-links:anchors`。
|
||||
|
||||
## 离线回归测试(对 CI 安全)
|
||||
|
||||
这些是在没有真实提供商的情况下运行的“真实流水线”回归测试:
|
||||
这些是“不依赖真实 provider 的真实流水线”回归测试:
|
||||
|
||||
- Gateway 网关工具调用(模拟 OpenAI,真实 gateway + Agent loop):`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 网关工具调用(mock OpenAI,真实 gateway + Agent loop):`src/gateway/gateway.test.ts`(用例:“runs a mock OpenAI tool call end-to-end via gateway agent loop”)
|
||||
- Gateway 网关向导(WS `wizard.start` / `wizard.next`,强制写入 config + auth):`src/gateway/gateway.test.ts`(用例:“runs wizard over ws and writes auth token config”)
|
||||
|
||||
## 智能体可靠性评估(Skills)
|
||||
|
||||
我们已经有一些对 CI 安全的测试,它们的行为类似于“智能体可靠性评估”:
|
||||
我们已经有一些对 CI 安全的测试,它们的行为类似“智能体可靠性评估”:
|
||||
|
||||
- 通过真实 gateway + Agent loop 的模拟工具调用(`src/gateway/gateway.test.ts`)。
|
||||
- 通过真实的 Gateway 网关 + Agent loop 进行 mock 工具调用(`src/gateway/gateway.test.ts`)。
|
||||
- 验证会话接线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。
|
||||
|
||||
对于 Skills(见 [Skills](/zh-CN/tools/skills)),目前仍缺少的内容:
|
||||
对于 Skills(见 [Skills](/zh-CN/tools/skills)),仍然缺少的是:
|
||||
|
||||
- **决策能力:** 当提示词中列出 Skills 时,智能体是否会选择正确的 skill(或避免选择无关 skill)?
|
||||
- **合规性:** 智能体在使用前是否会读取 `SKILL.md`,并遵循要求的步骤 / 参数?
|
||||
- **决策能力:** 当提示词中列出 Skills 时,智能体是否会选择正确的 Skills(或避开无关的 Skills)?
|
||||
- **合规性:** 智能体是否会在使用前读取 `SKILL.md`,并遵循要求的步骤 / 参数?
|
||||
- **工作流契约:** 断言工具顺序、会话历史延续和沙箱边界的多轮场景。
|
||||
|
||||
未来的评估应优先保持确定性:
|
||||
|
||||
- 一个使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、skill 文件读取和会话接线。
|
||||
- 一小组聚焦 skill 的场景(使用 vs 避免、门禁、提示注入)。
|
||||
- 只有在对 CI 安全的测试套件就位之后,才添加可选的实时评估(显式启用、受环境变量控制)。
|
||||
- 一个使用 mock provider 的场景运行器,用于断言工具调用 + 顺序、skill 文件读取和会话接线。
|
||||
- 一小组聚焦 Skills 的场景(使用 vs 避免、门控、提示注入)。
|
||||
- 只有在对 CI 安全的测试套件到位之后,才添加可选的实时评估(需显式启用并受环境变量门控)。
|
||||
|
||||
## 契约测试(插件和渠道形状)
|
||||
|
||||
契约测试用于验证每个已注册插件和渠道都符合其
|
||||
接口契约。它们会遍历所有已发现的插件,并运行一套
|
||||
形状和行为断言。默认的 `pnpm test` 单元通道会刻意
|
||||
跳过这些共享接缝和冒烟文件;当你修改共享渠道或提供商入口面时,
|
||||
请显式运行契约命令。
|
||||
契约测试用于验证每个已注册插件和渠道都符合其接口契约。它们会遍历所有已发现的插件,并运行一套形状和行为断言。默认的 `pnpm test` 单元通道会刻意跳过这些共享接缝和冒烟文件;当你修改共享渠道或 provider 界面时,请显式运行契约命令。
|
||||
|
||||
### 命令
|
||||
|
||||
- 所有契约:`pnpm test:contracts`
|
||||
- 仅渠道契约:`pnpm test:contracts:channels`
|
||||
- 仅提供商契约:`pnpm test:contracts:plugins`
|
||||
- 仅 provider 契约:`pnpm test:contracts:plugins`
|
||||
|
||||
### 渠道契约
|
||||
|
||||
位于 `src/channels/plugins/contracts/*.contract.test.ts`:
|
||||
|
||||
- **plugin** - 基本插件形状(id、名称、能力)
|
||||
- **plugin** - 基本插件形状(id、name、capabilities)
|
||||
- **setup** - 设置向导契约
|
||||
- **session-binding** - 会话绑定行为
|
||||
- **outbound-payload** - 消息负载结构
|
||||
- **inbound** - 入站消息处理
|
||||
- **actions** - 渠道操作处理器
|
||||
- **threading** - 线程 ID 处理
|
||||
- **directory** - 目录 / 成员列表 API
|
||||
- **directory** - 目录 / roster API
|
||||
- **group-policy** - 群组策略强制执行
|
||||
|
||||
### 提供商 Status 契约
|
||||
### Provider Status 契约
|
||||
|
||||
位于 `src/plugins/contracts/*.contract.test.ts`。
|
||||
|
||||
- **status** - 渠道 Status 探测
|
||||
- **registry** - 插件注册表形状
|
||||
|
||||
### 提供商契约
|
||||
### Provider 契约
|
||||
|
||||
位于 `src/plugins/contracts/*.contract.test.ts`:
|
||||
|
||||
@ -620,30 +654,30 @@ MCP 子进程会在每次运行后退出。
|
||||
- **catalog** - 模型目录 API
|
||||
- **discovery** - 插件发现
|
||||
- **loader** - 插件加载
|
||||
- **runtime** - 提供商运行时
|
||||
- **runtime** - provider 运行时
|
||||
- **shape** - 插件形状 / 接口
|
||||
- **wizard** - 设置向导
|
||||
|
||||
### 何时运行
|
||||
|
||||
- 修改 `plugin-sdk` 导出或子路径之后
|
||||
- 添加或修改渠道或提供商插件之后
|
||||
- 添加或修改渠道或 provider 插件之后
|
||||
- 重构插件注册或发现逻辑之后
|
||||
|
||||
契约测试会在 CI 中运行,并且不需要真实 API 密钥。
|
||||
契约测试会在 CI 中运行,并且不需要真实 API key。
|
||||
|
||||
## 添加回归测试(指南)
|
||||
## 添加回归测试(指导)
|
||||
|
||||
当你修复一个在实时环境中发现的提供商 / 模型问题时:
|
||||
当你修复一个在实时环境中发现的 provider / model 问题时:
|
||||
|
||||
- 如果可能,添加一个对 CI 安全的回归测试(模拟 / stub 提供商,或捕获精确的请求形状转换)
|
||||
- 如果它天生只能在实时环境中复现(速率限制、认证策略),则保持实时测试范围狭窄,并通过环境变量显式启用
|
||||
- 优先针对能捕获该缺陷的最小层:
|
||||
- 提供商请求转换 / 重放缺陷 → 直接模型测试
|
||||
- gateway 会话 / 历史 / 工具流水线缺陷 → gateway 实时冒烟或对 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 时故意失败,以确保新类别不会被静默跳过。
|
||||
- 如果可能,添加一个对 CI 安全的回归测试(mock / stub provider,或捕获精确的请求形状转换)
|
||||
- 如果问题本质上只能在实时环境中复现(速率限制、认证策略),请将实时测试保持为狭窄范围,并通过环境变量选择性启用
|
||||
- 优先瞄准能捕获该缺陷的最小层级:
|
||||
- provider 请求转换 / 重放缺陷 → 直接模型测试
|
||||
- gateway 会话 / 历史 / 工具管道缺陷 → gateway 实时冒烟测试或对 CI 安全的 gateway mock 测试
|
||||
- SecretRef 遍历防护栏:
|
||||
- `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言会拒绝遍历段执行 id。
|
||||
- 如果你在 `src/secrets/target-registry-data.ts` 中添加了新的 `includeInPlan` SecretRef 目标族,请更新该测试中的 `classifyTargetClass`。该测试会在遇到未分类目标 id 时故意失败,以确保新类别不会被静默跳过。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -1,53 +1,53 @@
|
||||
---
|
||||
read_when:
|
||||
- 你正在构建一个 OpenClaw 插件
|
||||
- 你需要发布一个插件配置 schema,或调试插件校验错误
|
||||
summary: 插件清单 + JSON schema 要求(严格配置校验)
|
||||
- 你需要发布一个插件配置 schema,或调试插件验证错误
|
||||
summary: 插件清单 + JSON schema 要求(严格配置验证)
|
||||
title: 插件清单
|
||||
x-i18n:
|
||||
generated_at: "2026-04-27T16:20:34Z"
|
||||
generated_at: "2026-04-27T19:38:34Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 662f374ff4a66b8a6f95dd5f0be8ac804a7b350f4f98d4e703d869b7b28804b9
|
||||
source_hash: 4a700ecd97b16735e415814731841c686490f12d0e303c09800afe664880ec3e
|
||||
source_path: plugins/manifest.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
这个页面仅适用于**原生 OpenClaw 插件清单**。
|
||||
此页面仅适用于**原生 OpenClaw 插件清单**。
|
||||
|
||||
关于兼容的 bundle 布局,请参阅 [插件 bundle](/zh-CN/plugins/bundles)。
|
||||
关于兼容的 bundle 布局,请参阅 [Plugin bundles](/zh-CN/plugins/bundles)。
|
||||
|
||||
兼容的 bundle 格式使用不同的清单文件:
|
||||
|
||||
- Codex bundle:`.codex-plugin/plugin.json`
|
||||
- Claude bundle:`.claude-plugin/plugin.json`,或不带清单的默认 Claude 组件布局
|
||||
- Claude bundle:`.claude-plugin/plugin.json` 或不带清单的默认 Claude 组件布局
|
||||
- Cursor bundle:`.cursor-plugin/plugin.json`
|
||||
|
||||
OpenClaw 也会自动检测这些 bundle 布局,但它们不会根据这里描述的 `openclaw.plugin.json` schema 进行校验。
|
||||
OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的 `openclaw.plugin.json` schema 对它们进行验证。
|
||||
|
||||
对于兼容 bundle,当布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据、声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值,以及受支持的 hook pack。
|
||||
对于兼容 bundle,当其布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据、声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值,以及支持的 hook pack。
|
||||
|
||||
每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用这个清单在**不执行插件代码的情况下**校验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。
|
||||
每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码**的情况下验证配置。缺失或无效的清单会被视为插件错误,并阻止配置验证。
|
||||
|
||||
请参阅完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
|
||||
关于原生能力模型以及当前的外部兼容性指导,请参阅:
|
||||
关于原生能力模型和当前外部兼容性指导,请参阅:
|
||||
[能力模型](/zh-CN/plugins/architecture#public-capability-model)。
|
||||
|
||||
## 这个文件的作用
|
||||
## 此文件的作用
|
||||
|
||||
`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下面的所有内容都必须足够轻量,以便在不启动插件运行时的情况下进行检查。
|
||||
`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下面的所有内容都必须足够轻量,以便无需启动插件运行时即可检查。
|
||||
|
||||
**用于:**
|
||||
|
||||
- 插件标识、配置校验,以及配置 UI 提示
|
||||
- 认证、新手引导和设置元数据(别名、自动启用、provider 环境变量、认证选项)
|
||||
- 插件身份、配置验证,以及配置 UI 提示
|
||||
- 认证、新手引导和设置元数据(别名、自动启用、提供商环境变量、认证选项)
|
||||
- 控制平面界面的激活提示
|
||||
- 简写模型系列归属
|
||||
- 简写模型家族归属
|
||||
- 静态能力归属快照(`contracts`)
|
||||
- 供共享 `openclaw qa` 主机检查的 QA 运行器元数据
|
||||
- 合并到目录和校验界面的渠道专用配置元数据
|
||||
- 供共享 `openclaw qa` 宿主检查的 QA 运行器元数据
|
||||
- 合并到目录和验证界面中的渠道特定配置元数据
|
||||
|
||||
**不要用于:**注册运行时行为、声明代码入口点,或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。
|
||||
**不要用于:** 注册运行时行为、声明代码入口点,或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。
|
||||
|
||||
## 最小示例
|
||||
|
||||
@ -143,69 +143,69 @@ OpenClaw 也会自动检测这些 bundle 布局,但它们不会根据这里描
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------------------------------ | -------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `id` | 是 | `string` | 规范插件 id。这是在 `plugins.entries.<id>` 中使用的 id。 |
|
||||
| `configSchema` | 是 | `object` | 该插件配置的内联 JSON Schema。 |
|
||||
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略它,或设置为任何非 `true` 的值,以使插件默认保持禁用。 |
|
||||
| `legacyPluginIds` | 否 | `string[]` | 会规范化为该规范插件 id 的旧版 id。 |
|
||||
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些 provider id 时,应自动启用该插件。 |
|
||||
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明由 `plugins.slots.*` 使用的互斥插件类型。 |
|
||||
| `channels` | 否 | `string[]` | 该插件拥有的渠道 id。用于发现和配置校验。 |
|
||||
| `providers` | 否 | `string[]` | 该插件拥有的 provider id。 |
|
||||
| `providerDiscoveryEntry` | 否 | `string` | 轻量级 provider 发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、限定于清单范围内的 provider 目录元数据。 |
|
||||
| `modelSupport` | 否 | `object` | 由清单拥有的简写模型系列元数据,用于在运行时之前自动加载插件。 |
|
||||
| `modelCatalog` | 否 | `object` | 由声明式模型目录元数据组成,适用于该插件拥有的 provider。这是未来只读列表、新手引导、模型选择器、别名和抑制功能的控制平面契约,且无需加载插件运行时。 |
|
||||
| `modelPricing` | 否 | `object` | 由 provider 拥有的外部定价查找策略。用它让本地/自托管 provider 退出远程定价目录,或将 provider 引用映射到 OpenRouter/LiteLLM 目录 id,而无需在核心中硬编码 provider id。 |
|
||||
| `modelIdNormalization` | 否 | `object` | 由 provider 拥有的模型 id 别名/前缀清理逻辑,必须在 provider 运行时加载之前运行。 |
|
||||
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的端点 host/baseUrl 元数据,用于那些核心必须在 provider 运行时加载之前分类的 provider 路由。 |
|
||||
| `providerRequest` | 否 | `object` | 低成本的 provider 系列和请求兼容性元数据,供通用请求策略在 provider 运行时加载之前使用。 |
|
||||
| `cliBackends` | 否 | `string[]` | 该插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
|
||||
| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用;其插件拥有的合成认证钩子应在运行时加载之前的冷启动模型发现期间进行探测。 |
|
||||
| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API key 值,表示非密钥的本地、OAuth 或环境凭证状态。 |
|
||||
| `commandAliases` | 否 | `object[]` | 由该插件拥有的命令名称,应在运行时加载之前生成带有插件感知能力的配置和 CLI 诊断信息。 |
|
||||
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 已弃用的兼容性环境变量元数据,用于 provider 认证/状态查找。对于新插件,优先使用 `setup.providers[].envVars`;在弃用窗口期内,OpenClaw 仍会读取此字段。 |
|
||||
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个 provider id 进行认证查找的 provider id,例如与基础 provider 共享 API key 和认证配置文件的编码 provider。 |
|
||||
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的低成本渠道环境变量元数据。将其用于通用启动/配置辅助工具应可见的、由环境变量驱动的渠道设置或认证界面。 |
|
||||
| `providerAuthChoices` | 否 | `object[]` | 低成本认证选项元数据,用于新手引导选择器、首选 provider 解析和简单的 CLI 标志接线。 |
|
||||
| `activation` | 否 | `object` | 低成本激活规划器元数据,用于由 provider、命令、渠道、路由和能力触发的加载。仅为元数据;实际行为仍由插件运行时负责。 |
|
||||
| `setup` | 否 | `object` | 低成本设置/新手引导描述符,供发现和设置界面在不加载插件运行时的情况下检查。 |
|
||||
| `qaRunners` | 否 | `object[]` | 由共享 `openclaw qa` 主机在插件运行时加载之前使用的低成本 QA 运行器描述符。 |
|
||||
| `contracts` | 否 | `object` | 静态内置能力快照,用于外部认证钩子、语音、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属。 |
|
||||
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 用于在 `contracts.mediaUnderstandingProviders` 中声明的 provider id 的低成本媒体理解默认值。 |
|
||||
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,会在运行时加载之前合并到发现和校验界面中。 |
|
||||
| `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 |
|
||||
| `name` | 否 | `string` | 人类可读的插件名称。 |
|
||||
| `description` | 否 | `string` | 在插件界面中显示的简短摘要。 |
|
||||
| `version` | 否 | `string` | 仅供参考的插件版本。 |
|
||||
| `uiHints` | 否 | `Record<string, object>` | 配置字段的 UI 标签、占位符和敏感性提示。 |
|
||||
| `id` | 是 | `string` | 规范插件 id。这是 `plugins.entries.<id>` 中使用的 id。 |
|
||||
| `configSchema` | 是 | `object` | 该插件配置的内联 JSON Schema。 |
|
||||
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略它,或将其设置为任何非 `true` 的值,则插件默认保持禁用。 |
|
||||
| `legacyPluginIds` | 否 | `string[]` | 会规范化为此规范插件 id 的旧版 id。 |
|
||||
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些提供商 id 时,应自动启用此插件。 |
|
||||
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的排他性插件类型。 |
|
||||
| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于设备发现和配置验证。 |
|
||||
| `providers` | 否 | `string[]` | 由此插件拥有的提供商 id。 |
|
||||
| `providerDiscoveryEntry` | 否 | `string` | 轻量级的提供商设备发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、限定于清单范围的提供商目录元数据。 |
|
||||
| `modelSupport` | 否 | `object` | 由清单拥有的简写模型家族元数据,用于在运行时之前自动加载插件。 |
|
||||
| `modelCatalog` | 否 | `object` | 由此插件拥有的提供商声明式模型目录元数据。这是未来只读列表、新手引导、模型选择器、别名和抑制功能的控制平面契约,无需加载插件运行时。 |
|
||||
| `modelPricing` | 否 | `object` | 由提供商拥有的外部定价查找策略。用它可将本地/自托管提供商排除在远程定价目录之外,或将提供商引用映射到 OpenRouter/LiteLLM 目录 id,而无需在核心中硬编码提供商 id。 |
|
||||
| `modelIdNormalization` | 否 | `object` | 由提供商拥有的模型 id 别名/前缀清理规则,必须在提供商运行时加载前运行。 |
|
||||
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的端点 host/baseUrl 元数据,用于核心必须在提供商运行时加载前分类的提供商路由。 |
|
||||
| `providerRequest` | 否 | `object` | 轻量级的提供商家族和请求兼容性元数据,供通用请求策略在提供商运行时加载前使用。 |
|
||||
| `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
|
||||
| `syntheticAuthRefs` | 否 | `string[]` | 提供商或 CLI 后端引用;在运行时加载前的冷模型设备发现期间,应探测其由插件拥有的合成认证钩子。 |
|
||||
| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API key 值,用于表示非密钥的本地、OAuth 或环境凭证状态。 |
|
||||
| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称;这些命令应在运行时加载前生成插件感知的配置和 CLI 诊断信息。 |
|
||||
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 已弃用的兼容性环境变量元数据,用于提供商认证/Status 查找。对于新插件,优先使用 `setup.providers[].envVars`;在弃用窗口期内,OpenClaw 仍会读取此字段。 |
|
||||
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个提供商 id 进行认证查找的提供商 id,例如与基础提供商共享 API key 和认证配置的 coding 提供商。 |
|
||||
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的轻量级渠道环境变量元数据。将其用于由环境变量驱动的渠道设置或认证界面,使通用启动/配置辅助工具能够识别。 |
|
||||
| `providerAuthChoices` | 否 | `object[]` | 轻量级认证选项元数据,用于新手引导选择器、首选提供商解析,以及简单的 CLI 标志接线。 |
|
||||
| `activation` | 否 | `object` | 轻量级激活规划器元数据,用于由提供商、命令、渠道、路由和能力触发的加载。仅为元数据;实际行为仍由插件运行时负责。 |
|
||||
| `setup` | 否 | `object` | 轻量级设置/新手引导描述符,供设备发现和设置界面在不加载插件运行时的情况下检查。 |
|
||||
| `qaRunners` | 否 | `object[]` | 由共享 `openclaw qa` 宿主在插件运行时加载前使用的轻量级 QA 运行器描述符。 |
|
||||
| `contracts` | 否 | `object` | 针对外部认证钩子、语音、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、web 抓取、web 搜索和工具归属的静态内置能力快照。 |
|
||||
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 为 `contracts.mediaUnderstandingProviders` 中声明的提供商 id 提供的轻量级媒体理解默认值。 |
|
||||
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,在运行时加载前合并到设备发现和验证界面中。 |
|
||||
| `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 |
|
||||
| `name` | 否 | `string` | 人类可读的插件名称。 |
|
||||
| `description` | 否 | `string` | 显示在插件界面中的简短摘要。 |
|
||||
| `version` | 否 | `string` | 信息性插件版本。 |
|
||||
| `uiHints` | 否 | `Record<string, object>` | 配置字段的 UI 标签、占位符和敏感性提示。 |
|
||||
|
||||
## `providerAuthChoices` 参考
|
||||
|
||||
每个 `providerAuthChoices` 条目描述一个新手引导或认证选项。
|
||||
OpenClaw 会在 provider 运行时加载之前读取它。
|
||||
provider 设置列表会使用这些清单选项、由描述符派生的设置选项,以及安装目录元数据,而无需加载 provider 运行时。
|
||||
OpenClaw 会在提供商运行时加载前读取它。
|
||||
提供商设置列表使用这些清单选项、从描述符派生的设置选项,以及安装目录元数据,而无需加载提供商运行时。
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| --------------------- | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `provider` | 是 | `string` | 此选项所属的 provider id。 |
|
||||
| `method` | 是 | `string` | 要分派到的认证方法 id。 |
|
||||
| `choiceId` | 是 | `string` | 供新手引导和 CLI 流程使用的稳定认证选项 id。 |
|
||||
| `choiceLabel` | 否 | `string` | 面向用户的标签。如果省略,OpenClaw 会回退到 `choiceId`。 |
|
||||
| `choiceHint` | 否 | `string` | 选择器中的简短帮助文本。 |
|
||||
| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,值越小排序越靠前。 |
|
||||
| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏该选项,但仍允许手动通过 CLI 选择。 |
|
||||
| `deprecatedChoiceIds` | 否 | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 |
|
||||
| `groupId` | 否 | `string` | 用于对相关选项分组的可选组 id。 |
|
||||
| `groupLabel` | 否 | `string` | 该组面向用户的标签。 |
|
||||
| `groupHint` | 否 | `string` | 该组的简短帮助文本。 |
|
||||
| `optionKey` | 否 | `string` | 用于简单单标志认证流程的内部选项键。 |
|
||||
| `cliFlag` | 否 | `string` | CLI 标志名称,例如 `--openrouter-api-key`。 |
|
||||
| `cliOption` | 否 | `string` | 完整的 CLI 选项形式,例如 `--openrouter-api-key <key>`。 |
|
||||
| `cliDescription` | 否 | `string` | CLI 帮助中使用的描述。 |
|
||||
| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如果省略,默认值为 `["text-inference"]`。 |
|
||||
| `provider` | 是 | `string` | 此选项所属的提供商 id。 |
|
||||
| `method` | 是 | `string` | 要分发到的认证方法 id。 |
|
||||
| `choiceId` | 是 | `string` | 供新手引导和 CLI 流程使用的稳定认证选项 id。 |
|
||||
| `choiceLabel` | 否 | `string` | 面向用户的标签。如果省略,OpenClaw 会回退到 `choiceId`。 |
|
||||
| `choiceHint` | 否 | `string` | 选择器的简短辅助文本。 |
|
||||
| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,值越小排序越靠前。 |
|
||||
| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏该选项,但仍允许手动 CLI 选择。 |
|
||||
| `deprecatedChoiceIds` | 否 | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 |
|
||||
| `groupId` | 否 | `string` | 用于将相关选项分组的可选组 id。 |
|
||||
| `groupLabel` | 否 | `string` | 该组面向用户的标签。 |
|
||||
| `groupHint` | 否 | `string` | 该组的简短辅助文本。 |
|
||||
| `optionKey` | 否 | `string` | 用于简单单标志认证流程的内部选项键。 |
|
||||
| `cliFlag` | 否 | `string` | CLI 标志名称,例如 `--openrouter-api-key`。 |
|
||||
| `cliOption` | 否 | `string` | 完整的 CLI 选项形式,例如 `--openrouter-api-key <key>`。 |
|
||||
| `cliDescription` | 否 | `string` | 用于 CLI 帮助的说明文本。 |
|
||||
| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如果省略,默认值为 `["text-inference"]`。 |
|
||||
|
||||
## `commandAliases` 参考
|
||||
|
||||
当插件拥有某个运行时命令名称,而用户可能会误将其放入 `plugins.allow`,或尝试将其作为根级 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用这些元数据在不导入插件运行时代码的情况下提供诊断信息。
|
||||
当插件拥有一个运行时命令名称,而用户可能误将其放入 `plugins.allow`,或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用此元数据来生成诊断信息,而无需导入插件运行时代码。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -221,20 +221,20 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------ | -------- | ----------------- | ----------------------------------------------------------------------- |
|
||||
| `name` | 是 | `string` | 属于此插件的命令名称。 |
|
||||
| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根级 CLI 命令。 |
|
||||
| `cliCommand` | 否 | `string` | 若存在,用于 CLI 操作时建议的相关根级 CLI 命令。 |
|
||||
| `name` | 是 | `string` | 属于此插件的命令名称。 |
|
||||
| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根 CLI 命令。 |
|
||||
| `cliCommand` | 否 | `string` | 如果存在,可建议用于 CLI 操作的相关根 CLI 命令。 |
|
||||
|
||||
## `activation` 参考
|
||||
|
||||
当插件可以低成本地声明哪些控制平面事件应将其纳入激活/加载计划时,请使用 `activation`。
|
||||
当插件可以以低成本声明哪些控制平面事件应将其纳入激活/加载计划时,请使用 `activation`。
|
||||
|
||||
此块是规划器元数据,而不是生命周期 API。它不会注册运行时行为,不会替代 `register(...)`,也不保证插件代码已经执行。激活规划器使用这些字段来缩小候选插件范围,然后才回退到现有的清单归属元数据,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和 hooks。
|
||||
此块是规划器元数据,不是生命周期 API。它不会注册运行时行为,不会替代 `register(...)`,也不保证插件代码已经执行。激活规划器使用这些字段缩小候选插件范围,然后再回退到现有的清单归属元数据,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和钩子。
|
||||
|
||||
优先使用已经能够描述归属关系的最窄元数据。如果这些字段能够表达该关系,请使用 `providers`、`channels`、`commandAliases`、设置描述符或 `contracts`。当这些归属字段无法表示额外的规划器提示时,再使用 `activation`。
|
||||
对于 `claude-cli`、`codex-cli` 或 `google-gemini-cli` 这样的 CLI 运行时别名,请使用顶层 `cliBackends`;`activation.onAgentHarnesses` 仅用于那些尚无归属字段的嵌入式 Agent harness id。
|
||||
优先使用已经描述归属关系的最窄元数据。能用 `providers`、`channels`、`commandAliases`、设置描述符或 `contracts` 表达关系时,就使用这些字段。只有在这些归属字段无法表达时,才使用 `activation` 提供额外的规划器提示。
|
||||
对于 `claude-cli`、`codex-cli` 或 `google-gemini-cli` 这类 CLI 运行时别名,请使用顶层 `cliBackends`;`activation.onAgentHarnesses` 仅用于那些尚无归属字段的嵌入式智能体 harness id。
|
||||
|
||||
此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时/插件入口点。当前使用方将其作为更广泛插件加载之前的缩小范围提示,因此缺失激活元数据通常只会带来性能损耗;只要旧版清单归属回退仍然存在,它就不应影响正确性。
|
||||
此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时/插件入口点。当前使用方将它作为在更广泛插件加载前进行缩小范围的提示,因此缺少激活元数据通常只会影响性能;在旧版清单归属回退仍然存在时,它不应改变正确性。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -251,30 +251,28 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------------ | -------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `onProviders` | 否 | `string[]` | 应将此插件纳入激活/加载计划的 provider id。 |
|
||||
| `onAgentHarnesses` | 否 | `string[]` | 应将此插件纳入激活/加载计划的嵌入式 Agent harness 运行时 id。对于 CLI 后端别名,请使用顶层 `cliBackends`。 |
|
||||
| `onCommands` | 否 | `string[]` | 应将此插件纳入激活/加载计划的命令 id。 |
|
||||
| `onChannels` | 否 | `string[]` | 应将此插件纳入激活/加载计划的渠道 id。 |
|
||||
| `onRoutes` | 否 | `string[]` | 应将此插件纳入激活/加载计划的路由类型。 |
|
||||
| `onConfigPaths` | 否 | `string[]` | 当这些根相对配置路径存在且未被显式禁用时,应将此插件纳入启动/加载计划。 |
|
||||
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划中使用的宽泛能力提示。若可能,优先使用更窄的字段。 |
|
||||
| `onProviders` | 否 | `string[]` | 应将此插件纳入激活/加载计划的提供商 id。 |
|
||||
| `onAgentHarnesses` | 否 | `string[]` | 应将此插件纳入激活/加载计划的嵌入式智能体 harness 运行时 id。对于 CLI 后端别名,请使用顶层 `cliBackends`。 |
|
||||
| `onCommands` | 否 | `string[]` | 应将此插件纳入激活/加载计划的命令 id。 |
|
||||
| `onChannels` | 否 | `string[]` | 应将此插件纳入激活/加载计划的渠道 id。 |
|
||||
| `onRoutes` | 否 | `string[]` | 应将此插件纳入激活/加载计划的路由类型。 |
|
||||
| `onConfigPaths` | 否 | `string[]` | 当某个相对根路径的配置路径存在且未被显式禁用时,应将此插件纳入启动/加载计划。 |
|
||||
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的宽泛能力提示。可能时优先使用更窄的字段。 |
|
||||
|
||||
当前的实际使用方:
|
||||
当前实时使用方:
|
||||
|
||||
- 由命令触发的 CLI 规划会回退到旧版
|
||||
- 由命令触发的 CLI 规划会回退到旧版的
|
||||
`commandAliases[].cliCommand` 或 `commandAliases[].name`
|
||||
- Agent 运行时启动规划对嵌入式 harness 使用 `activation.onAgentHarnesses`,对 CLI 运行时别名使用顶层 `cliBackends[]`
|
||||
- 由渠道触发的设置/渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]`
|
||||
归属
|
||||
- 启动时插件规划会对非渠道的根级配置界面使用 `activation.onConfigPaths`,例如内置浏览器插件的 `browser` 配置块
|
||||
- 由 provider 触发的设置/运行时规划在缺少显式 provider
|
||||
激活元数据时,会回退到旧版 `providers[]` 和顶层 `cliBackends[]` 归属
|
||||
- 智能体运行时启动规划对嵌入式 harness 使用 `activation.onAgentHarnesses`,对 CLI 运行时别名使用顶层 `cliBackends[]`
|
||||
- 由渠道触发的设置/渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]` 归属
|
||||
- 启动插件规划对非渠道的根配置界面使用 `activation.onConfigPaths`,例如内置浏览器插件的 `browser` 块
|
||||
- 由提供商触发的设置/运行时规划在缺少显式提供商激活元数据时,会回退到旧版 `providers[]` 和顶层 `cliBackends[]` 归属
|
||||
|
||||
规划器诊断可以区分显式激活提示和清单归属回退。例如,`activation-command-hint` 表示匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示规划器改为使用 `commandAliases` 归属。这些原因标签用于宿主诊断和测试;插件作者应继续声明最能描述归属关系的元数据。
|
||||
规划器诊断可以区分显式激活提示和清单归属回退。例如,`activation-command-hint` 表示匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示规划器改用了 `commandAliases` 归属。这些原因标签用于宿主诊断和测试;插件作者应继续声明最能描述归属关系的元数据。
|
||||
|
||||
## `qaRunners` 参考
|
||||
|
||||
当插件在共享 `openclaw qa` 根命令下提供一个或多个传输运行器时,请使用 `qaRunners`。请保持这些元数据轻量且静态;实际的 CLI 注册仍由插件运行时通过一个导出 `qaRunnerCliRegistrations` 的轻量 `runtime-api.ts` 界面负责。
|
||||
当插件在共享的 `openclaw qa` 根命令下贡献一个或多个传输运行器时,请使用 `qaRunners`。保持此元数据轻量且静态;实际的 CLI 注册仍由插件运行时通过导出 `qaRunnerCliRegistrations` 的轻量级 `runtime-api.ts` 接口负责。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -289,12 +287,12 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------- | -------- | -------- | ------------------------------------------------------------------ |
|
||||
| `commandName` | 是 | `string` | 挂载在 `openclaw qa` 下的子命令,例如 `matrix`。 |
|
||||
| `description` | 否 | `string` | 当共享宿主需要一个桩命令时使用的回退帮助文本。 |
|
||||
| `commandName` | 是 | `string` | 挂载在 `openclaw qa` 之下的子命令,例如 `matrix`。 |
|
||||
| `description` | 否 | `string` | 当共享宿主需要一个 stub 命令时使用的回退帮助文本。 |
|
||||
|
||||
## `setup` 参考
|
||||
|
||||
当设置和新手引导界面需要在运行时加载之前获取由插件拥有的低成本元数据时,请使用 `setup`。
|
||||
当设置和新手引导界面在运行时加载前需要由插件拥有的轻量级元数据时,请使用 `setup`。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -313,42 +311,40 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
|
||||
}
|
||||
```
|
||||
|
||||
顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是专用于设置的描述符界面,面向应保持为纯元数据的控制平面/设置流程。
|
||||
顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是用于控制平面/设置流程的、仅元数据的设置专用描述符界面。
|
||||
|
||||
存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现中优先采用的描述符优先查找界面。如果描述符只能缩小候选插件范围,而设置仍需要更丰富的设置期运行时钩子,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。
|
||||
存在时,`setup.providers` 和 `setup.cliBackends` 是设置设备发现的首选“描述符优先”查找界面。如果描述符只能缩小候选插件范围,而设置仍需要更丰富的设置时运行时钩子,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。
|
||||
|
||||
OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和环境变量查找。`providerAuthEnvVars` 在弃用窗口期间仍通过兼容适配器受支持,但仍在使用它的非内置插件会收到清单诊断。新插件应将设置/状态环境变量元数据放在 `setup.providers[].envVars` 上。
|
||||
OpenClaw 还会将 `setup.providers[].envVars` 纳入通用提供商认证和环境变量查找。`providerAuthEnvVars` 在弃用窗口期内仍通过兼容适配器受到支持,但仍在使用它的非内置插件会收到清单诊断信息。新插件应将设置/Status 环境变量元数据放在 `setup.providers[].envVars` 上。
|
||||
|
||||
当没有可用的 setup 入口,或 `setup.requiresRuntime: false`
|
||||
声明设置运行时不是必需时,OpenClaw 也可以从 `setup.providers[].authMethods`
|
||||
推导出简单的设置选项。对于自定义标签、CLI 标志、新手引导范围和助手元数据,显式的 `providerAuthChoices` 条目仍是首选。
|
||||
当没有可用的设置入口,或 `setup.requiresRuntime: false` 声明设置运行时并非必需时,OpenClaw 也可以根据 `setup.providers[].authMethods` 推导出简单的设置选项。对于自定义标签、CLI 标志、新手引导范围和助手元数据,显式的 `providerAuthChoices` 条目仍然是首选。
|
||||
|
||||
仅当这些描述符已足以满足设置界面需求时,才设置 `requiresRuntime: false`。OpenClaw 会将显式的 `false` 视为仅描述符契约,并且不会为设置查找执行 `setup-api` 或 `openclaw.setupEntry`。如果一个仅描述符插件仍然提供了这些设置运行时入口之一,OpenClaw 会报告一条附加诊断,并继续忽略它。省略 `requiresRuntime` 则保留旧版回退行为,这样那些添加了描述符但未添加该标志的现有插件不会出问题。
|
||||
仅当这些描述符已足以支持设置界面时,才设置 `requiresRuntime: false`。OpenClaw 将显式的 `false` 视为仅描述符契约,并且不会为设置查找执行 `setup-api` 或 `openclaw.setupEntry`。如果一个仅描述符插件仍然提供了这些设置运行时入口之一,OpenClaw 会报告一个附加诊断,并继续忽略它。省略 `requiresRuntime` 会保留旧版回退行为,这样为现有插件添加描述符而未添加该标志时不会出错。
|
||||
|
||||
由于设置查找可能会执行由插件拥有的 `setup-api` 代码,因此规范化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值在所有已发现插件中必须保持唯一。归属不明确时会采取失败即关闭的策略,而不是按发现顺序选取一个“赢家”。
|
||||
由于设置查找可能执行插件拥有的 `setup-api` 代码,规范化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值在所有已发现插件之间必须保持唯一。归属不明确时会采用失败关闭,而不是按发现顺序选一个“赢家”。
|
||||
|
||||
当设置运行时确实执行时,如果 `setup-api` 注册了清单描述符未声明的 provider 或 CLI 后端,或者某个描述符没有匹配的运行时注册项,设置注册表诊断会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。
|
||||
当设置运行时确实执行时,如果 `setup-api` 注册了清单描述符未声明的提供商或 CLI 后端,或者某个描述符没有对应的运行时注册,设置注册表诊断就会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。
|
||||
|
||||
### `setup.providers` 参考
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------- | -------- | ---------- | ------------------------------------------------------------------------------------ |
|
||||
| `id` | 是 | `string` | 在设置或新手引导期间公开的 provider id。请确保规范化 id 在全局范围内唯一。 |
|
||||
| `authMethods` | 否 | `string[]` | 该 provider 在无需加载完整运行时的情况下支持的设置/认证方法 id。 |
|
||||
| `envVars` | 否 | `string[]` | 通用设置/状态界面可在插件运行时加载前检查的环境变量。 |
|
||||
| `id` | 是 | `string` | 在设置或新手引导期间公开的提供商 id。保持规范化 id 在全局唯一。 |
|
||||
| `authMethods` | 否 | `string[]` | 该提供商在不加载完整运行时的情况下支持的设置/认证方法 id。 |
|
||||
| `envVars` | 否 | `string[]` | 通用设置/Status 界面可在插件运行时加载前检查的环境变量。 |
|
||||
|
||||
### `setup` 字段
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------------ | -------- | ---------- | --------------------------------------------------------------------------------------------------- |
|
||||
| `providers` | 否 | `object[]` | 在设置和新手引导期间公开的 provider 设置描述符。 |
|
||||
| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查找的设置期后端 id。请确保规范化 id 在全局范围内唯一。 |
|
||||
| `configMigrations` | 否 | `string[]` | 属于该插件设置界面的配置迁移 id。 |
|
||||
| `requiresRuntime` | 否 | `boolean` | 在描述符查找之后,设置是否仍需要执行 `setup-api`。 |
|
||||
| `providers` | 否 | `object[]` | 在设置和新手引导期间公开的提供商设置描述符。 |
|
||||
| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查找的设置时后端 id。保持规范化 id 在全局唯一。 |
|
||||
| `configMigrations` | 否 | `string[]` | 由该插件设置界面拥有的配置迁移 id。 |
|
||||
| `requiresRuntime` | 否 | `boolean` | 在描述符查找之后,设置是否仍需要执行 `setup-api`。 |
|
||||
|
||||
## `uiHints` 参考
|
||||
|
||||
`uiHints` 是一个从配置字段名称到小型渲染提示的映射。
|
||||
`uiHints` 是一个从配置字段名称映射到小型渲染提示的映射表。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -367,16 +363,16 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ------------- | ---------- | --------------------------------------- |
|
||||
| `label` | `string` | 面向用户的字段标签。 |
|
||||
| `help` | `string` | 简短帮助文本。 |
|
||||
| `tags` | `string[]` | 可选的 UI 标签。 |
|
||||
| `advanced` | `boolean` | 将该字段标记为高级项。 |
|
||||
| `sensitive` | `boolean` | 将该字段标记为密钥或敏感信息。 |
|
||||
| `placeholder` | `string` | 表单输入的占位文本。 |
|
||||
| `label` | `string` | 面向用户的字段标签。 |
|
||||
| `help` | `string` | 简短辅助文本。 |
|
||||
| `tags` | `string[]` | 可选的 UI 标签。 |
|
||||
| `advanced` | `boolean` | 将该字段标记为高级项。 |
|
||||
| `sensitive` | `boolean` | 将该字段标记为密钥或敏感信息。 |
|
||||
| `placeholder` | `string` | 表单输入的占位文本。 |
|
||||
|
||||
## `contracts` 参考
|
||||
|
||||
仅当 OpenClaw 可以在不导入插件运行时的情况下读取静态能力归属元数据时,才使用 `contracts`。
|
||||
仅在 OpenClaw 可无需导入插件运行时就能读取的静态能力归属元数据场景下使用 `contracts`。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -402,30 +398,30 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| -------------------------------- | ---------- | --------------------------------------------------------------------- |
|
||||
| `embeddedExtensionFactories` | `string[]` | Codex app-server 扩展工厂 id,目前为 `codex-app-server`。 |
|
||||
| `agentToolResultMiddleware` | `string[]` | 内置插件可为其注册工具结果中间件的运行时 id。 |
|
||||
| `externalAuthProviders` | `string[]` | 此插件拥有其外部认证配置文件钩子的 provider id。 |
|
||||
| `speechProviders` | `string[]` | 此插件拥有的语音 provider id。 |
|
||||
| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转录 provider id。 |
|
||||
| `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音 provider id。 |
|
||||
| `memoryEmbeddingProviders` | `string[]` | 此插件拥有的 Memory 嵌入 provider id。 |
|
||||
| `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解 provider id。 |
|
||||
| `imageGenerationProviders` | `string[]` | 此插件拥有的图像生成 provider id。 |
|
||||
| `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成 provider id。 |
|
||||
| `webFetchProviders` | `string[]` | 此插件拥有的网页抓取 provider id。 |
|
||||
| `webSearchProviders` | `string[]` | 此插件拥有的网页搜索 provider id。 |
|
||||
| `migrationProviders` | `string[]` | 此插件在 `openclaw migrate` 中拥有的导入 provider id。 |
|
||||
| `tools` | `string[]` | 此插件在内置契约检查中拥有的智能体工具名称。 |
|
||||
| `embeddedExtensionFactories` | `string[]` | Codex app-server 扩展工厂 id,目前为 `codex-app-server`。 |
|
||||
| `agentToolResultMiddleware` | `string[]` | 内置插件可为其注册工具结果中间件的运行时 id。 |
|
||||
| `externalAuthProviders` | `string[]` | 此插件拥有其外部认证配置钩子的提供商 id。 |
|
||||
| `speechProviders` | `string[]` | 此插件拥有的语音提供商 id。 |
|
||||
| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转录提供商 id。 |
|
||||
| `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音提供商 id。 |
|
||||
| `memoryEmbeddingProviders` | `string[]` | 此插件拥有的 Memory 嵌入提供商 id。 |
|
||||
| `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解提供商 id。 |
|
||||
| `imageGenerationProviders` | `string[]` | 此插件拥有的图像生成提供商 id。 |
|
||||
| `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成提供商 id。 |
|
||||
| `webFetchProviders` | `string[]` | 此插件拥有的 web 抓取提供商 id。 |
|
||||
| `webSearchProviders` | `string[]` | 此插件拥有的 web 搜索提供商 id。 |
|
||||
| `migrationProviders` | `string[]` | 此插件为 `openclaw migrate` 拥有的导入提供商 id。 |
|
||||
| `tools` | `string[]` | 此插件为内置契约检查拥有的智能体工具名称。 |
|
||||
|
||||
`contracts.embeddedExtensionFactories` 被保留用于内置的、仅限 Codex app-server 的扩展工厂。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并通过 `api.registerAgentToolResultMiddleware(...)` 进行注册。外部插件不能注册工具结果中间件,因为该接缝可以在模型看到之前重写高信任度的工具输出。
|
||||
`contracts.embeddedExtensionFactories` 保留用于内置的、仅适用于 Codex app-server 的扩展工厂。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并通过 `api.registerAgentToolResultMiddleware(...)` 注册。外部插件不能注册工具结果中间件,因为该接口可能会在模型看到之前重写高信任度工具输出。
|
||||
|
||||
实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明的插件仍可通过已弃用的兼容性回退运行,但该回退更慢,并将在迁移窗口结束后移除。
|
||||
实现 `resolveExternalAuthProfiles` 的提供商插件应声明 `contracts.externalAuthProviders`。未声明的插件仍可通过已弃用的兼容性回退运行,但该回退更慢,并将在迁移窗口结束后移除。
|
||||
|
||||
内置的 Memory 嵌入 provider 应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 之类的内置适配器。独立 CLI 路径使用此清单契约,在完整 Gateway 网关运行时注册 provider 之前,仅加载拥有该适配器的插件。
|
||||
内置 Memory 嵌入提供商应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 之类的内置适配器。独立 CLI 路径使用此清单契约,在完整 Gateway 网关运行时注册提供商之前仅加载拥有该适配器的插件。
|
||||
|
||||
## `mediaUnderstandingProviderMetadata` 参考
|
||||
|
||||
当媒体理解 provider 具有默认模型、自动认证回退优先级,或通用核心辅助工具在运行时加载前所需的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。键也必须在 `contracts.mediaUnderstandingProviders` 中声明。
|
||||
当媒体理解提供商具有默认模型、自动认证回退优先级,或泛型核心辅助工具在运行时加载前所需的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。键也必须在 `contracts.mediaUnderstandingProviders` 中声明。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -448,29 +444,29 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和
|
||||
}
|
||||
```
|
||||
|
||||
每个 provider 条目可以包含:
|
||||
每个提供商条目可以包含:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ---------------------- | ----------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| `capabilities` | `("image" \| "audio" \| "video")[]` | 此 provider 公开的媒体能力。 |
|
||||
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时使用的能力到模型默认值。 |
|
||||
| `autoPriority` | `Record<string, number>` | 在基于凭证的自动 provider 回退中,数字越小排序越靠前。 |
|
||||
| `nativeDocumentInputs` | `"pdf"[]` | 该 provider 支持的原生文档输入。 |
|
||||
| `capabilities` | `("image" \| "audio" \| "video")[]` | 该提供商公开的媒体能力。 |
|
||||
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时使用的能力到模型默认值映射。 |
|
||||
| `autoPriority` | `Record<string, number>` | 用于基于凭证的自动提供商回退时,数字越小排序越靠前。 |
|
||||
| `nativeDocumentInputs` | `"pdf"[]` | 该提供商支持的原生文档输入。 |
|
||||
|
||||
## `channelConfigs` 参考
|
||||
|
||||
当渠道插件在运行时加载前需要低成本配置元数据时,请使用 `channelConfigs`。对于已配置的外部渠道,如果没有可用的 setup 入口,或 `setup.requiresRuntime: false` 声明设置运行时不是必需的,只读渠道设置/状态发现可以直接使用这些元数据。
|
||||
当渠道插件在运行时加载前需要轻量级配置元数据时,请使用 `channelConfigs`。当没有可用的设置入口,或 `setup.requiresRuntime: false` 声明设置运行时并非必需时,只读渠道设置/Status 设备发现可以直接使用这些元数据来处理已配置的外部渠道。
|
||||
|
||||
`channelConfigs` 是插件清单元数据,而不是新的顶层用户配置区段。用户仍然在 `channels.<channel-id>` 下配置渠道实例。OpenClaw 读取清单元数据,以便在插件运行时代码执行之前判断哪个插件拥有该已配置渠道。
|
||||
`channelConfigs` 是插件清单元数据,不是新的顶层用户配置区段。用户仍然在 `channels.<channel-id>` 下配置渠道实例。OpenClaw 读取清单元数据,以便在插件运行时代码执行之前确定哪个插件拥有该已配置渠道。
|
||||
|
||||
对于渠道插件,`configSchema` 和 `channelConfigs` 描述的是不同路径:
|
||||
|
||||
- `configSchema` 校验 `plugins.entries.<plugin-id>.config`
|
||||
- `channelConfigs.<channel-id>.schema` 校验 `channels.<channel-id>`
|
||||
- `configSchema` 验证 `plugins.entries.<plugin-id>.config`
|
||||
- `channelConfigs.<channel-id>.schema` 验证 `channels.<channel-id>`
|
||||
|
||||
声明了 `channels[]` 的非内置插件,也应声明匹配的 `channelConfigs` 条目。否则,OpenClaw 仍然可以加载插件,但冷路径配置 schema、设置以及控制 UI 界面在插件运行时执行之前,将无法知道该渠道所拥有的选项结构。
|
||||
声明了 `channels[]` 的非内置插件也应声明匹配的 `channelConfigs` 条目。没有它们,OpenClaw 仍然可以加载插件,但冷路径配置 schema、设置和 Control UI 界面在插件运行时执行之前无法知道该渠道所拥有的选项结构。
|
||||
|
||||
`channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled` 和 `nativeSkillsAutoEnabled` 可以为在渠道运行时加载之前运行的命令配置检查声明静态 `auto` 默认值。内置渠道也可以通过 `package.json#openclaw.channel.commands` 与其他包拥有的渠道目录元数据一起发布相同的默认值。
|
||||
`channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled` 和 `nativeSkillsAutoEnabled` 可以为在渠道运行时加载前执行的命令配置检查声明静态 `auto` 默认值。内置渠道也可以通过 `package.json#openclaw.channel.commands` 发布相同的默认值,并与其其他由包拥有的渠道目录元数据一起提供。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -505,16 +501,16 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ------------- | ------------------------ | ----------------------------------------------------------------------------------------- |
|
||||
| `schema` | `object` | `channels.<id>` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 |
|
||||
| `uiHints` | `Record<string, object>` | 该渠道配置区段的可选 UI 标签/占位符/敏感性提示。 |
|
||||
| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 |
|
||||
| `description` | `string` | 用于检查和目录界面的简短渠道描述。 |
|
||||
| `commands` | `object` | 用于运行时前配置检查的静态原生命令和原生 Skills 自动默认值。 |
|
||||
| `preferOver` | `string[]` | 在选择界面中,该渠道应优先于的旧版或较低优先级插件 id。 |
|
||||
| `schema` | `object` | `channels.<id>` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 |
|
||||
| `uiHints` | `Record<string, object>` | 该渠道配置区段的可选 UI 标签/占位符/敏感性提示。 |
|
||||
| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 |
|
||||
| `description` | `string` | 用于检查和目录界面的简短渠道说明。 |
|
||||
| `commands` | `object` | 供运行时前配置检查使用的静态原生命令和原生 Skills 自动默认值。 |
|
||||
| `preferOver` | `string[]` | 在选择界面中,该渠道应优先于的旧版或较低优先级插件 id。 |
|
||||
|
||||
### 替换另一个渠道插件
|
||||
|
||||
当你的插件是某个渠道 id 的首选拥有者,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见情况包括重命名后的插件 id、取代内置插件的独立插件,或为保持配置兼容性而继续使用相同渠道 id 的维护分支。
|
||||
当你的插件是某个渠道 id 的首选拥有者,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见情况包括:插件 id 重命名、独立插件取代内置插件,或维护中的分支为了配置兼容性而保留相同的渠道 id。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -535,13 +531,13 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和
|
||||
}
|
||||
```
|
||||
|
||||
当配置了 `channels.chat` 时,OpenClaw 会同时考虑渠道 id 和首选插件 id。如果较低优先级的插件只是因为它是内置的或默认启用而被选中,OpenClaw 会在实际运行时配置中禁用它,以便只有一个插件拥有该渠道及其工具。显式用户选择仍然优先:如果用户显式启用了两个插件,OpenClaw 会保留这一选择,并报告重复渠道/工具诊断,而不是静默更改请求的插件集合。
|
||||
当配置了 `channels.chat` 时,OpenClaw 会同时考虑渠道 id 和首选插件 id。如果低优先级插件只是因为它是内置插件或默认启用而被选中,OpenClaw 会在有效运行时配置中禁用它,以便由一个插件独占该渠道及其工具。显式用户选择仍然优先:如果用户显式启用了两个插件,OpenClaw 会保留该选择,并报告重复的渠道/工具诊断,而不是静默更改请求的插件集合。
|
||||
|
||||
请将 `preferOver` 限定为那些确实能够提供同一渠道的插件 id。它不是通用优先级字段,也不会重命名用户配置键。
|
||||
将 `preferOver` 限定在确实可以提供同一渠道的插件 id 上。它不是通用优先级字段,也不会重命名用户配置键。
|
||||
|
||||
## `modelSupport` 参考
|
||||
|
||||
当 OpenClaw 应在插件运行时加载之前,根据像 `gpt-5.5` 或 `claude-sonnet-4.6` 这样的简写模型 id 推断你的 provider 插件时,请使用 `modelSupport`。
|
||||
当 OpenClaw 需要在插件运行时加载前,根据诸如 `gpt-5.5` 或 `claude-sonnet-4.6` 这类简写模型 id 推断你的提供商插件时,请使用 `modelSupport`。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -552,23 +548,23 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和
|
||||
}
|
||||
```
|
||||
|
||||
OpenClaw 按以下优先级处理:
|
||||
OpenClaw 按以下优先级应用:
|
||||
|
||||
- 显式 `provider/model` 引用使用拥有该模型的 `providers` 清单元数据
|
||||
- `modelPatterns` 优先于 `modelPrefixes`
|
||||
- 如果一个非内置插件和一个内置插件都匹配,则非内置插件优先
|
||||
- 剩余歧义会被忽略,直到用户或配置指定了 provider
|
||||
- 如果一个非内置插件和一个内置插件都匹配,则非内置插件胜出
|
||||
- 剩余歧义会被忽略,直到用户或配置指定提供商
|
||||
|
||||
字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --------------- | ---------- | ------------------------------------------------------------------------------- |
|
||||
| `modelPrefixes` | `string[]` | 针对简写模型 id 使用 `startsWith` 进行匹配的前缀。 |
|
||||
| `modelPatterns` | `string[]` | 在移除配置文件后缀后,针对简写模型 id 进行匹配的正则表达式源码。 |
|
||||
| `modelPrefixes` | `string[]` | 使用 `startsWith` 与简写模型 id 匹配的前缀。 |
|
||||
| `modelPatterns` | `string[]` | 在移除配置文件后缀后,用于匹配简写模型 id 的正则表达式源。 |
|
||||
|
||||
## `modelCatalog` 参考
|
||||
|
||||
当 OpenClaw 应在加载插件运行时之前了解 provider 模型元数据时,请使用 `modelCatalog`。这是由清单拥有的固定目录行、provider 别名、抑制规则和发现模式的来源。运行时刷新仍属于 provider 运行时代码,但清单会告知核心何时需要运行时。
|
||||
当 OpenClaw 需要在加载插件运行时之前了解提供商模型元数据时,请使用 `modelCatalog`。这是固定目录行、提供商别名、抑制规则和发现模式的清单拥有来源。运行时刷新仍属于提供商运行时代码,但清单会告诉核心何时需要运行时。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -621,51 +617,51 @@ OpenClaw 按以下优先级处理:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| `providers` | `Record<string, object>` | 此插件拥有的 provider id 的目录条目。键也应出现在顶层 `providers` 中。 |
|
||||
| `aliases` | `Record<string, object>` | 应解析到某个拥有的 provider 的 provider 别名,用于目录或抑制规划。 |
|
||||
| `suppressions` | `object[]` | 由于 provider 专属原因,由该插件抑制的、来自其他来源的模型条目。 |
|
||||
| `discovery` | `Record<string, "static" \| "refreshable" \| "runtime">` | provider 目录是可从清单元数据读取、可刷新到缓存,还是必须依赖运行时。 |
|
||||
| `providers` | `Record<string, object>` | 由该插件拥有的提供商 id 的目录条目。键也应出现在顶层 `providers` 中。 |
|
||||
| `aliases` | `Record<string, object>` | 应解析到某个拥有中的提供商、以用于目录或抑制规划的提供商别名。 |
|
||||
| `suppressions` | `object[]` | 由于提供商特定原因而由该插件抑制的、来自其他来源的模型条目。 |
|
||||
| `discovery` | `Record<string, "static" \| "refreshable" \| "runtime">` | 提供商目录是否可从清单元数据读取、刷新到缓存,或必须依赖运行时。 |
|
||||
|
||||
`aliases` 参与模型目录规划中的 provider 归属查找。别名目标必须是同一插件拥有的顶层 provider。当按 provider 过滤的列表使用别名时,OpenClaw 可以读取拥有该别名的清单,并在不加载 provider 运行时的情况下应用别名的 API/base URL 覆盖。
|
||||
`aliases` 会参与模型目录规划中的提供商归属查找。别名目标必须是由同一插件拥有的顶层提供商。当按提供商过滤的列表使用别名时,OpenClaw 可以读取拥有它的清单,并应用别名 API/base URL 覆盖,而无需加载提供商运行时。
|
||||
|
||||
`suppressions` 是 provider 运行时 `suppressBuiltInModel` 钩子的首选静态替代方案。仅当该 provider 由此插件拥有,或被声明为指向拥有的 provider 的 `modelCatalog.aliases` 键时,抑制条目才会生效。对于尚未迁移的插件,运行时抑制钩子仍会作为已弃用的兼容性回退执行。
|
||||
`suppressions` 是提供商运行时 `suppressBuiltInModel` 钩子的首选静态替代方案。只有当提供商由该插件拥有,或作为指向某个拥有中提供商的 `modelCatalog.aliases` 键被声明时,抑制条目才会生效。对于尚未迁移的插件,运行时抑制钩子仍会作为已弃用的兼容性回退继续运行。
|
||||
|
||||
provider 字段:
|
||||
提供商字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --------- | ------------------------ | ----------------------------------------------------------------- |
|
||||
| `baseUrl` | `string` | 此 provider 目录中模型的可选默认 base URL。 |
|
||||
| `api` | `ModelApi` | 此 provider 目录中模型的可选默认 API 适配器。 |
|
||||
| `headers` | `Record<string, string>` | 适用于此 provider 目录的可选静态 headers。 |
|
||||
| `models` | `object[]` | 必填模型条目。没有 `id` 的条目会被忽略。 |
|
||||
| `baseUrl` | `string` | 此提供商目录中模型的可选默认 base URL。 |
|
||||
| `api` | `ModelApi` | 此提供商目录中模型的可选默认 API 适配器。 |
|
||||
| `headers` | `Record<string, string>` | 适用于此提供商目录的可选静态 headers。 |
|
||||
| `models` | `object[]` | 必填的模型条目。没有 `id` 的条目会被忽略。 |
|
||||
|
||||
模型字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
||||
| `id` | `string` | provider 本地模型 id,不含 `provider/` 前缀。 |
|
||||
| `name` | `string` | 可选显示名称。 |
|
||||
| `api` | `ModelApi` | 可选的按模型覆盖 API。 |
|
||||
| `baseUrl` | `string` | 可选的按模型覆盖 base URL。 |
|
||||
| `headers` | `Record<string, string>` | 可选的按模型静态 headers。 |
|
||||
| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 模型接受的模态。 |
|
||||
| `reasoning` | `boolean` | 该模型是否公开推理行为。 |
|
||||
| `contextWindow` | `number` | provider 原生上下文窗口。 |
|
||||
| `contextTokens` | `number` | 当与 `contextWindow` 不同时,可选的实际运行时上下文上限。 |
|
||||
| `maxTokens` | `number` | 已知时的最大输出 token 数。 |
|
||||
| `cost` | `object` | 可选的每百万 token 美元定价,包括可选的 `tieredPricing`。 |
|
||||
| `compat` | `object` | 与 OpenClaw 模型配置兼容性相匹配的可选兼容性标志。 |
|
||||
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该条目根本不应出现时才使用 suppress。 |
|
||||
| `statusReason` | `string` | 与非可用状态一起显示的可选原因。 |
|
||||
| `replaces` | `string[]` | 此模型所取代的旧版 provider 本地模型 id。 |
|
||||
| `replacedBy` | `string` | 已弃用条目的替代 provider 本地模型 id。 |
|
||||
| `tags` | `string[]` | 供选择器和过滤器使用的稳定标签。 |
|
||||
| `id` | `string` | 提供商本地模型 id,不含 `provider/` 前缀。 |
|
||||
| `name` | `string` | 可选显示名称。 |
|
||||
| `api` | `ModelApi` | 可选的按模型粒度 API 覆盖。 |
|
||||
| `baseUrl` | `string` | 可选的按模型粒度 base URL 覆盖。 |
|
||||
| `headers` | `Record<string, string>` | 可选的按模型粒度静态 headers。 |
|
||||
| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 模型接受的模态。 |
|
||||
| `reasoning` | `boolean` | 模型是否公开 reasoning 行为。 |
|
||||
| `contextWindow` | `number` | 提供商原生上下文窗口。 |
|
||||
| `contextTokens` | `number` | 当与 `contextWindow` 不同时,可选的有效运行时上下文上限。 |
|
||||
| `maxTokens` | `number` | 已知时的最大输出 token 数。 |
|
||||
| `cost` | `object` | 可选的每百万 token 美元定价,包括可选的 `tieredPricing`。 |
|
||||
| `compat` | `object` | 与 OpenClaw 模型配置兼容性匹配的可选兼容性标志。 |
|
||||
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该条目完全不应出现时才使用 suppress。 |
|
||||
| `statusReason` | `string` | 与非可用状态一起显示的可选原因。 |
|
||||
| `replaces` | `string[]` | 该模型取代的旧版提供商本地模型 id。 |
|
||||
| `replacedBy` | `string` | 已弃用条目的替代提供商本地模型 id。 |
|
||||
| `tags` | `string[]` | 供选择器和过滤器使用的稳定标签。 |
|
||||
|
||||
不要将仅运行时数据放入 `modelCatalog`。如果某个 provider 需要账户状态、API 请求或本地进程发现才能知道完整模型集合,请在 `discovery` 中将该 provider 声明为 `refreshable` 或 `runtime`。
|
||||
不要将仅运行时数据放入 `modelCatalog`。如果提供商需要账号状态、API 请求或本地进程发现才能确定完整模型集合,请在 `discovery` 中将该提供商声明为 `refreshable` 或 `runtime`。
|
||||
|
||||
## `modelIdNormalization` 参考
|
||||
|
||||
对于必须在 provider 运行时加载之前发生的、低成本且由 provider 拥有的模型 id 清理,请使用 `modelIdNormalization`。这样可以将短模型名、provider 本地旧版 id 和代理前缀规则等别名保存在拥有该模型的插件清单中,而不是核心模型选择表中。
|
||||
对于必须在提供商运行时加载前发生的、低成本且由提供商拥有的模型 id 清理,请使用 `modelIdNormalization`。这样可以将简短模型名称、提供商本地旧版 id,以及代理前缀规则等别名保存在拥有该模型的插件清单中,而不是保存在核心模型选择表中。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -685,33 +681,33 @@ provider 字段:
|
||||
}
|
||||
```
|
||||
|
||||
provider 字段:
|
||||
提供商字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ------------------------------------ | ----------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `aliases` | `Record<string,string>` | 不区分大小写的精确模型 id 别名。返回值会按原样返回。 |
|
||||
| `stripPrefixes` | `string[]` | 在别名查找前要移除的前缀,适用于旧版的 provider/model 重复情况。 |
|
||||
| `prefixWhenBare` | `string` | 当规范化后的模型 id 尚不包含 `/` 时,要添加的前缀。 |
|
||||
| `prefixWhenBareAfterAliasStartsWith` | `object[]` | 别名查找之后的条件化裸 id 前缀规则,以 `modelPrefix` 和 `prefix` 为键。 |
|
||||
| `aliases` | `Record<string,string>` | 不区分大小写的精确模型 id 别名。返回值按原样保留。 |
|
||||
| `stripPrefixes` | `string[]` | 在别名查找前要移除的前缀,适用于旧版 `provider/model` 重复情况。 |
|
||||
| `prefixWhenBare` | `string` | 当规范化后的模型 id 尚未包含 `/` 时要添加的前缀。 |
|
||||
| `prefixWhenBareAfterAliasStartsWith` | `object[]` | 别名查找后的条件裸 id 前缀规则,以 `modelPrefix` 和 `prefix` 为键。 |
|
||||
|
||||
## `providerEndpoints` 参考
|
||||
|
||||
对于通用请求策略必须在 provider 运行时加载之前知道的端点分类,请使用 `providerEndpoints`。核心仍然负责每个 `endpointClass` 的含义;插件清单则拥有 host 和 base URL 元数据。
|
||||
对于通用请求策略必须在提供商运行时加载前知道的端点分类,请使用 `providerEndpoints`。每个 `endpointClass` 的含义仍由核心负责;插件清单负责 host 和 base URL 元数据。
|
||||
|
||||
端点字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ------------------------------ | ---------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `endpointClass` | `string` | 已知的核心端点类别,例如 `openrouter`、`moonshot-native` 或 `google-vertex`。 |
|
||||
| `hosts` | `string[]` | 映射到该端点类别的精确主机名。 |
|
||||
| `hostSuffixes` | `string[]` | 映射到该端点类别的主机后缀。若仅匹配域名后缀,请以 `.` 作为前缀。 |
|
||||
| `baseUrls` | `string[]` | 映射到该端点类别的精确规范化 HTTP(S) base URL。 |
|
||||
| `googleVertexRegion` | `string` | 适用于精确全局主机的静态 Google Vertex 区域。 |
|
||||
| `googleVertexRegionHostSuffix` | `string` | 从匹配主机中剥离以暴露 Google Vertex 区域前缀的后缀。 |
|
||||
| `endpointClass` | `string` | 已知的核心端点类别,例如 `openrouter`、`moonshot-native` 或 `google-vertex`。 |
|
||||
| `hosts` | `string[]` | 映射到该端点类别的精确主机名。 |
|
||||
| `hostSuffixes` | `string[]` | 映射到该端点类别的主机后缀。若仅匹配域名后缀,则以 `.` 为前缀。 |
|
||||
| `baseUrls` | `string[]` | 映射到该端点类别的精确规范化 HTTP(S) base URL。 |
|
||||
| `googleVertexRegion` | `string` | 精确全局主机对应的静态 Google Vertex 区域。 |
|
||||
| `googleVertexRegionHostSuffix` | `string` | 从匹配主机中剥离以暴露 Google Vertex 区域前缀的后缀。 |
|
||||
|
||||
## `providerRequest` 参考
|
||||
|
||||
对于通用请求策略在不加载 provider 运行时的情况下所需的低成本请求兼容性元数据,请使用 `providerRequest`。请将特定于行为的负载重写保留在 provider 运行时钩子或共享 provider 系列辅助工具中。
|
||||
对于通用请求策略在无需加载提供商运行时的情况下所需的低成本请求兼容性元数据,请使用 `providerRequest`。将特定行为的 payload 重写保留在提供商运行时钩子或共享提供商家族辅助工具中。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -729,17 +725,17 @@ provider 字段:
|
||||
}
|
||||
```
|
||||
|
||||
provider 字段:
|
||||
提供商字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --------------------- | ------------ | -------------------------------------------------------------------------------------- |
|
||||
| `family` | `string` | 通用请求兼容性决策和诊断中使用的 provider 系列标签。 |
|
||||
| `compatibilityFamily` | `"moonshot"` | 用于共享请求辅助工具的可选 provider 系列兼容性分组。 |
|
||||
| `openAICompletions` | `object` | OpenAI 兼容 completions 请求标志,目前为 `supportsStreamingUsage`。 |
|
||||
| `family` | `string` | 通用请求兼容性决策和诊断所使用的提供商家族标签。 |
|
||||
| `compatibilityFamily` | `"moonshot"` | 供共享请求辅助工具使用的可选提供商家族兼容性分组。 |
|
||||
| `openAICompletions` | `object` | OpenAI 兼容 completions 请求标志,目前为 `supportsStreamingUsage`。 |
|
||||
|
||||
## `modelPricing` 参考
|
||||
|
||||
当 provider 在运行时加载之前需要控制平面定价行为时,请使用 `modelPricing`。Gateway 网关定价缓存会在不导入 provider 运行时代码的情况下读取这些元数据。
|
||||
当提供商需要在运行时加载前提供控制平面定价行为时,请使用 `modelPricing`。Gateway 网关定价缓存会读取此元数据,而无需导入提供商运行时代码。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -760,25 +756,25 @@ provider 字段:
|
||||
}
|
||||
```
|
||||
|
||||
provider 字段:
|
||||
提供商字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ------------ | ----------------- | -------------------------------------------------------------------------------------------------- |
|
||||
| `external` | `boolean` | 对于永远不应获取 OpenRouter 或 LiteLLM 定价的本地/自托管 provider,请设置为 `false`。 |
|
||||
| `openRouter` | `false \| object` | OpenRouter 定价查找映射。`false` 表示为此 provider 禁用 OpenRouter 查找。 |
|
||||
| `liteLLM` | `false \| object` | LiteLLM 定价查找映射。`false` 表示为此 provider 禁用 LiteLLM 查找。 |
|
||||
| `external` | `boolean` | 对于永远不应获取 OpenRouter 或 LiteLLM 定价的本地/自托管提供商,设置为 `false`。 |
|
||||
| `openRouter` | `false \| object` | OpenRouter 定价查找映射。`false` 会禁用此提供商的 OpenRouter 查找。 |
|
||||
| `liteLLM` | `false \| object` | LiteLLM 定价查找映射。`false` 会禁用此提供商的 LiteLLM 查找。 |
|
||||
|
||||
来源字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| -------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| `provider` | `string` | 外部目录 provider id;当它与 OpenClaw provider id 不同时使用,例如 `zai` provider 对应的 `z-ai`。 |
|
||||
| `passthroughProviderModel` | `boolean` | 将包含斜杠的模型 id 视为嵌套的 provider/model 引用,适用于像 OpenRouter 这样的代理 provider。 |
|
||||
| `modelIdTransforms` | `"version-dots"[]` | 额外的外部目录模型 id 变体。`version-dots` 会尝试像 `claude-opus-4.6` 这样的点号版本 id。 |
|
||||
| `provider` | `string` | 当外部目录提供商 id 与 OpenClaw 提供商 id 不同时使用的外部目录提供商 id,例如 `zai` 提供商对应的 `z-ai`。 |
|
||||
| `passthroughProviderModel` | `boolean` | 将包含斜杠的模型 id 视为嵌套的 `provider/model` 引用,适用于 OpenRouter 之类的代理提供商。 |
|
||||
| `modelIdTransforms` | `"version-dots"[]` | 额外的外部目录模型 id 变体。`version-dots` 会尝试诸如 `claude-opus-4.6` 之类的点号版本 id。 |
|
||||
|
||||
### OpenClaw Provider Index
|
||||
|
||||
OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,面向那些其插件可能尚未安装的 provider。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。Provider Index 是内部回退契约,未来可安装 provider 和预安装模型选择器界面会在 provider 插件尚未安装时使用它。
|
||||
OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,用于其插件可能尚未安装的提供商。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。Provider Index 是内部回退契约,未来可安装提供商和预安装模型选择器界面会在提供商插件尚未安装时使用它。
|
||||
|
||||
目录权威顺序:
|
||||
|
||||
@ -787,65 +783,61 @@ OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,面向那些
|
||||
3. 来自显式刷新的模型目录缓存。
|
||||
4. OpenClaw Provider Index 预览条目。
|
||||
|
||||
Provider Index 绝不能包含密钥、启用状态、运行时钩子或实时账户专属模型数据。它的预览目录使用与插件清单相同的 `modelCatalog` provider 条目结构,但应限制为稳定显示元数据,除非像 `api`、`baseUrl`、定价或兼容性标志这样的运行时适配器字段被有意与已安装插件清单保持一致。对于具有实时 `/models` 发现能力的 provider,应通过显式模型目录缓存路径写入刷新后的条目,而不是在常规列表或新手引导中调用 provider API。
|
||||
Provider Index 不得包含密钥、启用状态、运行时钩子或实时的账号特定模型数据。它的预览目录使用与插件清单相同的 `modelCatalog` 提供商条目结构,但应仅限于稳定的显示元数据,除非运行时适配器字段(如 `api`、`baseUrl`、定价或兼容性标志)被有意保持与已安装插件清单一致。对于具有实时 `/models` 发现能力的提供商,应通过显式模型目录缓存路径写入刷新后的条目,而不是在正常列表或新手引导流程中调用提供商 API。
|
||||
|
||||
Provider Index 条目也可以携带适用于那些其插件已移出核心、或尚未安装的 provider 的可安装插件元数据。这些元数据沿用渠道目录模式:包名、npm 安装规格、预期完整性,以及低成本认证选项标签,足以展示一个可安装的设置选项。一旦插件安装完成,其清单将优先生效,而该 provider 的 Provider Index 条目会被忽略。
|
||||
Provider Index 条目还可以携带可安装插件元数据,用于那些插件已移出核心或尚未安装的提供商。此元数据遵循与渠道目录相同的模式:包名、npm 安装规格、预期完整性,以及轻量级认证选项标签,足以显示一个可安装的设置选项。一旦插件安装完成,其清单即取得优先权,Provider Index 中该提供商的条目会被忽略。
|
||||
|
||||
旧版顶层能力键已弃用。请使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、
|
||||
`realtimeVoiceProviders`、`mediaUnderstandingProviders`、
|
||||
`imageGenerationProviders`、`videoGenerationProviders`、
|
||||
`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载不再将这些顶层字段视为能力归属。
|
||||
旧版顶层能力键已弃用。使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载不再将这些顶层字段视为能力归属。
|
||||
|
||||
## 清单与 `package.json` 的区别
|
||||
|
||||
这两个文件负责不同的工作:
|
||||
这两个文件承担不同职责:
|
||||
|
||||
| 文件 | 用途 |
|
||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `openclaw.plugin.json` | 发现、配置校验、认证选项元数据,以及必须在插件代码运行之前存在的 UI 提示 |
|
||||
| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 配置块 |
|
||||
| `openclaw.plugin.json` | 设备发现、配置验证、认证选项元数据,以及在插件代码运行前必须存在的 UI 提示 |
|
||||
| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 配置块 |
|
||||
|
||||
如果你不确定某项元数据应该放在哪里,请使用以下规则:
|
||||
如果你不确定某段元数据应放在哪里,请使用以下规则:
|
||||
|
||||
- 如果 OpenClaw 必须在加载插件代码之前知道它,就把它放在 `openclaw.plugin.json` 中
|
||||
- 如果它与打包、入口文件或 npm 安装行为有关,就把它放在 `package.json` 中
|
||||
- 如果 OpenClaw 必须在加载插件代码前知道它,请放在 `openclaw.plugin.json`
|
||||
- 如果它与打包、入口文件或 npm 安装行为有关,请放在 `package.json`
|
||||
|
||||
### 会影响发现的 `package.json` 字段
|
||||
### 会影响设备发现的 `package.json` 字段
|
||||
|
||||
某些运行时前插件元数据有意放在 `package.json` 的
|
||||
`openclaw` 配置块下,而不是放在 `openclaw.plugin.json` 中。
|
||||
某些运行时前插件元数据有意放在 `package.json` 的 `openclaw` 配置块下,而不是 `openclaw.plugin.json` 中。
|
||||
|
||||
重要示例:
|
||||
|
||||
| 字段 | 含义 |
|
||||
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `openclaw.extensions` | 声明原生插件入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.runtimeExtensions` | 为已安装包声明已构建的 JavaScript 运行时入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.setupEntry` | 在新手引导、延后渠道启动和只读渠道 Status/SecretRef 发现期间使用的轻量级、仅设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.runtimeSetupEntry` | 为已安装包声明已构建的 JavaScript 设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.channel` | 低成本渠道目录元数据,例如标签、文档路径、别名和选择说明。 |
|
||||
| `openclaw.channel.commands` | 在渠道运行时加载之前,供配置、审计和命令列表界面使用的静态原生命令和原生 Skills 自动默认值元数据。 |
|
||||
| `openclaw.channel.configuredState` | 轻量级已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经存在仅由环境变量驱动的设置?”。 |
|
||||
| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已有任何内容完成登录?”。 |
|
||||
| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 用于内置插件和外部发布插件的安装/更新提示。 |
|
||||
| `openclaw.install.defaultChoice` | 当有多个安装来源可用时的首选安装路径。 |
|
||||
| `openclaw.install.minHostVersion` | 最低受支持的 OpenClaw 宿主版本,使用诸如 `>=2026.3.22` 这样的 semver 下限。 |
|
||||
| `openclaw.install.expectedIntegrity` | 预期的 npm dist 完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验获取到的产物。 |
|
||||
| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一个范围很窄的内置插件重装恢复路径。 |
|
||||
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间,先加载仅设置用的渠道界面,再加载完整渠道插件。 |
|
||||
| `openclaw.extensions` | 声明原生插件入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.runtimeExtensions` | 为已安装包声明构建后的 JavaScript 运行时入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.setupEntry` | 在新手引导、延迟渠道启动和只读渠道 Status/SecretRef 发现期间使用的轻量级仅设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.runtimeSetupEntry` | 为已安装包声明构建后的 JavaScript 设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.channel` | 轻量级渠道目录元数据,例如标签、文档路径、别名和选择文案。 |
|
||||
| `openclaw.channel.commands` | 在渠道运行时加载前供配置、审计和命令列表界面使用的静态原生命令和原生 Skills 自动默认元数据。 |
|
||||
| `openclaw.channel.configuredState` | 轻量级已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已存在仅环境变量的设置?”。 |
|
||||
| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已有任何登录状态?”。 |
|
||||
| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 内置插件和外部发布插件的安装/更新提示。 |
|
||||
| `openclaw.install.defaultChoice` | 当存在多个安装来源时的首选安装路径。 |
|
||||
| `openclaw.install.minHostVersion` | 最低支持的 OpenClaw 宿主版本,使用类似 `>=2026.3.22` 的 semver 下限。 |
|
||||
| `openclaw.install.expectedIntegrity` | 预期的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此验证获取到的制品。 |
|
||||
| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一个受限的内置插件重新安装恢复路径。 |
|
||||
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置的渠道界面,再加载完整渠道插件。 |
|
||||
|
||||
清单元数据决定了在运行时加载之前,新手引导中会出现哪些 provider/渠道/设置选项。`package.json#openclaw.install` 则告诉新手引导,当用户选择了其中某个选项后,如何获取或启用该插件。不要把安装提示移到 `openclaw.plugin.json` 中。
|
||||
清单元数据决定了在运行时加载前,新手引导中会出现哪些提供商/渠道/设置选项。`package.json#openclaw.install` 告诉新手引导当用户选择这些选项之一时,如何获取或启用该插件。不要将安装提示移到 `openclaw.plugin.json` 中。
|
||||
|
||||
`openclaw.install.minHostVersion` 会在安装期间和清单注册表加载期间强制执行。无效值会被拒绝;较新但有效的值会使该插件在较旧宿主上被跳过。
|
||||
`openclaw.install.minHostVersion` 会在安装和清单注册表加载期间强制执行。无效值会被拒绝;较新的但有效的值会让旧宿主跳过该插件。
|
||||
|
||||
精确的 npm 版本锁定已经放在 `npmSpec` 中,例如
|
||||
`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录条目应将精确规格与 `expectedIntegrity` 配对使用,这样如果获取到的 npm 产物不再匹配锁定的发布版本,更新流程就会以失败即关闭的方式处理。为兼容性考虑,交互式新手引导仍会提供受信任注册表的 npm 规格,包括裸包名和 dist-tag。目录诊断可以区分精确、浮动、带完整性锁定、缺少完整性、包名不匹配和无效默认选项来源。它们还会在存在 `expectedIntegrity` 但没有可用于锁定它的有效 npm 来源时发出警告。当存在 `expectedIntegrity` 时,安装/更新流程会强制执行它;当省略它时,注册表解析结果会被记录,但不会附带完整性锁定。
|
||||
精确的 npm 版本固定已经存在于 `npmSpec` 中,例如
|
||||
`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录条目应将精确规格与 `expectedIntegrity` 配对,这样如果获取到的 npm 制品不再匹配固定版本,更新流程就会以失败关闭。出于兼容性考虑,交互式新手引导仍会提供受信任注册表的 npm 规格,包括裸包名和 dist-tag。目录诊断可以区分精确、浮动、带完整性固定、缺失完整性、包名不匹配和无效默认选项来源。它们还会在存在 `expectedIntegrity` 但没有可用于固定的有效 npm 来源时发出警告。当存在 `expectedIntegrity` 时,安装/更新流程会强制执行它;省略时,注册表解析结果会被记录,但不会附带完整性固定。
|
||||
|
||||
当状态、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`。设置入口应公开渠道元数据,以及适用于设置阶段的配置、状态和密钥适配器;请将网络客户端、网关监听器和传输运行时保留在主扩展入口点中。
|
||||
当 Status、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账号时,渠道插件应提供 `openclaw.setupEntry`。设置入口应公开渠道元数据以及适用于设置的安全配置、Status 和 secrets 适配器;将网络客户端、Gateway 网关监听器和传输运行时保留在主扩展入口点中。
|
||||
|
||||
运行时入口点字段不会覆盖源入口点字段的包边界检查。例如,`openclaw.runtimeExtensions` 不能让一个越界的 `openclaw.extensions` 路径变得可加载。
|
||||
|
||||
`openclaw.install.allowInvalidConfigRecovery` 的范围被有意限制得很窄。它不会让任意损坏的配置变得可安装。当前它只允许安装流程从特定的旧内置插件升级失败中恢复,例如缺失的内置插件路径,或同一内置插件下陈旧的 `channels.<id>` 条目。无关的配置错误仍会阻止安装,并将运维人员引导到 `openclaw doctor --fix`。
|
||||
`openclaw.install.allowInvalidConfigRecovery` 是有意保持狭窄范围的。它不会让任意损坏的配置变得可安装。当前它只允许安装流程从特定的旧内置插件升级失败中恢复,例如缺失的内置插件路径,或同一个内置插件的过期 `channels.<id>` 条目。无关的配置错误仍会阻止安装,并引导操作员使用 `openclaw doctor --fix`。
|
||||
|
||||
`openclaw.channel.persistedAuthState` 是一个微型检查器模块的包元数据:
|
||||
|
||||
@ -863,9 +855,9 @@ Provider Index 条目也可以携带适用于那些其插件已移出核心、
|
||||
}
|
||||
```
|
||||
|
||||
当设置、Doctor 或已配置状态流程需要在完整渠道插件加载之前进行低成本的“是/否”认证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整的渠道运行时 barrel 来路由它。
|
||||
当设置、Doctor、Status 或只读存在性流程需要在完整渠道插件加载前执行一个低成本的“是/否”认证探测时,请使用它。持久化认证状态并不是已配置的渠道状态:不要用这个元数据自动启用插件、修复运行时依赖,或决定是否应加载某个渠道运行时。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 来间接调用它。
|
||||
|
||||
`openclaw.channel.configuredState` 对低成本、仅环境变量的已配置检查采用相同的结构:
|
||||
`openclaw.channel.configuredState` 采用相同的结构,用于低成本的仅环境变量已配置检查:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -881,51 +873,51 @@ Provider Index 条目也可以携带适用于那些其插件已移出核心、
|
||||
}
|
||||
```
|
||||
|
||||
当一个渠道能够根据环境变量或其他微小的非运行时输入来判断已配置状态时,请使用它。如果检查需要完整配置解析或真实的渠道运行时,请将该逻辑保留在插件的 `config.hasConfiguredState` hook 中。
|
||||
当某个渠道可以通过环境变量或其他微小的非运行时输入来回答已配置状态时,请使用它。如果检查需要完整配置解析或真实渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` 钩子中。
|
||||
|
||||
## 设备发现优先级(重复插件 id)
|
||||
|
||||
OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区、配置中显式选定的路径)。如果两个发现结果共享同一个 `id`,只会保留**优先级最高**的清单;优先级较低的重复项会被丢弃,而不会与其并行加载。
|
||||
OpenClaw 会从多个根目录发现插件(内置、全局安装、工作区、显式配置选择的路径)。如果两个发现结果共享相同的 `id`,则只保留**最高优先级**的清单;较低优先级的重复项会被丢弃,而不是与其并行加载。
|
||||
|
||||
优先级从高到低如下:
|
||||
|
||||
1. **配置选定** —— 在 `plugins.entries.<id>` 中显式固定的路径
|
||||
2. **内置** —— 随 OpenClaw 一起发布的插件
|
||||
3. **全局安装** —— 安装到全局 OpenClaw 插件根目录的插件
|
||||
4. **工作区** —— 相对于当前工作区发现的插件
|
||||
1. **配置选择** — 在 `plugins.entries.<id>` 中显式固定的路径
|
||||
2. **内置** — 随 OpenClaw 一起发布的插件
|
||||
3. **全局安装** — 安装到全局 OpenClaw 插件根目录中的插件
|
||||
4. **工作区** — 相对于当前工作区发现的插件
|
||||
|
||||
影响:
|
||||
|
||||
- 如果某个内置插件的分叉版本或过时副本位于工作区中,它不会遮蔽内置版本。
|
||||
- 若要真正用本地插件覆盖内置插件,请通过 `plugins.entries.<id>` 固定它,使它依靠优先级获胜,而不是依赖工作区发现。
|
||||
- 被丢弃的重复项会记录日志,以便 Doctor 和启动诊断能够指向被舍弃的副本。
|
||||
- 工作区中一个分叉版或陈旧的内置插件副本不会遮蔽内置构建版本。
|
||||
- 如果你确实要用本地插件覆盖内置插件,请通过 `plugins.entries.<id>` 固定它,使其凭借优先级获胜,而不是依赖工作区发现。
|
||||
- 被丢弃的重复项会被记录,这样 Doctor 和启动诊断就能指出被丢弃的副本。
|
||||
|
||||
## JSON Schema 要求
|
||||
|
||||
- **每个插件都必须提供一个 JSON Schema**,即使它不接受任何配置。
|
||||
- 空 schema 也是可以接受的(例如 `{ "type": "object", "additionalProperties": false }`)。
|
||||
- Schema 会在配置读写时校验,而不是在运行时校验。
|
||||
- 可以接受空 schema(例如 `{ "type": "object", "additionalProperties": false }`)。
|
||||
- Schema 会在配置读取/写入时验证,而不是在运行时验证。
|
||||
|
||||
## 校验行为
|
||||
## 验证行为
|
||||
|
||||
- 未知的 `channels.*` 键会被视为**错误**,除非该渠道 id 是由某个插件清单声明的。
|
||||
- 未知的 `channels.*` 键会被视为**错误**,除非该渠道 id 已由插件清单声明。
|
||||
- `plugins.entries.<id>`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*`
|
||||
必须引用**可发现的**插件 id。未知 id 会被视为**错误**。
|
||||
- 如果某个插件已安装,但其清单或 schema 缺失或损坏,校验会失败,Doctor 会报告该插件错误。
|
||||
- 如果插件配置存在,但插件处于**禁用**状态,配置会被保留,并且 Doctor + 日志中会显示一条**警告**。
|
||||
必须引用**可发现**的插件 id。未知 id 会被视为**错误**。
|
||||
- 如果插件已安装,但其清单或 schema 缺失或损坏,验证将失败,Doctor 会报告该插件错误。
|
||||
- 如果插件配置存在,但插件已**禁用**,配置会被保留,并且 Doctor + 日志中会显示**警告**。
|
||||
|
||||
有关完整的 `plugins.*` schema,请参阅 [配置参考](/zh-CN/gateway/configuration)。
|
||||
完整的 `plugins.*` schema 请参阅[配置参考](/zh-CN/gateway/configuration)。
|
||||
|
||||
## 说明
|
||||
## 注意事项
|
||||
|
||||
- 清单是**原生 OpenClaw 插件**的必需项,包括本地文件系统加载。运行时仍会单独加载插件模块;清单仅用于发现 + 校验。
|
||||
- 对于**原生 OpenClaw 插件**,包括本地文件系统加载,清单都是**必需的**。运行时仍会单独加载插件模块;清单仅用于设备发现 + 验证。
|
||||
- 原生清单使用 JSON5 解析,因此只要最终值仍然是对象,就接受注释、尾随逗号和未加引号的键。
|
||||
- 清单加载器只会读取文档中记录的清单字段。避免使用自定义顶层键。
|
||||
- 清单加载器只会读取已记录的清单字段。避免自定义顶层键。
|
||||
- 当插件不需要它们时,`channels`、`providers`、`cliBackends` 和 `skills` 都可以省略。
|
||||
- `providerDiscoveryEntry` 必须保持轻量,不应导入宽泛的运行时代码;请将其用于静态 provider 目录元数据或狭义的发现描述符,而不是请求期执行。
|
||||
- 互斥插件类型通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory`,`kind: "context-engine"` 通过 `plugins.slots.contextEngine`(默认 `legacy`)。
|
||||
- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` 以及 `channelEnvVars`)仅是声明式的。Status、审计、cron 投递校验及其他只读界面,在将某个环境变量视为已配置之前,仍会应用插件信任和实际激活策略。
|
||||
- 对于需要 provider 代码的运行时向导元数据,请参阅 [provider 运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
|
||||
- `providerDiscoveryEntry` 必须保持轻量,不应导入宽泛的运行时代码;将其用于静态提供商目录元数据或窄范围发现描述符,而不是请求时执行。
|
||||
- 排他性插件类型通过 `plugins.slots.*` 选择:`kind: "memory"` 对应 `plugins.slots.memory`,`kind: "context-engine"` 对应 `plugins.slots.contextEngine`(默认 `legacy`)。
|
||||
- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` 和 `channelEnvVars`)仅为声明式。Status、审计、cron 投递验证和其他只读界面在将某个环境变量视为已配置之前,仍会应用插件信任和有效激活策略。
|
||||
- 对于需要提供商代码的运行时向导元数据,请参阅[提供商运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
|
||||
- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器允许列表要求(例如 pnpm `allow-build-scripts` + `pnpm rebuild <package>`)。
|
||||
|
||||
## 相关内容
|
||||
@ -937,7 +929,7 @@ OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区
|
||||
<Card title="插件架构" href="/zh-CN/plugins/architecture" icon="diagram-project">
|
||||
内部架构和能力模型。
|
||||
</Card>
|
||||
<Card title="插件 SDK 概览" href="/zh-CN/plugins/sdk-overview" icon="book">
|
||||
<Card title="SDK 概览" href="/zh-CN/plugins/sdk-overview" icon="book">
|
||||
插件 SDK 参考和子路径导入。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@ -2,27 +2,27 @@
|
||||
read_when:
|
||||
- 你想通过 LiteLLM 代理来路由 OpenClaw
|
||||
- 你需要通过 LiteLLM 实现成本跟踪、日志记录或模型路由
|
||||
summary: 通过 LiteLLM Proxy 运行 OpenClaw,以实现统一的模型访问和成本跟踪
|
||||
summary: 通过 LiteLLM Proxy 运行 OpenClaw,以统一访问模型并跟踪成本
|
||||
title: LiteLLM
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T18:12:26Z"
|
||||
generated_at: "2026-04-27T19:38:37Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: f4e2cdddff8dd953b989beb4f2ed1c31dae09298dacd0cf809ef07b41358623b
|
||||
source_hash: 26b5150cfca92c9cd425c864c711efb3ab62ef94377b9d1e5d6476b07bf4c800
|
||||
source_path: providers/litellm.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
[LiteLLM](https://litellm.ai) 是一个开源的 LLM 网关,为 100 多家模型提供商提供统一的 API。通过 LiteLLM 路由 OpenClaw,以获得集中式成本跟踪、日志记录,以及在不更改 OpenClaw 配置的情况下切换后端的灵活性。
|
||||
[LiteLLM](https://litellm.ai) 是一个开源 LLM 网关,提供统一 API 以接入 100 多家模型提供商。通过 LiteLLM 路由 OpenClaw,以获得集中式成本跟踪、日志记录,以及无需更改 OpenClaw 配置即可切换后端的灵活性。
|
||||
|
||||
<Tip>
|
||||
**为什么将 LiteLLM 与 OpenClaw 搭配使用?**
|
||||
**为什么将 LiteLLM 与 OpenClaw 一起使用?**
|
||||
|
||||
- **成本跟踪** — 精确查看 OpenClaw 在所有模型上的花费
|
||||
- **模型路由** — 无需更改配置,即可在 Claude、GPT-4、Gemini、Bedrock 之间切换
|
||||
- **成本跟踪** — 准确查看 OpenClaw 在所有模型上的花费
|
||||
- **模型路由** — 无需更改配置即可在 Claude、GPT-4、Gemini、Bedrock 之间切换
|
||||
- **虚拟密钥** — 为 OpenClaw 创建带有支出限制的密钥
|
||||
- **日志记录** — 完整的请求/响应日志,便于调试
|
||||
- **故障回退** — 如果你的主要提供商宕机,则自动故障转移
|
||||
- **故障回退** — 当你的主要提供商不可用时自动故障转移
|
||||
|
||||
</Tip>
|
||||
|
||||
@ -30,13 +30,19 @@ x-i18n:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="新手引导(推荐)">
|
||||
**最适合:** 以最快的方式完成可用的 LiteLLM 设置。
|
||||
**最适合:** 以最快方式完成可用的 LiteLLM 设置。
|
||||
|
||||
<Steps>
|
||||
<Step title="运行新手引导">
|
||||
```bash
|
||||
openclaw onboard --auth-choice litellm-api-key
|
||||
```
|
||||
|
||||
如果要针对远程代理进行非交互式设置,请显式传入代理 URL:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive --auth-choice litellm-api-key --litellm-api-key "$LITELLM_API_KEY" --custom-base-url "https://litellm.example/v1"
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@ -52,14 +58,14 @@ x-i18n:
|
||||
litellm --model claude-opus-4-6
|
||||
```
|
||||
</Step>
|
||||
<Step title="将 OpenClaw 指向 LiteLLM">
|
||||
<Step title="让 OpenClaw 指向 LiteLLM">
|
||||
```bash
|
||||
export LITELLM_API_KEY="your-litellm-key"
|
||||
|
||||
openclaw
|
||||
```
|
||||
|
||||
就这样。OpenClaw 现在会通过 LiteLLM 进行路由。
|
||||
就这样。OpenClaw 现在会通过 LiteLLM 路由。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@ -117,7 +123,7 @@ export LITELLM_API_KEY="sk-litellm-key"
|
||||
|
||||
### 图像生成
|
||||
|
||||
LiteLLM 也可以通过与 OpenAI 兼容的 `/images/generations` 和 `/images/edits` 路由,为 `image_generate` 工具提供支持。在 `agents.defaults.imageGenerationModel` 下配置一个 LiteLLM 图像模型:
|
||||
LiteLLM 也可以通过兼容 OpenAI 的 `/images/generations` 和 `/images/edits` 路由,为 `image_generate` 工具提供支持。在 `agents.defaults.imageGenerationModel` 下配置一个 LiteLLM 图像模型:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -140,11 +146,11 @@ LiteLLM 也可以通过与 OpenAI 兼容的 `/images/generations` 和 `/images/e
|
||||
}
|
||||
```
|
||||
|
||||
诸如 `http://localhost:4000` 这样的 loopback LiteLLM URL 无需全局私有网络覆盖即可工作。对于局域网上托管的代理,请设置 `models.providers.litellm.request.allowPrivateNetwork: true`,因为 API 密钥将被发送到配置的代理主机。
|
||||
像 `http://localhost:4000` 这样的 loopback LiteLLM URL 无需全局私有网络覆盖即可工作。对于托管在局域网中的代理,请设置 `models.providers.litellm.request.allowPrivateNetwork: true`,因为 API 密钥将被发送到已配置的代理主机。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="虚拟密钥">
|
||||
为 OpenClaw 创建一个带支出限制的专用密钥:
|
||||
为 OpenClaw 创建一个带有支出限制的专用密钥:
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:4000/key/generate" \
|
||||
@ -162,7 +168,7 @@ LiteLLM 也可以通过与 OpenAI 兼容的 `/images/generations` 和 `/images/e
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="模型路由">
|
||||
LiteLLM 可以将模型请求路由到不同的后端。在你的 LiteLLM `config.yaml` 中进行配置:
|
||||
LiteLLM 可以将模型请求路由到不同后端。在你的 LiteLLM `config.yaml` 中进行配置:
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
@ -177,19 +183,19 @@ LiteLLM 也可以通过与 OpenAI 兼容的 `/images/generations` 和 `/images/e
|
||||
api_key: os.environ/OPENAI_API_KEY
|
||||
```
|
||||
|
||||
OpenClaw 会继续请求 `claude-opus-4-6` —— 路由由 LiteLLM 处理。
|
||||
OpenClaw 会继续请求 `claude-opus-4-6`——由 LiteLLM 负责处理路由。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="查看用量">
|
||||
检查 LiteLLM 的仪表板或 API:
|
||||
<Accordion title="查看使用情况">
|
||||
查看 LiteLLM 的仪表板或 API:
|
||||
|
||||
```bash
|
||||
# Key info
|
||||
# 密钥信息
|
||||
curl "http://localhost:4000/key/info" \
|
||||
-H "Authorization: Bearer sk-litellm-key"
|
||||
|
||||
# Spend logs
|
||||
# 支出日志
|
||||
curl "http://localhost:4000/spend/logs" \
|
||||
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
|
||||
```
|
||||
@ -198,24 +204,26 @@ LiteLLM 也可以通过与 OpenAI 兼容的 `/images/generations` 和 `/images/e
|
||||
|
||||
<Accordion title="代理行为说明">
|
||||
- LiteLLM 默认运行在 `http://localhost:4000`
|
||||
- OpenClaw 通过 LiteLLM 的代理式、与 OpenAI 兼容的 `/v1` 端点进行连接
|
||||
- 原生仅限 OpenAI 的请求整形不适用于通过 LiteLLM 的场景:没有 `service_tier`、没有 Responses `store`、没有提示缓存提示,也没有 OpenAI 推理兼容负载整形
|
||||
- OpenClaw 通过 LiteLLM 的代理式、兼容 OpenAI 的 `/v1` 端点进行连接
|
||||
- 原生仅限 OpenAI 的请求整形不会通过 LiteLLM 生效:
|
||||
不支持 `service_tier`、Responses `store`、prompt-cache 提示,也不支持
|
||||
OpenAI reasoning 兼容载荷整形
|
||||
- 在自定义 LiteLLM base URL 上,不会注入隐藏的 OpenClaw 归因请求头(`originator`、`version`、`User-Agent`)
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Note>
|
||||
有关通用提供商配置和故障转移行为,请参阅 [模型提供商](/zh-CN/concepts/model-providers)。
|
||||
有关通用 provider 配置和故障转移行为,请参阅 [Model Providers](/zh-CN/concepts/model-providers)。
|
||||
</Note>
|
||||
|
||||
## 相关内容
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="LiteLLM Docs" href="https://docs.litellm.ai" icon="book">
|
||||
<Card title="LiteLLM 文档" href="https://docs.litellm.ai" icon="book">
|
||||
LiteLLM 官方文档和 API 参考。
|
||||
</Card>
|
||||
<Card title="模型选择" href="/zh-CN/concepts/model-providers" icon="layers">
|
||||
所有提供商、模型引用和故障转移行为的概览。
|
||||
所有 provider、模型引用和故障转移行为的概览。
|
||||
</Card>
|
||||
<Card title="配置" href="/zh-CN/gateway/configuration" icon="gear">
|
||||
完整配置参考。
|
||||
|
||||
@ -1,145 +1,157 @@
|
||||
---
|
||||
read_when:
|
||||
- 查找公开发布通道定义
|
||||
- 运行发布验证或包验收
|
||||
- 查找版本命名和发布节奏
|
||||
summary: 发布通道、操作员检查清单、验证环境、版本命名和发布节奏
|
||||
- 正在查找公开发布渠道定义
|
||||
- 运行发布验证或软件包验收
|
||||
- 正在查找版本命名和节奏
|
||||
summary: 发布通道、操作员检查清单、验证框、版本命名和节奏
|
||||
title: 发布策略
|
||||
x-i18n:
|
||||
generated_at: "2026-04-27T12:56:11Z"
|
||||
generated_at: "2026-04-27T19:38:38Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 344606e845ab48966188b5031572dcbb827001b5c0e0f9be657f3a0e6d307835
|
||||
source_hash: 1ad73d75e54bd21cb740b64af0b33cc9d38283de8917544d5795990d3f0aacb6
|
||||
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` 的持续移动头部版本
|
||||
|
||||
## 版本命名
|
||||
|
||||
- 稳定版发布版本:`YYYY.M.D`
|
||||
- Stable 发布版本:`YYYY.M.D`
|
||||
- Git 标签:`vYYYY.M.D`
|
||||
- 稳定版修正版发布版本:`YYYY.M.D-N`
|
||||
- Stable 修正版发布版本:`YYYY.M.D-N`
|
||||
- Git 标签:`vYYYY.M.D-N`
|
||||
- Beta 预发布版本:`YYYY.M.D-beta.N`
|
||||
- Git 标签:`vYYYY.M.D-beta.N`
|
||||
- 月份和日期不要补零
|
||||
- `latest` 表示当前已提升的稳定 npm 发布版本
|
||||
- 不要为月份或日期补零
|
||||
- `latest` 表示当前已提升的 stable npm 发布版本
|
||||
- `beta` 表示当前 beta 安装目标
|
||||
- 稳定版和稳定版修正版默认发布到 npm `beta`;发布操作员可以显式指定 `latest`,或在之后提升经过验证的 beta 构建
|
||||
- 每个稳定版 OpenClaw 发布都会同时交付 npm 包和 macOS 应用;
|
||||
beta 发布通常会先验证并发布 npm/包路径,而 mac 应用构建/签名/公证仅保留给稳定版,除非明确要求
|
||||
- Stable 和 stable 修正版发布默认发布到 npm `beta`;发布操作员可以显式指定 `latest`,或稍后再提升经过验证的 beta 构建
|
||||
- 每个 stable OpenClaw 发布都会同时交付 npm 软件包和 macOS 应用;
|
||||
beta 发布通常会先验证并发布 npm/软件包路径,而 macOS 应用的构建/签名/公证通常保留给 stable,除非有明确请求
|
||||
|
||||
## 发布节奏
|
||||
|
||||
- 发布先走 beta
|
||||
- 只有在最新 beta 验证完成后,才会进入稳定版
|
||||
- 维护者通常会从当前 `main` 创建的 `release/YYYY.M.D` 分支切发布,
|
||||
- 只有在最新 beta 完成验证后,才会进入 stable
|
||||
- 维护者通常会从当前 `main` 创建 `release/YYYY.M.D` 分支来进行发布,
|
||||
这样发布验证和修复就不会阻塞 `main` 上的新开发
|
||||
- 如果某个 beta 标签已经被推送或发布后仍需修复,维护者会切下一个
|
||||
`-beta.N` 标签,而不是删除或重建旧的 beta 标签
|
||||
- 详细发布流程、审批、凭证和恢复说明仅面向维护者
|
||||
- 如果某个 beta 标签已经推送或发布且需要修复,维护者会切出下一个 `-beta.N` 标签,而不是删除或重建旧的 beta 标签
|
||||
- 详细的发布流程、审批、凭证和恢复说明仅面向维护者
|
||||
|
||||
## 发布操作员检查清单
|
||||
|
||||
这份检查清单描述的是发布流程的公开形态。私有凭证、签名、公证、dist-tag 恢复和紧急回滚细节保留在仅面向维护者的发布运行手册中。
|
||||
此检查清单是发布流程的公开形态。私有凭证、
|
||||
签名、公证、dist-tag 恢复以及紧急回滚细节保留在
|
||||
仅维护者可见的发布运行手册中。
|
||||
|
||||
1. 从当前 `main` 开始:拉取最新代码,确认目标提交已推送,
|
||||
并确认当前 `main` 的 CI 足够绿色,可以从它切分支。
|
||||
2. 使用 `/changelog` 根据真实提交历史重写 `CHANGELOG.md` 顶部部分,
|
||||
保持条目面向用户,提交它、推送它,然后在分支前再 rebase/pull 一次。
|
||||
3. 审查以下文件中的发布兼容性记录:
|
||||
2. 使用 `/changelog` 基于真实提交历史重写 `CHANGELOG.md` 的顶部章节,
|
||||
保持条目面向用户,提交它,推送它,并在分支前再执行一次 rebase/pull。
|
||||
3. 审查
|
||||
`src/plugins/compat/registry.ts` 和
|
||||
`src/commands/doctor/shared/deprecation-compat.ts`。仅在升级路径仍有保障时移除已过期兼容项,或记录为何有意保留它。
|
||||
4. 从当前 `main` 创建 `release/YYYY.M.D`;不要直接在 `main` 上执行常规发布工作。
|
||||
5. 为预期标签更新所有必需的版本位置,然后运行本地确定性预检:
|
||||
`pnpm check:test-types`、`pnpm check:architecture`、
|
||||
`pnpm build && pnpm ui:build` 和 `pnpm release:check`。
|
||||
6. 以 `preflight_only=true` 运行 `OpenClaw NPM Release`。在标签存在之前,
|
||||
允许使用完整 40 字符的发布分支 SHA 进行仅验证预检。保存成功的 `preflight_run_id`。
|
||||
7. 使用 `Full Release Validation` 针对发布分支、标签或完整提交 SHA 启动所有预发布测试。这是四个大型发布测试环境(Vitest、Docker、QA Lab 和 Package)的唯一手动入口点。
|
||||
8. 如果验证失败,在发布分支上修复,并重新运行最小范围的失败文件、lane、工作流作业、包配置、提供商或模型允许列表,以证明修复有效。仅当变更表面使之前的证据失效时,才重新运行完整总验证。
|
||||
9. 对于 beta,打上 `vYYYY.M.D-beta.N` 标签,使用 npm dist-tag `beta` 发布,然后针对已发布的 `openclaw@YYYY.M.D-beta.N` 或 `openclaw@beta` 包运行发布后包验收。如果一个已推送或已发布的 beta 需要修复,就切下一个 `-beta.N`;不要删除或重写旧 beta。
|
||||
10. 对于稳定版,仅在经过验证的 beta 或发布候选版本具备所需验证证据后继续。稳定版 npm 发布会通过 `preflight_run_id` 复用成功的预检制品;稳定版 macOS 发布就绪还要求 `main` 上具备已打包的 `.zip`、`.dmg`、`.dSYM.zip` 和更新后的 `appcast.xml`。
|
||||
11. 发布后,运行 npm 发布后验证器;在需要发布后渠道证明时,可选运行独立的已发布 npm Telegram E2E;在需要时执行 dist-tag 提升;根据完整匹配的 `CHANGELOG.md` 章节生成 GitHub release/prerelease 说明;并执行发布公告步骤。
|
||||
`src/commands/doctor/shared/deprecation-compat.ts`
|
||||
中的发布兼容性记录。只有在升级路径仍有保障时才移除已过期的兼容性,
|
||||
否则要记录为什么仍需保留。
|
||||
4. 从当前 `main` 创建 `release/YYYY.M.D`;不要直接在 `main` 上进行常规发布工作。
|
||||
5. 为目标标签更新所有必需的版本位置,然后运行本地确定性预检:
|
||||
`pnpm check:test-types`, `pnpm check:architecture`,
|
||||
`pnpm build && pnpm ui:build`,以及 `pnpm release:check`。
|
||||
6. 使用 `preflight_only=true` 运行 `OpenClaw NPM Release`。在标签尚不存在时,
|
||||
可以使用完整的 40 字符发布分支 SHA 进行仅验证用途的预检。保存成功的
|
||||
`preflight_run_id`。
|
||||
7. 针对发布分支、标签或完整提交 SHA,使用 `Full Release Validation`
|
||||
启动所有预发布测试。这是四个大型发布验证框的唯一手动入口:
|
||||
Vitest、Docker、QA Lab 和 Package。
|
||||
8. 如果验证失败,在发布分支上修复,并重新运行能证明修复有效的最小失败范围,
|
||||
比如单个文件、通道、workflow 作业、软件包配置、提供商或模型 allowlist。
|
||||
只有在改动范围使先前证据失效时,才重新运行完整总流程。
|
||||
9. 对于 beta,打上 `vYYYY.M.D-beta.N` 标签,使用 npm dist-tag `beta` 发布,
|
||||
然后针对已发布的 `openclaw@YYYY.M.D-beta.N`
|
||||
或 `openclaw@beta` 软件包运行发布后软件包验收。如果已推送或已发布的 beta 需要修复,
|
||||
则切出下一个 `-beta.N`;不要删除或改写旧的 beta。
|
||||
10. 对于 stable,只有在经过验证的 beta 或候选发布已具备所需验证证据后才继续。
|
||||
Stable 的 npm 发布会通过 `preflight_run_id` 复用成功的预检产物;stable 的 macOS 发布就绪
|
||||
还要求 `main` 上存在已打包的 `.zip`、`.dmg`、`.dSYM.zip` 以及更新后的
|
||||
`appcast.xml`。
|
||||
11. 发布后,运行 npm 发布后验证器;当你需要发布后的渠道证明时,可选择运行独立的
|
||||
已发布 npm Telegram E2E;并在需要时执行 dist-tag 提升、基于完整匹配
|
||||
`CHANGELOG.md` 章节生成 GitHub release/prerelease 说明,以及发布公告步骤。
|
||||
|
||||
## 发布预检
|
||||
|
||||
- 在发布预检前运行 `pnpm check:test-types`,这样测试 TypeScript 就能在更快的本地 `pnpm check` gate 之外继续得到覆盖
|
||||
- 在发布预检前运行 `pnpm check:architecture`,这样更广泛的导入循环和架构边界检查就能在更快的本地 gate 之外保持绿色
|
||||
- 在 `pnpm release:check` 之前运行 `pnpm build && pnpm ui:build`,这样 pack 验证步骤所需的 `dist/*` 发布制品和 Control UI bundle 才会存在
|
||||
- 在发布审批之前运行手动 `Full Release Validation` 工作流,以便从一个入口点启动所有预发布测试环境。它接受分支、标签或完整提交 SHA,分发手动 `CI`,并分发 `OpenClaw Release Checks`,以执行安装 smoke、包验收、Docker 发布路径测试套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram lane。只有在包已经发布,且还需要运行发布后 Telegram E2E 时,才提供 `npm_telegram_package_spec`。示例:
|
||||
- 在发布预检之前运行 `pnpm check:test-types`,这样测试 TypeScript 也能在更快的本地 `pnpm check` 门禁之外得到覆盖
|
||||
- 在发布预检之前运行 `pnpm check:architecture`,这样更广泛的导入循环和架构边界检查也能在更快的本地门禁之外保持绿色
|
||||
- 在运行 `pnpm release:check` 之前执行 `pnpm build && pnpm ui:build`,这样打包验证步骤所需的 `dist/*` 发布产物和 Control UI bundle 就会存在
|
||||
- 在发布审批之前运行手动 `Full Release Validation` workflow,从一个入口点启动所有预发布测试框。它接受分支、标签或完整提交 SHA,分发手动 `CI`,并分发 `OpenClaw Release Checks`,用于安装冒烟测试、软件包验收、Docker 发布路径测试套件、live/E2E、OpenWebUI、QA Lab 一致性、Matrix 和 Telegram 通道。只有在软件包已经发布且还需要运行发布后 Telegram E2E 时,才提供 `npm_telegram_package_spec`。示例:
|
||||
`gh workflow run full-release-validation.yml --ref main -f ref=release/YYYY.M.D`
|
||||
- 当你希望在发布工作继续进行时,为某个包候选版本获取侧通道证明,请运行手动 `Package Acceptance` 工作流。对 `openclaw@beta`、`openclaw@latest` 或某个精确发布版本,使用 `source=npm`;用 `source=ref` 可用当前 `workflow_ref` harness 打包一个受信任的 `package_ref` 分支/标签/SHA;用 `source=url` 可提供带必需 SHA-256 的 HTTPS tarball;用 `source=artifact` 可使用由其他 GitHub Actions 运行上传的 tarball。该工作流会将候选版本解析为 `package-under-test`,对该 tarball 复用 Docker E2E 发布调度器,并可用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier` 对同一 tarball 运行 Telegram QA。
|
||||
示例:`gh workflow run package-acceptance.yml --ref main -f workflow_ref=main -f source=npm -f package_spec=openclaw@beta -f suite_profile=product -f telegram_mode=mock-openai`
|
||||
常见 profile:
|
||||
- `smoke`:安装/渠道/智能体、Gateway 网关网络和配置重载 lane
|
||||
- `package`:原生制品包/更新/插件 lane,不含 OpenWebUI 或 live ClawHub
|
||||
- `product`:在 package profile 基础上增加 MCP 渠道、cron/subagent 清理、OpenAI Web 搜索和 OpenWebUI
|
||||
- 当你希望在发布工作继续进行的同时,为某个软件包候选版本获得旁路证明时,运行手动 `Package Acceptance` workflow。对 `openclaw@beta`、`openclaw@latest` 或精确发布版本使用 `source=npm`;使用 `source=ref` 时,可用当前 `workflow_ref` harness 打包可信的 `package_ref` 分支/标签/SHA;对带有必需 SHA-256 的 HTTPS tarball 使用 `source=url`;对由其他 GitHub Actions 运行上传的 tarball 使用 `source=artifact`。该 workflow 会将候选版本解析为 `package-under-test`,针对该 tarball 复用 Docker E2E 发布调度器,并可使用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier` 对同一个 tarball 运行 Telegram QA。示例:`gh workflow run package-acceptance.yml --ref main -f workflow_ref=main -f source=npm -f package_spec=openclaw@beta -f suite_profile=product -f telegram_mode=mock-openai`
|
||||
常见配置:
|
||||
- `smoke`:安装/渠道/智能体、Gateway 网关网络和配置热重载通道
|
||||
- `package`:原生制品软件包/更新/插件通道,不含 OpenWebUI 或 live ClawHub
|
||||
- `product`:在 package 配置基础上增加 MCP 渠道、cron/subagent 清理、OpenAI web search 和 OpenWebUI
|
||||
- `full`:带 OpenWebUI 的 Docker 发布路径分块
|
||||
- `custom`:精确选择 `docker_lanes` 以便聚焦重跑
|
||||
- 当你只需要发布候选版本具备完整的常规 CI 覆盖时,直接运行手动 `CI` 工作流。手动 CI 分发会绕过 changed scoping,并强制执行 Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、build smoke、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n lane。
|
||||
- `custom`:精确选择 `docker_lanes`,用于聚焦重跑
|
||||
- 当你只需要发布候选版本具备完整常规 CI 覆盖时,直接运行手动 `CI` workflow。手动 CI 分发会绕过 changed 范围限制,并强制运行 Linux Node 分片、bundled-plugin 分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟测试、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n 通道。
|
||||
示例:`gh workflow run ci.yml --ref release/YYYY.M.D`
|
||||
- 在验证发布遥测时运行 `pnpm qa:otel:smoke`。它会通过本地 OTLP/HTTP 接收器执行 QA-lab,并验证导出的 trace span 名称、有界属性以及内容/标识符脱敏,而不需要 Opik、Langfuse 或其他外部采集器。
|
||||
- 在每次带标签发布前运行 `pnpm release:check`
|
||||
- 发布检查现在在单独的手动工作流中运行:
|
||||
- 在验证发布遥测时运行 `pnpm qa:otel:smoke`。它会通过本地 OTLP/HTTP 接收器驱动 QA-lab,并验证导出的 trace span 名称、受限属性以及内容/标识符脱敏,无需 Opik、Langfuse 或其他外部收集器。
|
||||
- 在每次打标签发布之前运行 `pnpm release:check`
|
||||
- 发布检查现在在单独的手动 workflow 中运行:
|
||||
`OpenClaw Release Checks`
|
||||
- `OpenClaw Release Checks` 也会在发布审批前运行 QA Lab mock parity gate,以及快速 live Matrix profile 和 Telegram QA lane。live lane 使用 `qa-live-shared` 环境;Telegram 还使用 Convex CI 凭证租约。当你需要并行运行完整 Matrix 传输、媒体和 E2EE 清单时,请运行手动 `QA-Lab - All Lanes` 工作流,并设置 `matrix_profile=all` 和 `matrix_shards=true`。
|
||||
- 跨操作系统的安装和升级运行时验证属于公开的
|
||||
`OpenClaw Release Checks` 和 `Full Release Validation` 的一部分,它们会直接调用可复用工作流
|
||||
- `OpenClaw Release Checks` 还会在发布审批之前运行 QA Lab mock 一致性门禁,以及快速 live Matrix 配置和 Telegram QA 通道。live 通道使用 `qa-live-shared` 环境;Telegram 还会使用 Convex CI 凭证租约。若你想并行运行完整的 Matrix 传输、媒体和 E2EE 清单,请使用 `matrix_profile=all` 和 `matrix_shards=true` 运行手动 `QA-Lab - All Lanes` workflow。
|
||||
- 跨操作系统的安装和升级运行时验证属于公开的 `OpenClaw Release Checks` 和 `Full Release Validation`,它们会直接调用可复用 workflow
|
||||
`.github/workflows/openclaw-cross-os-release-checks-reusable.yml`
|
||||
- 这种拆分是有意为之:保持真实 npm 发布路径简短、确定且聚焦制品,而较慢的 live 检查保留在各自 lane 中,以免拖慢或阻塞发布
|
||||
- 带有密钥的发布检查应通过 `Full Release Validation` 进行分发,或从 `main`/release 工作流 ref 进行分发,以保持工作流逻辑和密钥处于受控状态
|
||||
- 这种拆分是有意为之:保持真实 npm 发布路径简短、确定性强,并聚焦于制品;而较慢的 live 检查则保留在独立通道中,这样它们就不会拖慢或阻塞发布
|
||||
- 含有秘密信息的发布检查应通过 `Full Release Validation` 分发,或从 `main`/release workflow ref 分发,以确保 workflow 逻辑和 secrets 受到控制
|
||||
- `OpenClaw Release Checks` 接受分支、标签或完整提交 SHA,只要解析后的提交可从某个 OpenClaw 分支或发布标签到达
|
||||
- `OpenClaw NPM Release` 的仅验证预检也接受当前完整 40 字符工作流分支提交 SHA,而不要求已推送标签
|
||||
- 这条 SHA 路径仅用于验证,不能被提升为真实发布
|
||||
- 在 SHA 模式下,工作流只会为包元数据检查合成 `v<package.json version>`;真实发布仍然需要真实的发布标签
|
||||
- 这两个工作流都会将真实发布和提升路径保留在 GitHub-hosted runner 上,而非变更型验证路径则可以使用更大的 Blacksmith Linux runner
|
||||
- 该工作流会运行
|
||||
- `OpenClaw NPM Release` 的仅验证预检也接受当前完整的 40 字符 workflow 分支提交 SHA,而不要求已有已推送的标签
|
||||
- 该 SHA 路径仅用于验证,不能提升为真实发布
|
||||
- 在 SHA 模式下,workflow 仅为软件包元数据检查合成 `v<package.json version>`;真实发布仍然需要真实的发布标签
|
||||
- 两个 workflow 都会将真实发布和提升路径保留在 GitHub-hosted runners 上,而非变更性的验证路径则可使用更大的 Blacksmith Linux runners
|
||||
- 该 workflow 会运行
|
||||
`OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache`
|
||||
并使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 两个工作流密钥
|
||||
- npm 发布预检不再等待单独的发布检查 lane
|
||||
并使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 两个 workflow secrets
|
||||
- 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/修正版版本),以在全新临时前缀中验证已发布 registry 安装路径
|
||||
- 在 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`
|
||||
以针对已发布 npm 包验证已安装包的新手引导、Telegram 设置和真实 Telegram E2E,并使用共享的租赁 Telegram 凭证池。维护者在本地一次性运行时可以省略 Convex 变量,直接传入三个 `OPENCLAW_QA_TELEGRAM_*` 环境凭证。
|
||||
- 维护者也可以通过 GitHub Actions 中的手动 `NPM Telegram Beta E2E` 工作流运行相同的发布后检查。它被有意设计为仅手动运行,不会在每次合并时执行。
|
||||
(或匹配的 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`
|
||||
来验证基于已发布 npm 软件包的已安装软件包新手引导、Telegram 设置以及真实 Telegram E2E,使用共享的租赁 Telegram 凭证池。本地维护者的一次性运行可以省略 Convex 变量,直接传入三个 `OPENCLAW_QA_TELEGRAM_*` 环境变量凭证。
|
||||
- 维护者也可以通过 GitHub Actions 中的手动 `NPM Telegram Beta E2E` workflow 运行相同的发布后检查。它有意仅支持手动运行,不会在每次合并时执行。
|
||||
- 维护者发布自动化现在采用先预检再提升:
|
||||
- 真实 npm 发布必须通过成功的 npm `preflight_run_id`
|
||||
- 真实 npm 发布必须从与成功预检运行相同的 `main` 或
|
||||
`release/YYYY.M.D` 分支分发
|
||||
- 稳定版 npm 发布默认指向 `beta`
|
||||
- 稳定版 npm 发布可通过工作流输入显式指定 `latest`
|
||||
- 基于令牌的 npm dist-tag 变更现在位于
|
||||
- 真实 npm 发布必须从与成功预检运行相同的 `main` 或 `release/YYYY.M.D` 分支分发
|
||||
- stable npm 发布默认指向 `beta`
|
||||
- stable npm 发布可以通过 workflow 输入显式指定 `latest`
|
||||
- 基于 token 的 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` 这样的稳定版修正版发布,发布后验证器还会检查从 `YYYY.M.D` 到 `YYYY.M.D-N` 的相同临时前缀升级路径,这样发布修正就不会悄悄让旧的全局安装仍停留在基础稳定版载荷上
|
||||
- npm 发布预检会以失败关闭方式终止,除非 tarball 同时包含 `dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 载荷,这样我们就不会再次发布空的浏览器仪表板
|
||||
- 发布后验证还会检查已发布 registry 安装是否在根 `dist/*`
|
||||
布局下包含非空的内置插件运行时依赖。若某次发布携带缺失或为空的内置插件依赖载荷,则发布后验证器会失败,且不能被提升为 `latest`。
|
||||
- `pnpm test:install:smoke` 也会对候选更新 tarball 强制执行 npm pack `unpackedSize` 预算,因此安装器 e2e 能在发布路径之前捕获意外的打包膨胀
|
||||
- 如果发布工作修改了 CI 规划、扩展计时清单或扩展测试矩阵,请在审批前重新生成并审查来自 `.github/workflows/ci.yml` 的、由规划器拥有的 `checks-node-extensions` 工作流矩阵输出,这样发布说明就不会描述过时的 CI 布局
|
||||
- 稳定版 macOS 发布就绪性还包括更新器表面:
|
||||
- GitHub release 最终必须包含打包好的 `.zip`、`.dmg` 和 `.dSYM.zip`
|
||||
- 发布后,`main` 上的 `appcast.xml` 必须指向新的稳定版 zip
|
||||
- 打包应用必须保持非调试 bundle id、非空 Sparkle feed URL,以及不低于该发布版本规范 Sparkle 构建下限的 `CFBundleVersion`
|
||||
- 对于像 `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`。
|
||||
- `pnpm test:install:smoke` 还会对候选更新 tarball 的 npm pack `unpackedSize` 预算进行强制检查,因此安装器 e2e 能在发布路径之前捕获意外的软件包膨胀
|
||||
- 如果发布工作涉及 CI 规划、扩展时序清单或扩展测试矩阵,请在审批前重新生成并审查来自 `.github/workflows/ci.yml` 的、由规划器拥有的 `checks-node-extensions` workflow 矩阵输出,以免发布说明描述了过时的 CI 布局
|
||||
- stable macOS 发布就绪还包括更新器相关界面:
|
||||
- GitHub release 最终必须包含已打包的 `.zip`、`.dmg` 和 `.dSYM.zip`
|
||||
- 发布后,`main` 上的 `appcast.xml` 必须指向新的 stable zip
|
||||
- 打包后的应用必须保持非调试 bundle id、非空 Sparkle feed URL,以及不低于该发布版本规范 Sparkle 构建底线的 `CFBundleVersion`
|
||||
|
||||
## 发布测试环境
|
||||
## 发布测试框
|
||||
|
||||
`Full Release Validation` 是操作员从一个入口点启动所有预发布测试的方式。请从受信任的 `main` 工作流 ref 运行它,并将发布分支、标签或完整提交 SHA 作为 `ref` 传入:
|
||||
`Full Release Validation` 是操作员从一个入口点启动所有预发布测试的方式。从可信的 `main` workflow ref 运行它,并将发布分支、标签或完整提交 SHA 作为 `ref` 传入:
|
||||
|
||||
```bash
|
||||
gh workflow run full-release-validation.yml \
|
||||
@ -149,27 +161,29 @@ gh workflow run full-release-validation.yml \
|
||||
-f mode=both
|
||||
```
|
||||
|
||||
该工作流会解析目标 ref,使用 `target_ref=<release-ref>` 分发手动 `CI`,分发 `OpenClaw Release Checks`,并在设置了 `npm_telegram_package_spec` 时可选分发独立的发布后 Telegram E2E。然后,`OpenClaw Release Checks` 会进一步扇出安装 smoke、跨操作系统发布检查、live/E2E Docker 发布路径覆盖、带 Telegram 包 QA 的 Package Acceptance、QA Lab parity、live Matrix 和 live Telegram。只有当 `Full Release Validation` 摘要显示 `normal_ci` 和 `release_checks` 均成功,且任意可选 `npm_telegram` 子任务也成功或被有意跳过时,整轮运行才算可接受。
|
||||
子工作流会从运行 `Full Release Validation` 的受信任 ref 分发,通常是 `--ref main`,即便目标 `ref` 指向较旧的发布分支或标签也是如此。不存在单独的 Full Release Validation 工作流 ref 输入;通过选择工作流运行 ref 来选择受信任的 harness。
|
||||
该 workflow 会解析目标 ref,使用
|
||||
`target_ref=<release-ref>` 分发手动 `CI`,分发 `OpenClaw Release Checks`,并在设置了
|
||||
`npm_telegram_package_spec` 时可选择分发独立的发布后 Telegram E2E。随后,`OpenClaw Release Checks` 会进一步展开安装冒烟测试、跨操作系统发布检查、live/E2E Docker 发布路径覆盖、带 Telegram 软件包 QA 的 Package Acceptance、QA Lab 一致性、live Matrix 和 live Telegram。只有当 `Full Release Validation` 摘要中 `normal_ci` 和 `release_checks` 均显示成功,且任何可选的 `npm_telegram` 子任务要么成功要么被有意跳过时,完整运行才可接受。
|
||||
子 workflow 会从运行 `Full Release Validation` 的可信 ref 分发,通常是 `--ref main`,即使目标 `ref` 指向较旧的发布分支或标签也是如此。没有单独的 Full Release Validation workflow-ref 输入;通过选择 workflow 运行 ref 来选择可信 harness。
|
||||
|
||||
根据发布阶段使用以下变体:
|
||||
|
||||
```bash
|
||||
# 验证尚未发布的发布候选分支。
|
||||
# 验证尚未发布的候选发布分支。
|
||||
gh workflow run full-release-validation.yml \
|
||||
--ref main \
|
||||
-f ref=release/YYYY.M.D \
|
||||
-f provider=openai \
|
||||
-f mode=both
|
||||
|
||||
# 验证某个已推送的精确提交。
|
||||
# 验证一个已推送的精确提交。
|
||||
gh workflow run full-release-validation.yml \
|
||||
--ref main \
|
||||
-f ref=<40-char-sha> \
|
||||
-f provider=openai \
|
||||
-f mode=both
|
||||
|
||||
# 在 beta 发布后,加入已发布包的 Telegram E2E。
|
||||
# 发布 beta 后,增加针对已发布软件包的 Telegram E2E。
|
||||
gh workflow run full-release-validation.yml \
|
||||
--ref main \
|
||||
-f ref=release/YYYY.M.D \
|
||||
@ -179,21 +193,20 @@ gh workflow run full-release-validation.yml \
|
||||
-f npm_telegram_provider_mode=mock-openai
|
||||
```
|
||||
|
||||
在聚焦修复之后,不要把完整总验证作为第一次重跑。如果某个测试环境失败,请使用失败的子工作流、作业、Docker lane、包 profile、模型提供商或 QA lane 作为下一次证明。只有当修复改动了共享发布编排,或使之前所有测试环境的证据失效时,才重新运行完整总验证。总验证的最终验证器会重新检查已记录的子工作流运行 id,因此在某个子工作流成功重跑后,只需重新运行失败的 `Verify full validation` 父作业。
|
||||
不要在针对某个聚焦修复的首次重跑时使用完整总流程。如果某个测试框失败,请使用失败的子 workflow、作业、Docker 通道、软件包配置、模型提供商或 QA 通道作为下一次证明。只有当修复更改了共享发布编排,或使早先的全框证据失效时,才再次运行完整总流程。总流程的最终验证器会重新检查已记录的子 workflow 运行 id,因此在某个子 workflow 成功重跑后,只需重跑失败的 `Verify full validation` 父作业。
|
||||
|
||||
### Vitest
|
||||
|
||||
Vitest 测试环境是手动 `CI` 子工作流。手动 CI 会有意绕过 changed scoping,并强制对发布候选版本执行正常测试图谱:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、build smoke、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。
|
||||
Vitest 测试框是手动 `CI` 子 workflow。手动 CI 会有意绕过 changed 范围限制,并对发布候选版本强制运行常规测试图:Linux Node 分片、bundled-plugin 分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟测试、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。
|
||||
|
||||
使用这个测试环境来回答“源码树是否通过了完整的常规测试套件?”
|
||||
它并不等同于发布路径产品验证。需要保留的证据:
|
||||
使用此测试框来回答“源码树是否通过了完整的常规测试套件?”这个问题。它不同于发布路径产品验证。需要保留的证据:
|
||||
|
||||
- 显示已分发 `CI` 运行 URL 的 `Full Release Validation` 摘要
|
||||
- 针对精确目标 SHA 呈绿色的 `CI` 运行
|
||||
- 在调查回归时,记录 CI 作业中的失败或较慢分片名称
|
||||
- 当运行需要性能分析时,记录诸如 `.artifacts/vitest-shard-timings.json` 这样的 Vitest 计时制品
|
||||
- 在精确目标 SHA 上呈绿色的 `CI` 运行
|
||||
- 在调查回归时,CI 作业中的失败或缓慢分片名称
|
||||
- 当某次运行需要性能分析时,像 `.artifacts/vitest-shard-timings.json` 这样的 Vitest 计时产物
|
||||
|
||||
只有当发布需要确定性的常规 CI,而不需要 Docker、QA Lab、live、跨操作系统或 package 测试环境时,才直接运行手动 CI:
|
||||
只有当发布需要确定性的常规 CI,而不需要 Docker、QA Lab、live、跨操作系统或软件包测试框时,才直接运行手动 CI:
|
||||
|
||||
```bash
|
||||
gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D
|
||||
@ -201,52 +214,66 @@ gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D
|
||||
|
||||
### Docker
|
||||
|
||||
Docker 测试环境位于 `OpenClaw Release Checks` 中,通过 `openclaw-live-and-e2e-checks-reusable.yml` 以及发布模式的 `install-smoke` 工作流提供。它通过打包好的 Docker 环境来验证发布候选版本,而不仅仅是源码级测试。
|
||||
Docker 测试框位于 `OpenClaw Release Checks` 中,通过
|
||||
`openclaw-live-and-e2e-checks-reusable.yml` 以及发布模式的
|
||||
`install-smoke` workflow 提供。它会通过已打包的 Docker 环境来验证发布候选版本,而不仅仅是源码级测试。
|
||||
|
||||
发布 Docker 覆盖范围包括:
|
||||
发布 Docker 覆盖包括:
|
||||
|
||||
- 启用了慢速 Bun 全局安装 smoke 的完整安装 smoke
|
||||
- 仓库 E2E lane
|
||||
- 发布路径 Docker 分块:`core`、`package-update`、`plugins-runtime` 和 `bundled-channels`
|
||||
- 在请求时,于 `plugins-runtime` 分块中覆盖 OpenWebUI
|
||||
- 将内置渠道依赖 lane 拆分到它们自己的 `bundled-channels` 分块中,而不是串行的全合一内置渠道 lane
|
||||
- 拆分后的内置插件安装/卸载 lane:
|
||||
- 启用了较慢 Bun 全局安装冒烟测试的完整安装冒烟测试
|
||||
- 仓库 E2E 通道
|
||||
- 发布路径 Docker 分块:`core`、`package-update-openai`、
|
||||
`package-update-anthropic`、`package-update-core`、`plugins-runtime-core`、
|
||||
`plugins-runtime-install-a`、`plugins-runtime-install-b` 和
|
||||
`bundled-channels`
|
||||
- 在请求时,于 `plugins-runtime-core` 分块中包含 OpenWebUI 覆盖
|
||||
- 将 bundled-channel 依赖通道拆分到独立的 `bundled-channels` 分块中,
|
||||
而不是串行的一体式 bundled-channel 通道
|
||||
- 拆分后的 bundled plugin 安装/卸载通道
|
||||
`bundled-plugin-install-uninstall-0` 到
|
||||
`bundled-plugin-install-uninstall-7`
|
||||
- 当发布检查包含 live suite 时,运行 live/E2E provider 套件和 Docker live 模型覆盖
|
||||
- 当发布检查包含 live 套件时,live/E2E provider 套件和 Docker live 模型覆盖
|
||||
|
||||
重跑前请先使用 Docker 制品。发布路径调度器会上传 `.artifacts/docker-tests/`,其中包含 lane 日志、`summary.json`、`failures.json`、阶段耗时、调度器计划 JSON 和重跑命令。对于聚焦恢复,请在可复用 live/E2E 工作流上使用 `docker_lanes=<lane[,lane]>`,而不是重跑所有发布分块。生成的重跑命令会在可用时包含之前的 `package_artifact_run_id` 和预制 Docker 镜像输入,因此失败的 lane 可以复用相同的 tarball 和 GHCR 镜像。
|
||||
重跑前先使用 Docker 产物。发布路径调度器会上传
|
||||
`.artifacts/docker-tests/`,其中包含通道日志、`summary.json`、`failures.json`、
|
||||
阶段计时、调度器计划 JSON 和重跑命令。若要进行聚焦恢复,请在可复用的 live/E2E workflow 上使用
|
||||
`docker_lanes=<lane[,lane]>`,而不是重跑所有发布分块。生成的重跑命令会在可用时包含先前的
|
||||
`package_artifact_run_id` 和已准备好的 Docker 镜像输入,因此失败的通道可以复用相同的 tarball 和 GHCR 镜像。
|
||||
|
||||
### QA Lab
|
||||
|
||||
QA Lab 测试环境也是 `OpenClaw Release Checks` 的一部分。它是智能体行为和渠道级发布 gate,与 Vitest 和 Docker 包机制分离。
|
||||
QA Lab 测试框也是 `OpenClaw Release Checks` 的一部分。它是智能体行为和渠道级别的发布门禁,与 Vitest 和 Docker 软件包机制分开。
|
||||
|
||||
发布 QA Lab 覆盖范围包括:
|
||||
发布 QA Lab 覆盖包括:
|
||||
|
||||
- mock parity gate:使用智能体 parity 包,将 OpenAI 候选 lane 与 Opus 4.6 基线进行比较
|
||||
- 使用 `qa-live-shared` 环境的快速 live Matrix QA profile
|
||||
- 使用 Convex CI 凭证租约的 live Telegram QA lane
|
||||
- 当发布遥测需要明确本地证明时,运行 `pnpm qa:otel:smoke`
|
||||
- 使用 agentic parity pack,将 OpenAI 候选通道与 Opus 4.6 基线进行比较的 mock 一致性门禁
|
||||
- 使用 `qa-live-shared` 环境的快速 live Matrix QA 配置
|
||||
- 使用 Convex CI 凭证租约的 live Telegram QA 通道
|
||||
- 当发布遥测需要显式本地证明时运行 `pnpm qa:otel:smoke`
|
||||
|
||||
使用这个测试环境来回答“该发布在 QA 场景和 live 渠道流程中是否行为正确?”
|
||||
在批准发布时,请保留 parity、Matrix 和 Telegram lane 的制品 URL。完整 Matrix 覆盖仍可通过手动分片 QA-Lab 运行获得,而不是默认的发布关键 lane。
|
||||
使用这个测试框来回答“该发布在 QA 场景和 live 渠道流程中的行为是否正确?”批准发布时,请保留 parity、Matrix 和 Telegram 通道的产物 URL。完整的 Matrix 覆盖仍可作为手动分片 QA-Lab 运行来获得,而不是默认的发布关键通道。
|
||||
|
||||
### Package
|
||||
|
||||
Package 测试环境是可安装产品 gate。它由 `Package Acceptance` 和解析器 `scripts/resolve-openclaw-package-candidate.mjs` 支持。该解析器会将候选版本规范化为 Docker E2E 消费的 `package-under-test` tarball,验证包清单,记录包版本和 SHA-256,并将工作流 harness ref 与包源 ref 分离。
|
||||
Package 测试框是可安装产品门禁。它由
|
||||
`Package Acceptance` 和解析器
|
||||
`scripts/resolve-openclaw-package-candidate.mjs` 支持。该解析器会将候选版本标准化为供 Docker E2E 使用的 `package-under-test` tarball,验证软件包清单,记录软件包版本和 SHA-256,并将 workflow harness ref 与软件包源 ref 分离。
|
||||
|
||||
支持的候选来源:
|
||||
|
||||
- `source=npm`:`openclaw@beta`、`openclaw@latest` 或某个精确 OpenClaw 发布版本
|
||||
- `source=ref`:使用所选 `workflow_ref` harness 打包一个受信任的 `package_ref` 分支、标签或完整提交 SHA
|
||||
- `source=url`:下载一个带必需 `package_sha256` 的 HTTPS `.tgz`
|
||||
- `source=artifact`:复用另一条 GitHub Actions 运行上传的 `.tgz`
|
||||
- `source=npm`:`openclaw@beta`、`openclaw@latest` 或精确的 OpenClaw 发布版本
|
||||
- `source=ref`:使用所选 `workflow_ref` harness 打包可信的 `package_ref` 分支、标签或完整提交 SHA
|
||||
- `source=url`:下载带有必需 `package_sha256` 的 HTTPS `.tgz`
|
||||
- `source=artifact`:复用由其他 GitHub Actions 运行上传的 `.tgz`
|
||||
|
||||
`OpenClaw Release Checks` 会以 `source=ref`、`package_ref=<release-ref>`、`suite_profile=custom`、`docker_lanes=bundled-channel-deps-compat plugins-offline` 和 `telegram_mode=mock-openai` 运行 Package Acceptance。发布路径 Docker 分块覆盖了重叠的安装、更新和插件更新 lane;Package Acceptance 则保留了原生制品的内置渠道兼容性、离线插件 fixture,以及针对同一解析 tarball 的 Telegram 包 QA。它是 GitHub 原生方式下,大多数过去需要 Parallels 的 package/update 覆盖的替代方案。跨操作系统发布检查对于操作系统特定的新手引导、安装器和平台行为仍然重要,但 package/update 产品验证应优先使用 Package Acceptance。
|
||||
`OpenClaw Release Checks` 会以 `source=ref`、
|
||||
`package_ref=<release-ref>`、`suite_profile=custom`、
|
||||
`docker_lanes=bundled-channel-deps-compat plugins-offline` 和
|
||||
`telegram_mode=mock-openai` 运行 Package Acceptance。发布路径 Docker 分块覆盖了其中重叠的安装、更新和插件更新通道;Package Acceptance 则保留了原生制品的 bundled-channel 兼容性、离线插件夹具,以及针对同一个已解析 tarball 的 Telegram 软件包 QA。它是 GitHub 原生方案,用来替代此前大多数依赖 Parallels 的软件包/更新覆盖。跨操作系统发布检查对特定操作系统的新手引导、安装器和平台行为仍然重要,但软件包/更新产品验证应优先使用 Package Acceptance。
|
||||
|
||||
旧版 package-acceptance 宽松策略被有意限定在时间范围内。到 `2026.4.25` 为止的包可以使用兼容路径来处理已发布到 npm 的元数据缺口:tarball 中缺失的私有 QA 清单条目、缺失的 `gateway install --wrapper`、tarball 派生 git fixture 中缺失的 patch 文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。`2026.4.25` 之后的包必须满足现代包契约;这些缺口都会导致发布验证失败。
|
||||
旧版 package-acceptance 的宽松处理被有意限制了时效。直到 `2026.4.25` 的软件包,仍可对已发布到 npm 的元数据缺口使用兼容路径:tarball 中缺失的私有 QA inventory 条目、缺失的 `gateway install --wrapper`、tarball 派生 git 夹具中缺失的补丁文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。`2026.4.25` 之后的软件包必须满足现代软件包契约;同样的缺口会导致发布验证失败。
|
||||
|
||||
当发布问题涉及真实可安装包时,请使用更广泛的 Package Acceptance profile:
|
||||
当发布问题涉及实际可安装的软件包时,请使用更广泛的 Package Acceptance 配置:
|
||||
|
||||
```bash
|
||||
gh workflow run package-acceptance.yml \
|
||||
@ -257,60 +284,63 @@ gh workflow run package-acceptance.yml \
|
||||
-f suite_profile=product
|
||||
```
|
||||
|
||||
常见 package profile:
|
||||
常见软件包配置:
|
||||
|
||||
- `smoke`:快速包安装/渠道/智能体、Gateway 网关网络和配置重载 lane
|
||||
- `package`:安装/更新/插件包契约,不含 live ClawHub;这是发布检查默认值
|
||||
- `product`:`package` 加上 MCP 渠道、cron/subagent 清理、OpenAI Web 搜索和 OpenWebUI
|
||||
- `smoke`:快速软件包安装/渠道/智能体、Gateway 网关网络和配置热重载通道
|
||||
- `package`:不含 live ClawHub 的安装/更新/插件软件包契约;这是发布检查默认值
|
||||
- `product`:在 `package` 基础上增加 MCP 渠道、cron/subagent 清理、OpenAI web 搜索和 OpenWebUI
|
||||
- `full`:带 OpenWebUI 的 Docker 发布路径分块
|
||||
- `custom`:精确的 `docker_lanes` 列表,用于聚焦重跑
|
||||
- `custom`:用于聚焦重跑的精确 `docker_lanes` 列表
|
||||
|
||||
如需 package 候选版本的 Telegram 证明,请在 Package Acceptance 上启用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier`。工作流会将解析后的 `package-under-test` tarball 传入 Telegram lane;独立的 Telegram 工作流仍接受已发布的 npm spec,用于发布后检查。
|
||||
若要获取软件包候选版本的 Telegram 证明,请在 Package Acceptance 上启用
|
||||
`telegram_mode=mock-openai` 或 `telegram_mode=live-frontier`。该 workflow 会将已解析的
|
||||
`package-under-test` tarball 传入 Telegram 通道;独立的 Telegram workflow 仍然接受已发布的 npm 规格以进行发布后检查。
|
||||
|
||||
## NPM 工作流输入
|
||||
## NPM workflow 输入
|
||||
|
||||
`OpenClaw NPM Release` 接受以下由操作员控制的输入:
|
||||
|
||||
- `tag`:必需的发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或 `v2026.4.2-beta.1`;当 `preflight_only=true` 时,也可以是当前完整 40 字符工作流分支提交 SHA,用于仅验证预检
|
||||
- `tag`:必需的发布标签,如 `v2026.4.2`、`v2026.4.2-1` 或
|
||||
`v2026.4.2-beta.1`;当 `preflight_only=true` 时,也可以是当前完整的 40 字符 workflow 分支提交 SHA,用于仅验证的预检
|
||||
- `preflight_only`:`true` 表示仅验证/构建/打包,`false` 表示真实发布路径
|
||||
- `preflight_run_id`:真实发布路径中必填,以便工作流复用成功预检运行中准备好的 tarball
|
||||
- `npm_dist_tag`:发布路径的 npm 目标标签;默认为 `beta`
|
||||
- `preflight_run_id`:真实发布路径上必需,以便 workflow 复用成功预检运行中准备好的 tarball
|
||||
- `npm_dist_tag`:发布路径的 npm 目标标签;默认值为 `beta`
|
||||
|
||||
`OpenClaw Release Checks` 接受以下由操作员控制的输入:
|
||||
|
||||
- `ref`:要验证的分支、标签或完整提交 SHA。带密钥的检查要求解析后的提交必须可从某个 OpenClaw 分支或发布标签到达。
|
||||
- `ref`:要验证的分支、标签或完整提交 SHA。含 secrets 的检查要求解析后的提交可从某个 OpenClaw 分支或发布标签到达。
|
||||
|
||||
规则:
|
||||
|
||||
- 稳定版和修正版标签可以发布到 `beta` 或 `latest`
|
||||
- Stable 和修正版标签可以发布到 `beta` 或 `latest`
|
||||
- Beta 预发布标签只能发布到 `beta`
|
||||
- 对于 `OpenClaw NPM Release`,仅当 `preflight_only=true` 时才允许使用完整提交 SHA 输入
|
||||
- 对于 `OpenClaw NPM Release`,只有在 `preflight_only=true` 时才允许输入完整提交 SHA
|
||||
- `OpenClaw Release Checks` 和 `Full Release Validation` 始终仅用于验证
|
||||
- 真实发布路径必须使用预检期间使用的同一个 `npm_dist_tag`;工作流会在发布继续前验证该元数据
|
||||
- 真实发布路径必须使用与预检期间相同的 `npm_dist_tag`;workflow 会在继续发布前验证该元数据
|
||||
|
||||
## 稳定版 npm 发布顺序
|
||||
## Stable npm 发布顺序
|
||||
|
||||
在切稳定版 npm 发布时:
|
||||
在切 stable npm 发布时:
|
||||
|
||||
1. 运行 `OpenClaw NPM Release`,并设置 `preflight_only=true`
|
||||
- 在标签尚不存在之前,你可以使用当前完整工作流分支提交
|
||||
SHA,对预检工作流进行仅验证的 dry run
|
||||
2. 在常规的 beta-first 流程中选择 `npm_dist_tag=beta`;仅当你明确想直接发布稳定版时才选择 `latest`
|
||||
3. 当你希望通过一个手动工作流同时获得常规 CI、live prompt cache、Docker、QA Lab、Matrix 和 Telegram 覆盖时,请针对发布分支、发布标签或完整提交 SHA 运行 `Full Release Validation`
|
||||
4. 如果你有意只需要确定性的常规测试图谱,则改为在发布 ref 上运行手动 `CI` 工作流
|
||||
1. 使用 `preflight_only=true` 运行 `OpenClaw NPM Release`
|
||||
- 在标签尚不存在时,你可以使用当前完整 workflow 分支提交 SHA,对预检 workflow 进行仅验证的演练
|
||||
2. 对于正常的 beta 优先流程,选择 `npm_dist_tag=beta`;只有在你有意直接发布 stable 时,才选择 `latest`
|
||||
3. 当你希望从一个手动 workflow 获得常规 CI 加上 live prompt cache、Docker、QA Lab、Matrix 和 Telegram 覆盖时,对发布分支、发布标签或完整提交 SHA 运行 `Full Release Validation`
|
||||
4. 如果你有意只需要确定性的常规测试图,则改为在发布 ref 上运行手动 `CI` workflow
|
||||
5. 保存成功的 `preflight_run_id`
|
||||
6. 再次运行 `OpenClaw NPM Release`,并设置 `preflight_only=false`,同时传入相同的 `tag`、相同的 `npm_dist_tag` 以及保存的 `preflight_run_id`
|
||||
7. 如果该发布落在 `beta` 上,请使用私有的
|
||||
6. 再次运行 `OpenClaw NPM Release`,设置 `preflight_only=false`,并使用相同的
|
||||
`tag`、相同的 `npm_dist_tag` 和保存的 `preflight_run_id`
|
||||
7. 如果发布落在 `beta` 上,使用私有
|
||||
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
|
||||
工作流,将该稳定版从 `beta` 提升到 `latest`
|
||||
8. 如果该发布有意直接发布到 `latest`,并且 `beta`
|
||||
也应立即跟随同一个稳定构建,请使用同一个私有工作流将两个 dist-tag 都指向该稳定版本,或者让其计划中的自愈同步稍后再移动 `beta`
|
||||
workflow 将该 stable 版本从 `beta` 提升到 `latest`
|
||||
8. 如果该发布有意直接发布到 `latest`,并且 `beta` 应立即跟随同一个 stable 构建,则使用同一个私有 workflow 将两个 dist-tag 都指向该 stable 版本,或者让其计划的自愈同步稍后再移动 `beta`
|
||||
|
||||
出于安全原因,dist-tag 变更位于私有仓库中,因为它仍需要 `NPM_TOKEN`,而公共仓库保持仅 OIDC 发布。
|
||||
dist-tag 变更位于私有仓库中以保证安全,因为它仍需要
|
||||
`NPM_TOKEN`,而公开仓库保持仅使用 OIDC 的发布方式。
|
||||
|
||||
这样可以让直接发布路径和 beta-first 提升路径都被文档化,并对操作员可见。
|
||||
这使得直接发布路径和 beta 优先提升路径都得到了文档记录,并且对操作员可见。
|
||||
|
||||
如果维护者必须回退到本地 npm 认证,请仅在专用 tmux 会话内运行任何 1Password CLI(`op`)命令。不要直接从主智能体 shell 调用 `op`;将其限制在 tmux 中可以让提示、警报和 OTP 处理可观察,并防止重复的主机警报。
|
||||
如果维护者必须回退到本地 npm 身份验证,请仅在专用 tmux 会话中运行任何 1Password CLI(`op`)命令。不要直接从主智能体 shell 调用 `op`;将其限制在 tmux 内可以让提示、警报和 OTP 处理保持可观察,并防止重复的主机警报。
|
||||
|
||||
## 公开参考
|
||||
|
||||
@ -330,4 +360,4 @@ gh workflow run package-acceptance.yml \
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [发布通道](/zh-CN/install/development-channels)
|
||||
- [发布渠道](/zh-CN/install/development-channels)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user