From 7ca450d76f7a12ba812a4a68aa892fee32ab8bb3 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Mon, 27 Apr 2026 22:53:31 +0000 Subject: [PATCH] chore(i18n): refresh zh-CN translations --- docs/zh-CN/ci.md | 176 ++++----- docs/zh-CN/help/testing.md | 591 ++++++++++++++--------------- docs/zh-CN/logging.md | 109 +++--- docs/zh-CN/plugins/sdk-subpaths.md | 420 ++++++++++---------- docs/zh-CN/plugins/sdk-testing.md | 89 +++-- docs/zh-CN/reference/RELEASING.md | 295 +++++++------- docs/zh-CN/tools/index.md | 190 +++++----- 7 files changed, 944 insertions(+), 926 deletions(-) diff --git a/docs/zh-CN/ci.md b/docs/zh-CN/ci.md index 293f0b3a2..ef7888057 100644 --- a/docs/zh-CN/ci.md +++ b/docs/zh-CN/ci.md @@ -1,63 +1,64 @@ --- read_when: - - 你需要了解某个 CI 作业为何运行或未运行。 - - 你正在调试失败的 GitHub Actions 检查。 -summary: CI 作业图、作用域门控,以及本地等效命令 + - 你需要了解为什么某个 CI 作业运行了或没有运行 + - 你正在调试失败的 GitHub Actions 检查 +summary: CI 作业图、范围门禁,以及本地等效命令 title: CI 流水线 x-i18n: - generated_at: "2026-04-27T19:38:35Z" + generated_at: "2026-04-27T22:50:24Z" model: gpt-5.4 provider: openai - source_hash: 4b6aef34b73f85ef7dae00d21cebfa7c560173dd7b979ca19829ea5290972047 + source_hash: 4bc5befeb5ad84227dd8b36f4ee3b91166c9e5c4417eacb82f9500d568359558 source_path: ci.md workflow: 15 --- -CI 会在每次推送到 `main` 以及每个拉取请求上运行。它使用智能作用域划分,在仅有不相关区域变更时跳过昂贵作业。手动触发的 `workflow_dispatch` 运行会有意绕过智能作用域,并展开完整的常规 CI 作业图,用于发布候选或大范围验证。 +CI 会在每次推送到 `main` 以及每个拉取请求时运行。它使用智能范围划分,只在相关区域发生变更时运行昂贵作业;如果只是无关区域变更,则会跳过这些作业。手动触发的 `workflow_dispatch` 运行会有意绕过智能范围划分,并展开完整的常规 CI 作业图,用于发布候选版本或大范围验证。 -`Full Release Validation` 是用于“发布前运行所有内容”的手动总控工作流。它接受分支、标签或完整提交 SHA,使用该目标分发手动 `CI` 工作流,并分发 `OpenClaw Release Checks`,以执行安装冒烟测试、包验收、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab 对等性、Matrix 和 Telegram 流水线。提供已发布的包规格时,它还可以运行发布后的 `NPM Telegram Beta E2E` 工作流。这个总控工作流会记录已分发的子运行 ID,最终的 `Verify full validation` 作业会重新检查当前子运行的结论。如果某个子工作流被重新运行并变为绿色,只需重新运行父级验证器作业即可刷新总控结果。 +`Full Release Validation` 是用于“发布前运行所有内容”的手动总控工作流。它接受分支、标签或完整提交 SHA,使用该目标触发手动 `CI` 工作流,并触发 `OpenClaw Release Checks`,以运行安装冒烟测试、包验收、Docker 发布路径测试套件、实时 / E2E、OpenWebUI、QA Lab 一致性、Matrix 和 Telegram 测试路径。如果提供了已发布的软件包规格,它还可以运行发布后的 `NPM Telegram Beta E2E` 工作流。这个总控工作流会记录所触发的子运行 id,而最终的 `Verify full validation` 作业会重新检查当前各个子运行的结论。如果某个子工作流被重新运行并变为绿色,只需重新运行父级验证器作业即可刷新总控结果。 -发布 live/E2E 子工作流仍然保留广泛的原生 `pnpm test:live` 覆盖,但它不再作为一个串行作业运行,而是通过 `scripts/test-live-shard.mjs` 以具名分片形式运行(`native-live-src-agents`、`native-live-src-gateway-core`、`native-live-src-gateway-backends`、`native-live-test`、`native-live-extensions-a-k`、`native-live-extensions-l-n`、`native-live-extensions-openai`、`native-live-extensions-o-z` 和 `native-live-extensions-media`)。这样在保持相同文件覆盖率的同时,也让缓慢的 live provider 故障更容易重跑和诊断。 +为便于恢复,`Full Release Validation` 和 `OpenClaw Release Checks` 都接受 `rerun_group`。发布候选版本使用 `all`;如果只想重新运行常规完整 CI 子工作流,使用 `ci`;如果想重新运行所有发布相关子工作流,使用 `release-checks`;也可以使用更窄的发布分组:在总控工作流中可选 `install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live` 或 `npm-telegram`。这样在针对性修复后,就能把失败发布测试环境的重跑范围控制在较小范围内。 -`Package Acceptance` 是一个侧运行工作流,用于验证包产物,而不会阻塞发布工作流。它可以从已发布的 npm 规格、使用所选 `workflow_ref` harness 构建的可信 `package_ref`、带 SHA-256 的 HTTPS tarball URL,或来自另一个 GitHub Actions 运行的 tarball 产物中解析出一个候选包,将其上传为 `package-under-test`,然后复用 Docker 发布/E2E 调度器,对这个 tarball 运行,而不是重新打包工作流检出内容。配置档覆盖 smoke、package、product、full,以及自定义 Docker 流水线选择。`package` 配置档使用离线插件覆盖,因此已发布包验证不会被 live ClawHub 可用性卡住。可选的 Telegram 流水线会在 `NPM Telegram Beta E2E` 工作流中复用 `package-under-test` 产物,而单独分发时仍保留已发布 npm 规格路径。 +发布用的实时 / E2E 子工作流仍保留广泛的原生 `pnpm test:live` 覆盖范围,但它会通过 `scripts/test-live-shard.mjs` 将其拆分为具名分片运行:`native-live-src-agents`、`native-live-src-gateway-core`、`native-live-src-gateway-backends`、`native-live-test`、`native-live-extensions-a-k`、`native-live-extensions-l-n`、`native-live-extensions-openai`、`native-live-extensions-o-z` 和 `native-live-extensions-media`,而不是作为一个串行作业运行。这样既保留相同的文件覆盖范围,也让耗时较长的实时提供商失败更容易重跑和诊断。 + +`Package Acceptance` 是一个旁路运行工作流,用于验证某个软件包制品,而不会阻塞发布工作流。它会从已发布的 npm 规格、使用所选 `workflow_ref` 测试框架构建的可信 `package_ref`、带有 SHA-256 的 HTTPS tarball URL,或来自其他 GitHub Actions 运行的 tarball 制品中解析出一个候选包,将其上传为 `package-under-test`,然后复用 Docker 发布 / E2E 调度器,用这个 tarball 替代对工作流检出内容的重新打包。它支持 smoke、package、product、full 以及自定义 Docker 测试路径选择等配置档。`package` 配置档使用离线插件覆盖,因此已发布软件包的验证不依赖实时的 ClawHub 可用性。可选的 Telegram 测试路径会在 `NPM Telegram Beta E2E` 工作流中复用 `package-under-test` 制品,而已发布 npm 规格的路径则保留给独立触发场景。 ## 包验收 -当问题是“这个可安装的 OpenClaw 包作为一个产品是否可用?”时,请使用 `Package Acceptance`。它与常规 CI 不同:常规 CI 验证源代码树,而包验收则通过用户在安装或更新后实际经历的同一套 Docker E2E harness 来验证单个 tarball。 +当问题是“这个可安装的 OpenClaw 软件包作为产品是否可用?”时,请使用 `Package Acceptance`。它不同于常规 CI:常规 CI 验证的是源代码树,而包验收验证的是一个单独的 tarball,并通过用户在安装或更新后实际会走到的同一套 Docker E2E 测试框架进行验证。 -该工作流有四个作业: +该工作流包含四个作业: -1. `resolve_package` 检出 `workflow_ref`,解析一个包候选,写入 `.artifacts/docker-e2e-package/openclaw-current.tgz`,写入 `.artifacts/docker-e2e-package/package-candidate.json`,将二者作为 `package-under-test` 产物上传,并在 GitHub 步骤摘要中输出来源、workflow ref、package ref、版本、SHA-256 和配置档。 -2. `docker_acceptance` 调用 `openclaw-live-and-e2e-checks-reusable.yml`,并传入 `ref=workflow_ref` 与 `package_artifact_name=package-under-test`。该可复用工作流会下载该产物、校验 tarball 清单、在需要时准备 package-digest Docker 镜像,并针对该包运行所选 Docker 流水线,而不是打包工作流检出内容。 -3. `package_telegram` 会按需调用 `NPM Telegram Beta E2E`。当 `telegram_mode` 不为 `none` 时它会运行;如果 Package Acceptance 已解析出一个包,它会安装同一个 `package-under-test` 产物;单独的 Telegram 分发仍可以安装已发布的 npm 规格。 -4. `summary` 会在包解析、Docker 验收或可选 Telegram 流水线失败时使整个工作流失败。 +1. `resolve_package` 会检出 `workflow_ref`,解析出一个软件包候选项,写入 `.artifacts/docker-e2e-package/openclaw-current.tgz`,写入 `.artifacts/docker-e2e-package/package-candidate.json`,将二者作为 `package-under-test` 制品上传,并在 GitHub 步骤摘要中打印来源、工作流引用、软件包引用、版本、SHA-256 和配置档。 +2. `docker_acceptance` 会调用 `openclaw-live-and-e2e-checks-reusable.yml`,并传入 `ref=workflow_ref` 和 `package_artifact_name=package-under-test`。该可复用工作流会下载该制品,验证 tarball 清单,按需准备基于软件包摘要的 Docker 镜像,并针对该软件包而不是对工作流检出内容打包后运行所选 Docker 测试路径。当某个配置档选择了多个目标 `docker_lanes` 时,该可复用工作流会只准备一次软件包和共享镜像,然后将这些测试路径展开为并行的目标 Docker 作业,并为每个作业生成唯一制品。 +3. `package_telegram` 可选地调用 `NPM Telegram Beta E2E`。当 `telegram_mode` 不为 `none` 时,它会运行;如果 `Package Acceptance` 已解析出一个软件包,它会安装同一个 `package-under-test` 制品;而独立触发的 Telegram 场景仍然可以安装已发布的 npm 规格。 +4. `summary` 会在软件包解析、Docker 验收,或可选的 Telegram 测试路径失败时使整个工作流失败。 候选来源: -- `source=npm`:仅接受 `openclaw@beta`、`openclaw@latest` 或精确的 OpenClaw 发布版本,例如 `openclaw@2026.4.27-beta.2`。用于已发布 beta/稳定版验收。 -- `source=ref`:打包一个可信的 `package_ref` 分支、标签或完整提交 SHA。解析器会获取 OpenClaw 分支/标签,验证所选提交可从仓库分支历史或发布标签到达,在分离工作树中安装依赖,并使用 `scripts/package-openclaw-for-docker.mjs` 打包。 -- `source=url`:下载 HTTPS `.tgz`;必须提供 `package_sha256`。 -- `source=artifact`:从 `artifact_run_id` 和 `artifact_name` 下载一个 `.tgz`;`package_sha256` 是可选的,但对于外部共享产物应当提供。 +- `source=npm`:只接受 `openclaw@beta`、`openclaw@latest`,或精确的 OpenClaw 发布版本,例如 `openclaw@2026.4.27-beta.2`。用于已发布 beta / stable 版本的验收。 +- `source=ref`:打包一个可信的 `package_ref` 分支、标签或完整提交 SHA。解析器会获取 OpenClaw 分支 / 标签,验证所选提交可从仓库分支历史或某个发布标签到达,在一个分离工作树中安装依赖,并使用 `scripts/package-openclaw-for-docker.mjs` 进行打包。 +- `source=url`:下载一个 HTTPS `.tgz`;必须提供 `package_sha256`。 +- `source=artifact`:从 `artifact_run_id` 和 `artifact_name` 下载一个 `.tgz`;`package_sha256` 是可选的,但对于外部共享制品,仍建议提供。 -请将 `workflow_ref` 和 `package_ref` 区分开。`workflow_ref` 是运行测试所用的可信工作流/harness 代码。`package_ref` 是在 `source=ref` 时被打包的源码提交。这样,当前测试 harness 就可以验证较旧但可信的源码提交,而无需运行旧的工作流逻辑。 +请将 `workflow_ref` 和 `package_ref` 分开理解。`workflow_ref` 是运行测试时使用的可信工作流 / 测试框架代码。`package_ref` 是在 `source=ref` 时实际被打包的源代码提交。这样,当前测试框架就可以验证较早但可信的源代码提交,而无需运行旧的工作流逻辑。 -配置档与 Docker 覆盖的对应关系: +配置档与 Docker 覆盖范围的映射如下: - `smoke`:`npm-onboard-channel-agent`、`gateway-network`、`config-reload` - `package`:`npm-onboard-channel-agent`、`doctor-switch`、`update-channel-switch`、`bundled-channel-deps-compat`、`plugins-offline`、`plugin-update` -- `product`:`package` 加上 `mcp-channels`、`cron-mcp-cleanup`、`openai-web-search-minimal`、`openwebui` +- `product`:在 `package` 基础上增加 `mcp-channels`、`cron-mcp-cleanup`、`openai-web-search-minimal`、`openwebui` - `full`:带 OpenWebUI 的完整 Docker 发布路径分块 -- `custom`:精确的 `docker_lanes`;当 `suite_profile=custom` 时为必填 +- `custom`:精确指定 `docker_lanes`;当 `suite_profile=custom` 时必须提供 -发布检查会以 `source=ref`、`package_ref=`、`workflow_ref=`、`suite_profile=custom`、`docker_lanes='bundled-channel-deps-compat plugins-offline'` 和 `telegram_mode=mock-openai` 调用 Package Acceptance。发布路径 Docker 分块会覆盖重叠的包/更新/插件流水线,而 Package Acceptance 则会针对同一个已解析包 tarball,保留产物原生的 bundled-channel 兼容性、离线插件以及 Telegram 证明。 -跨 OS 发布检查仍覆盖 OS 特定的新手引导、安装器和平台行为;而包/更新产品验证应从 Package Acceptance 开始。Windows 打包版和安装器全新安装流水线还会验证:已安装包是否可以从原始绝对 Windows 路径导入浏览器控制覆盖项。 +发布检查会以 `source=ref`、`package_ref=`、`workflow_ref=`、`suite_profile=custom`、`docker_lanes='bundled-channel-deps-compat plugins-offline'` 和 `telegram_mode=mock-openai` 来调用 Package Acceptance。发布路径中的 Docker 分块会覆盖重叠的软件包 / 更新 / 插件测试路径,而 Package Acceptance 则会针对同一个已解析的软件包 tarball,补充验证制品原生的 bundled-channel 兼容性、离线插件以及 Telegram 证明。跨操作系统的发布检查仍然覆盖特定于操作系统的新手引导、安装器和平台行为;而软件包 / 更新的产品级验证应从 Package Acceptance 开始。Windows 的打包版和安装器全新测试路径还会验证:已安装的软件包能否从原始的绝对 Windows 路径导入 browser-control override。 -Package Acceptance 对于截至 `2026.4.25`(包括 `2026.4.25-beta.*`)的已发布包,提供了一个有界的旧版兼容窗口。这里记录这些放宽规则,是为了避免它们变成永久性的静默跳过:如果 tarball 省略了已知私有 QA 条目,`dist/postinstall-inventory.json` 中的相关项可能会发出警告;如果包未暴露该标志,`doctor-switch` 可能会跳过 `gateway install --wrapper` 持久化子用例;`update-channel-switch` 可能会从 tarball 派生的伪 git 夹具中裁剪缺失的 `pnpm.patchedDependencies`,并可能记录缺失的持久化 `update.channel`;插件冒烟测试可能会读取旧版安装记录位置,或接受缺失的 marketplace 安装记录持久化;并且 `plugin-update` 可能允许配置元数据迁移,同时仍要求安装记录和不重新安装行为保持不变。`2026.4.25` 之后的包必须满足现代契约;相同条件将不再警告或跳过,而是直接失败。 +Package Acceptance 对已发布的软件包保留了一个有界的旧版兼容窗口,覆盖到 `2026.4.25`,包括 `2026.4.25-beta.*`。这些例外情况记录在这里,是为了避免它们变成永久性的静默跳过:如果 tarball 省略了这些文件,那么 `dist/postinstall-inventory.json` 中已知的私有 QA 条目可能会发出警告;如果软件包未暴露该标志,`doctor-switch` 可能会跳过 `gateway install --wrapper` 持久化子场景;`update-channel-switch` 可能会从基于 tarball 派生的伪 git 夹具中裁剪缺失的 `pnpm.patchedDependencies`,并可能记录缺失的持久化 `update.channel`;插件冒烟测试可能会读取旧版安装记录位置,或接受缺失的 marketplace 安装记录持久化;而 `plugin-update` 可能允许配置元数据迁移,但仍要求安装记录及“不重新安装”行为保持不变。`2026.4.25` 之后的软件包必须满足现代契约;相同条件将不再是警告或跳过,而会直接失败。 示例: ```bash -# 使用产品级覆盖验证当前 beta 包。 +# Validate the current beta package with product-level coverage. gh workflow run package-acceptance.yml \ --ref main \ -f workflow_ref=main \ @@ -66,7 +67,7 @@ gh workflow run package-acceptance.yml \ -f suite_profile=product \ -f telegram_mode=mock-openai -# 使用当前 harness 打包并验证一个发布分支。 +# Pack and validate a release branch with the current harness. gh workflow run package-acceptance.yml \ --ref main \ -f workflow_ref=main \ @@ -75,7 +76,7 @@ gh workflow run package-acceptance.yml \ -f suite_profile=package \ -f telegram_mode=mock-openai -# 验证一个 tarball URL。对于 source=url,SHA-256 是必填项。 +# Validate a tarball URL. SHA-256 is mandatory for source=url. gh workflow run package-acceptance.yml \ --ref main \ -f workflow_ref=main \ @@ -84,7 +85,7 @@ gh workflow run package-acceptance.yml \ -f package_sha256=<64-char-sha256> \ -f suite_profile=smoke -# 复用另一个 Actions 运行上传的 tarball。 +# Reuse a tarball uploaded by another Actions run. gh workflow run package-acceptance.yml \ --ref main \ -f workflow_ref=main \ @@ -95,17 +96,17 @@ gh workflow run package-acceptance.yml \ -f docker_lanes='install-e2e plugin-update' ``` -调试失败的包验收运行时,先查看 `resolve_package` 摘要,确认包来源、版本和 SHA-256。然后检查 `docker_acceptance` 子运行及其 Docker 产物:`.artifacts/docker-tests/**/summary.json`、`failures.json`、流水线日志、阶段耗时以及重跑命令。优先重跑失败的包配置档或精确的 Docker 流水线,而不是重跑整个发布验证。 +当你调试失败的包验收运行时,请先查看 `resolve_package` 摘要,确认软件包来源、版本和 SHA-256。然后检查 `docker_acceptance` 子运行及其 Docker 制品:`.artifacts/docker-tests/**/summary.json`、`failures.json`、测试路径日志、阶段耗时,以及重跑命令。优先重跑失败的软件包配置档或精确的 Docker 测试路径,而不是重跑完整发布验证。 -QA Lab 在主智能作用域工作流之外有专门的 CI 流水线。`Parity gate` 工作流会在匹配的 PR 变更和手动分发时运行;它会构建私有 QA 运行时,并比较模拟的 GPT-5.5 和 Opus 4.6 agentic packs。`QA-Lab - All Lanes` 工作流会在 `main` 上按夜间计划运行,也可手动分发;它会将模拟 parity gate、live Matrix 流水线,以及 live Telegram 和 Discord 流水线作为并行作业展开。live 作业使用 `qa-live-shared` 环境,而 Telegram/Discord 使用 Convex 租约。Matrix 在计划运行和发布门禁中使用 `--profile fast`,仅当检出的 CLI 支持时才额外添加 `--fail-fast`。CLI 默认值和手动工作流输入仍为 `all`;手动 `matrix_profile=all` 分发总会将完整 Matrix 覆盖分片为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作业。`OpenClaw Release Checks` 也会在发布批准前运行发布关键的 QA Lab 流水线。 +QA Lab 在主智能范围工作流之外有专门的 CI 测试路径。`Parity gate` 工作流会在匹配的 PR 变更和手动触发时运行;它会构建私有 QA 运行时,并比较 mock GPT-5.5 和 Opus 4.6 的 agentic 包。`QA-Lab - All Lanes` 工作流会在 `main` 上每晚运行,并支持手动触发;它会将 mock parity gate、实时 Matrix 测试路径,以及实时 Telegram 和 Discord 测试路径展开为并行作业。实时作业使用 `qa-live-shared` 环境,而 Telegram / Discord 使用 Convex 租约。Matrix 在定时和发布门禁中使用 `--profile fast`,并且仅在当前检出的 CLI 支持时才添加 `--fail-fast`。CLI 默认值和手动工作流输入仍然是 `all`;手动触发 `matrix_profile=all` 时,总会将完整的 Matrix 覆盖拆分为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作业。`OpenClaw Release Checks` 也会在发布批准前运行对发布至关重要的 QA Lab 测试路径。 -`Duplicate PRs After Merge` 工作流是一个手动维护者工作流,用于合并后的重复项清理。它默认以 dry-run 模式运行,只有当 `apply=true` 时才会关闭明确列出的 PR。在修改 GitHub 之前,它会验证已落地 PR 确实已合并,并确认每个重复 PR 要么共享被引用的问题,要么具有重叠的变更块。 +`Duplicate PRs After Merge` 工作流是一个供维护者在合并后清理重复 PR 的手动工作流。它默认是 dry-run,只有在 `apply=true` 时才会关闭被明确列出的 PR。在修改 GitHub 之前,它会先验证:已落地的 PR 确实已合并,并且每个重复 PR 都具有共享的引用 issue 或重叠的变更 hunk。 -`CodeQL` 工作流有意作为一个窄范围的首轮扫描器,而不是覆盖整个仓库的全面扫描。每日运行和手动运行会扫描 Actions 工作流代码,以及风险最高的 JavaScript/TypeScript 凭证、密钥、沙箱隔离、cron 和 Gateway 网关 相关区域。关键安全流水线在这些窄范围 JavaScript/TypeScript 区域上运行高精度安全查询,而独立的关键质量流水线则只运行错误严重级别的非安全查询。Swift、Android、Python、UI 和内置插件的 CodeQL 扩展,应仅在这一窄配置具有稳定运行时间和有效信号之后,再作为具有限定范围或分片的后续工作重新加入。 +`CodeQL` 工作流有意被设计为一个范围较窄的首轮扫描器,而不是对整个仓库进行全面扫描。每日运行和手动运行会扫描 Actions 工作流代码,以及风险最高的 JavaScript / TypeScript 凭证、密钥、沙箱隔离、cron 和 Gateway 网关相关区域。关键安全测试路径会对这些较窄的范围运行高精度安全查询,而独立的关键质量测试路径则仅对同样较窄的 JavaScript / TypeScript 范围运行错误级别的非安全查询。Swift、Android、Python、UI 以及内置插件的 CodeQL 扩展应仅在这个窄范围配置拥有稳定的运行时表现和信号后,再作为限定范围或分片的后续工作逐步加回。 -`Docs Agent` 工作流是一个由事件驱动的 Codex 维护流水线,用于让现有文档与最近落地的变更保持一致。它没有纯计划触发:`main` 上一次成功的、非机器人触发的 push CI 运行可以触发它,手动分发也可以直接运行它。工作流运行触发的调用会在以下情况下跳过:`main` 已继续前进,或过去一小时内已经创建了另一个未被跳过的 Docs Agent 运行。真正运行时,它会审查从上一个未跳过的 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此每小时一次的运行即可覆盖自上次文档处理以来积累的所有 main 变更。 +`Docs Agent` 工作流是一个事件驱动的 Codex 维护测试路径,用于让现有文档与最近已落地的变更保持一致。它没有单纯的定时调度:在 `main` 上成功完成的一次非机器人推送 CI 运行可以触发它,也可以通过手动触发直接运行。对于由 workflow-run 触发的调用,如果 `main` 已继续前进,或者在过去一小时内已创建过另一次未被跳过的 Docs Agent 运行,它就会跳过。当它运行时,会审查从上一次未被跳过的 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此每小时一次运行就可以覆盖自上次文档处理以来累积到 `main` 的所有变更。 -`Test Performance Agent` 工作流是一个由事件驱动的 Codex 维护流水线,用于处理慢速测试。它没有纯计划触发:`main` 上一次成功的、非机器人触发的 push CI 运行可以触发它,但如果当天 UTC 已经有另一个由 workflow-run 触发的实例运行过或正在运行,它就会跳过。手动分发会绕过这个每日活动门控。该流水线会构建一个完整测试套件的分组 Vitest 性能报告,让 Codex 仅进行小范围、保持覆盖率不变的测试性能修复,而不是进行大规模重构;然后重新运行完整测试套件报告,并拒绝会降低通过基线测试数量的更改。如果基线中存在失败测试,Codex 只能修复明显的失败;并且在提交任何内容之前,agent 运行后的完整测试套件报告必须通过。当机器人推送落地前 `main` 已前进时,该流水线会对已验证补丁执行变基,重新运行 `pnpm check:changed`,并重试推送;存在冲突的过时补丁会被跳过。它使用 GitHub 托管的 Ubuntu,这样 Codex action 就可以与 docs agent 保持相同的 drop-sudo 安全姿态。 +`Test Performance Agent` 工作流是一个面向慢测试的事件驱动 Codex 维护测试路径。它没有单纯的定时调度:在 `main` 上成功完成的一次非机器人推送 CI 运行可以触发它,但如果当天 UTC 已经有另一次由 workflow-run 触发的调用正在运行或已经运行过,它就会跳过。手动触发会绕过这个按天限制的活动门禁。该测试路径会构建一份完整测试套件的分组 Vitest 性能报告,让 Codex 仅进行小范围、保持覆盖率不变的测试性能修复,而不是做大规模重构;然后重新运行完整测试套件报告,并拒绝任何导致通过基线测试数量下降的变更。如果基线中存在失败测试,Codex 只能修复明显的失败,并且在提交任何内容之前,智能体处理后的完整测试套件报告必须通过。当 `main` 在机器人推送落地前继续前进时,该测试路径会对已验证的补丁执行 rebase,重新运行 `pnpm check:changed`,然后重试推送;存在冲突的过时补丁会被跳过。它使用 GitHub 托管的 Ubuntu,这样 Codex action 就能与 docs agent 保持相同的 drop-sudo 安全策略。 ```bash gh workflow run duplicate-after-merge.yml \ @@ -116,31 +117,31 @@ gh workflow run duplicate-after-merge.yml \ ## 作业概览 -| 作业 | 用途 | 何时运行 | -| -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | -| `preflight` | 检测是否仅有文档变更、变更作用域、变更扩展,并构建 CI 清单 | 始终在非草稿 push 和 PR 上运行 | -| `security-scm-fast` | 通过 `zizmor` 进行私钥检测和工作流审计 | 始终在非草稿 push 和 PR 上运行 | -| `security-dependency-audit` | 针对 npm 漏洞进行无依赖的生产 lockfile 审计 | 始终在非草稿 push 和 PR 上运行 | -| `security-fast` | 快速安全作业所需的聚合作业 | 始终在非草稿 push 和 PR 上运行 | -| `build-artifacts` | 构建 `dist/`、Control UI、已构建产物检查,以及可复用的下游产物 | 与 Node 相关的变更 | -| `checks-fast-core` | 快速 Linux 正确性流水线,例如 bundled/plugin-contract/protocol 检查 | 与 Node 相关的变更 | -| `checks-fast-contracts-channels` | 分片的渠道契约检查,带有稳定的聚合检查结果 | 与 Node 相关的变更 | -| `checks-node-extensions` | 覆盖整个扩展套件的完整内置插件测试分片 | 与 Node 相关的变更 | -| `checks-node-core-test` | Core Node 测试分片,不包括渠道、内置、契约和扩展流水线 | 与 Node 相关的变更 | -| `check` | 分片后的主要本地门禁等效项:生产类型、lint、守卫、测试类型和严格冒烟测试 | 与 Node 相关的变更 | +| 作业 | 用途 | 运行时机 | +| --- | --- | --- | +| `preflight` | 检测仅文档变更、变更范围、已变更扩展,并构建 CI 清单 | 所有非草稿推送和 PR | +| `security-scm-fast` | 通过 `zizmor` 检测私钥和审计工作流 | 所有非草稿推送和 PR | +| `security-dependency-audit` | 针对 npm 公告执行无依赖的生产 lockfile 审计 | 所有非草稿推送和 PR | +| `security-fast` | 快速安全作业的必需聚合作业 | 所有非草稿推送和 PR | +| `build-artifacts` | 构建 `dist/`、Control UI、已构建制品检查,以及可复用的下游制品 | 与 Node 相关的变更 | +| `checks-fast-core` | 快速 Linux 正确性测试路径,例如 bundled / 插件契约 / 协议检查 | 与 Node 相关的变更 | +| `checks-fast-contracts-channels` | 分片的渠道契约检查,并提供稳定的聚合检查结果 | 与 Node 相关的变更 | +| `checks-node-extensions` | 针对整个扩展套件的完整内置插件测试分片 | 与 Node 相关的变更 | +| `checks-node-core-test` | 核心 Node 测试分片,不包括渠道、内置、契约和扩展测试路径 | 与 Node 相关的变更 | +| `check` | 分片后的主本地门禁等效项:生产类型、lint、守卫、测试类型和严格 smoke | 与 Node 相关的变更 | | `check-additional` | 架构、边界、扩展表面守卫、包边界和 gateway-watch 分片 | 与 Node 相关的变更 | | `build-smoke` | 已构建 CLI 冒烟测试和启动内存冒烟测试 | 与 Node 相关的变更 | -| `checks` | 已构建产物渠道测试的验证器 | 与 Node 相关的变更 | -| `checks-node-compat-node22` | Node 22 兼容性构建和冒烟流水线 | 用于发布的手动 CI 分发 | -| `check-docs` | 文档格式、lint 和失效链接检查 | 文档发生变更 | -| `skills-python` | Python 支持的 Skills 的 Ruff + pytest | 与 Python Skills 相关的变更 | -| `checks-windows` | Windows 特定的进程/路径测试,以及共享运行时导入说明符回归测试 | 与 Windows 相关的变更 | -| `macos-node` | 使用共享已构建产物的 macOS TypeScript 测试流水线 | 与 macOS 相关的变更 | +| `checks` | 已构建制品渠道测试的验证器 | 与 Node 相关的变更 | +| `checks-node-compat-node22` | Node 22 兼容性构建和 smoke 测试路径 | 为发布而进行的手动 CI 触发 | +| `check-docs` | 文档格式、lint 和损坏链接检查 | 文档发生变更时 | +| `skills-python` | 面向 Python 支持的 Skills 的 Ruff + pytest | 与 Python Skills 相关的变更 | +| `checks-windows` | Windows 特定进程 / 路径测试,以及共享运行时导入说明符回归测试 | 与 Windows 相关的变更 | +| `macos-node` | 使用共享已构建制品的 macOS TypeScript 测试路径 | 与 macOS 相关的变更 | | `macos-swift` | macOS 应用的 Swift lint、构建和测试 | 与 macOS 相关的变更 | -| `android` | 两个 flavor 的 Android 单元测试外加一个 debug APK 构建 | 与 Android 相关的变更 | -| `test-performance-agent` | 在可信活动之后每日执行的 Codex 慢测试优化 | 主 CI 成功后或手动分发 | +| `android` | 两个 flavor 的 Android 单元测试,以及一次 debug APK 构建 | 与 Android 相关的变更 | +| `test-performance-agent` | 在可信活动之后,按天运行的 Codex 慢测试优化 | `main` CI 成功后或手动触发 | -手动 CI 分发运行与常规 CI 相同的作业图,但会强制开启所有作用域流水线:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟测试、文档检查、Python Skills、Windows、macOS、Android,以及 Control UI i18n。手动运行使用唯一的并发组,因此发布候选的完整套件不会因同一 ref 上的另一个 push 或 PR 运行而被取消。可选的 `target_ref` 输入允许可信调用方针对某个分支、标签或完整提交 SHA 运行该作业图,同时使用所选分发 ref 中的工作流文件。 +手动触发的 CI 会运行与常规 CI 相同的作业图,但会强制开启所有按范围控制的测试路径:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟、文档检查、Python Skills、Windows、macOS、Android,以及 Control UI i18n。手动运行使用唯一的并发组,因此某个发布候选版本的完整测试套件不会因为同一 ref 上的另一条推送或 PR 运行而被取消。可选的 `target_ref` 输入允许可信调用方在使用所选 dispatch ref 的工作流文件的同时,针对某个分支、标签或完整提交 SHA 运行该作业图。 ```bash gh workflow run ci.yml --ref release/YYYY.M.D @@ -150,38 +151,41 @@ gh workflow run full-release-validation.yml --ref main -f ref= ## 快速失败顺序 -作业按顺序排列,以便廉价检查先失败,再决定是否运行昂贵作业: +作业的排列顺序经过设计,以便让廉价检查先失败,再决定是否运行昂贵作业: -1. `preflight` 决定到底有哪些流水线存在。`docs-scope` 和 `changed-scope` 逻辑是该作业内的步骤,不是独立作业。 -2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,而无需等待更重的产物和平台矩阵作业。 -3. `build-artifacts` 会与快速 Linux 流水线并行,以便下游消费者在共享构建就绪后立即开始。 -4. 更重的平台和运行时流水线随后展开:`checks-fast-core`、`checks-fast-contracts-channels`、`checks-node-extensions`、`checks-node-core-test`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 和 `android`。 +1. `preflight` 决定到底存在哪些测试路径。`docs-scope` 和 `changed-scope` 逻辑是这个作业中的步骤,不是独立作业。 +2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,而不必等待更重的制品和平台矩阵作业。 +3. `build-artifacts` 会与快速 Linux 测试路径并行运行,这样下游消费者就可以在共享构建准备好后立刻开始。 +4. 更重的平台和运行时测试路径会在之后展开:`checks-fast-core`、`checks-fast-contracts-channels`、`checks-node-extensions`、`checks-node-core-test`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 和 `android`。 -作用域逻辑位于 `scripts/ci-changed-scope.mjs`,并由 `src/scripts/ci-changed-scope.test.ts` 中的单元测试覆盖。手动分发会跳过 changed-scope 检测,并让 preflight 清单表现得像是每个受作用域控制的区域都发生了变更。 -CI 工作流编辑会验证 Node CI 作业图和工作流 lint,但不会仅因这些编辑就强制运行 Windows、Android 或 macOS 原生构建;这些平台流水线仍然只对平台源码变更生效。 -仅涉及 CI 路由的编辑、选定的廉价 core-test fixture 编辑,以及狭义的插件契约辅助函数/测试路由编辑,会走一个快速的仅 Node 清单路径:preflight、安全检查,以及单个 `checks-fast-core` 任务。该路径会跳过构建产物、Node 22 兼容性、渠道契约、完整 core 分片、内置插件分片和附加守卫矩阵,前提是变更文件仅限于该快速任务可直接覆盖的路由或辅助表面。 -Windows Node 检查仅作用于 Windows 特定的进程/路径包装器、npm/pnpm/UI 运行器辅助函数、包管理器配置,以及执行该流水线的 CI 工作流表面;不相关的源码、插件、安装冒烟测试和纯测试变更会保留在 Linux Node 流水线上,这样就不会为正常测试分片已覆盖的内容占用一个 16 vCPU 的 Windows worker。 -独立的 `install-smoke` 工作流通过自己的 `preflight` 作业复用同一个作用域脚本。它将冒烟覆盖拆分为 `run_fast_install_smoke` 和 `run_full_install_smoke`。对于拉取请求,Docker/包表面、内置插件包/manifest 变更,以及 Docker 冒烟作业覆盖到的 core 插件/渠道/Gateway 网关/插件 SDK 表面,会运行快速路径。仅源码的内置插件变更、纯测试编辑和纯文档编辑不会占用 Docker worker。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行 agents delete shared-workspace CLI 冒烟测试,运行容器化 gateway-network e2e,验证一个内置扩展 build arg,并在 240 秒的总命令超时限制下运行有界的内置插件 Docker 配置,同时每个场景的 Docker run 也分别有限制。完整路径会保留 QR 包安装以及安装器 Docker/更新覆盖,用于夜间计划运行、手动分发、workflow-call 发布检查,以及真正触及安装器/包/Docker 表面的拉取请求。`main` 推送(包括 merge commit)不会强制走完整路径;当 changed-scope 逻辑在 push 上本应请求完整覆盖时,该工作流仍然只保留快速 Docker 冒烟测试,而将完整安装冒烟测试留给夜间运行或发布验证。较慢的 Bun 全局安装 image-provider 冒烟测试由单独的 `run_bun_global_install_smoke` 控制;它会在夜间计划和发布检查工作流中运行,手动 `install-smoke` 分发也可以选择启用它,但拉取请求和 `main` 推送不会运行它。QR 和安装器 Docker 测试保留它们各自以安装为重点的 Dockerfile。本地 `test:docker:all` 会预构建一个共享的 live-test 镜像,将 OpenClaw 一次性打包为 npm tarball,并构建两个共享的 `scripts/e2e/Dockerfile` 镜像:一个是用于安装器/更新/插件依赖流水线的裸 Node/Git 运行器,另一个是功能型镜像,会将同一个 tarball 安装到 `/app` 中,供常规功能流水线使用。Docker 流水线定义位于 `scripts/lib/docker-e2e-scenarios.mjs`,规划逻辑位于 `scripts/lib/docker-e2e-plan.mjs`,而运行器仅执行所选计划。调度器会通过 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 和 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 为每个流水线选择镜像,然后以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行各流水线;主池默认槽位数为 10,可通过 `OPENCLAW_DOCKER_ALL_PARALLELISM` 调整;provider 敏感的尾池默认槽位数也是 10,可通过 `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` 调整。较重流水线的默认上限分别为 `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` 和 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`,以避免 npm 安装和多服务流水线让 Docker 过度超配,同时较轻的流水线仍可填满可用槽位。即使单个流水线重于当前有效上限,只要池为空,它仍可启动,然后独占运行直到释放容量。默认情况下,各流水线启动会错开 2 秒,以避免本地 Docker daemon 出现 create 风暴;可通过 `OPENCLAW_DOCKER_ALL_START_STAGGER_MS=0` 或其他毫秒值覆盖。本地聚合运行在预检查阶段会检查 Docker、移除过期的 OpenClaw E2E 容器、输出活动流水线状态、持久化流水线耗时以便最长优先排序,并支持通过 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 检查调度器。默认情况下,它会在首次失败后停止调度新的池化流水线;每个流水线都有一个 120 分钟的兜底超时,可通过 `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` 覆盖;部分选定的 live/tail 流水线使用更严格的单流水线上限。`OPENCLAW_DOCKER_ALL_LANES=` 会运行精确的调度器流水线,包括诸如 `install-e2e` 这类仅发布时使用的流水线,以及像 `bundled-channel-update-acpx` 这样拆分的内置更新流水线,同时跳过清理冒烟测试,以便智能体复现某一条失败流水线。可复用的 live/E2E 工作流会先询问 `scripts/test-docker-all.mjs --plan-json`:需要哪个包、哪种镜像类型、哪个 live 镜像、哪条流水线以及哪类凭证覆盖,然后由 `scripts/docker-e2e.mjs` 将该计划转换为 GitHub 输出和摘要。它会通过 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw,或下载当前运行的包产物,或从 `package_artifact_run_id` 下载包产物;验证 tarball 清单;当计划需要安装包的流水线时,通过 Blacksmith 的 Docker layer cache 构建并推送带 package-digest 标签的 bare/functional GHCR Docker E2E 镜像;并在可用时复用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 输入或现有的 package-digest 镜像,而不是重新构建。`Package Acceptance` 工作流是高级别的包门禁:它会从 npm、可信的 `package_ref`、带 SHA-256 的 HTTPS tarball,或先前工作流的产物中解析一个候选包,然后将这个单一的 `package-under-test` 产物传入可复用的 Docker E2E 工作流。它将 `workflow_ref` 与 `package_ref` 分离,这样当前的验收逻辑就可以在不检出旧工作流代码的情况下验证较旧但可信的提交。发布检查会针对目标 ref 运行自定义的 Package Acceptance 增量:内置渠道兼容性、离线插件 fixtures,以及基于已解析 tarball 的 Telegram 包 QA。发布路径 Docker 套件会以较小的分块作业运行,并使用 `OPENCLAW_SKIP_DOCKER_BUILD=1`,这样每个分块只会拉取所需的镜像类型,并通过同一个加权调度器执行多条流水线(`OPENCLAW_DOCKER_ALL_PROFILE=release-path`、`OPENCLAW_DOCKER_ALL_CHUNK=core|package-update-openai|package-update-anthropic|package-update-core|plugins-runtime-core|plugins-runtime-install-a|plugins-runtime-install-b|bundled-channels`)。当完整发布路径覆盖请求 OpenWebUI 时,它会并入 `plugins-runtime-core`,仅在只调度 OpenWebUI 的情况下保留单独的 `openwebui` 分块。旧的聚合分块名称 `package-update`、`plugins-runtime` 和 `plugins-integrations` 仍可用于手动重跑,但发布工作流使用拆分后的分块,因此安装器 E2E 和内置插件安装/卸载全量扫描不会主导关键路径。`install-e2e` 流水线别名仍然是两个 provider 安装器流水线的聚合手动重跑别名。`bundled-channels` 分块运行的是拆分后的 `bundled-channel-*` 和 `bundled-channel-update-*` 流水线,而不是串行的一体化 `bundled-channel-deps` 流水线。每个分块都会上传 `.artifacts/docker-tests/`,其中包含流水线日志、耗时、`summary.json`、`failures.json`、阶段耗时、调度器计划 JSON、慢流水线表,以及每条流水线的重跑命令。工作流的 `docker_lanes` 输入会针对已准备好的镜像运行选定流水线,而不是运行分块作业;这样可以将失败流水线的调试限制在一个定向 Docker 作业内,并为该次运行准备、下载或复用包产物;如果选定的流水线是 live Docker 流水线,该定向作业会在本地为该次重跑构建 live-test 镜像。生成的每条流水线 GitHub 重跑命令会在这些值存在时包含 `package_artifact_run_id`、`package_artifact_name` 以及已准备镜像输入,因此失败流水线可以复用失败运行中的同一个包和镜像。使用 `pnpm test:docker:rerun ` 可从 GitHub 某次运行下载 Docker 产物,并打印组合式/逐流水线的定向重跑命令;使用 `pnpm test:docker:timings ` 可生成慢流水线和阶段关键路径摘要。计划中的 live/E2E 工作流每天运行完整的发布路径 Docker 套件。内置更新矩阵按更新目标拆分,以便重复的 npm update 和 doctor 修复过程能够与其他内置检查一起分片运行。 +范围逻辑位于 `scripts/ci-changed-scope.mjs`,并由 `src/scripts/ci-changed-scope.test.ts` 中的单元测试覆盖。 +手动触发会跳过变更范围检测,并让预检清单表现得像所有按范围控制的区域都发生了变更。 +CI 工作流编辑会验证 Node CI 作业图以及工作流 lint,但不会仅因这些改动就强制运行 Windows、Android 或 macOS 原生构建;这些平台测试路径仍然只对平台源码变更生效。 +仅涉及 CI 路由的编辑、选定的廉价核心测试夹具编辑,以及狭窄的插件契约辅助函数 / 测试路由编辑,会使用快速的仅 Node 清单路径:preflight、安全检查,以及单个 `checks-fast-core` 任务。当变更文件仅限于快速任务可直接覆盖的路由或辅助层时,这条路径会避免构建制品、Node 22 兼容性、渠道契约、完整核心分片、内置插件分片以及额外守卫矩阵。 +Windows Node 检查的范围仅限于 Windows 特定的进程 / 路径封装、npm / pnpm / UI 运行器辅助函数、包管理器配置,以及执行该测试路径的 CI 工作流相关区域;无关的源码、插件、install-smoke 和仅测试改动会继续留在 Linux Node 测试路径上,这样就不会为了常规测试分片已经覆盖到的内容而占用 16 vCPU 的 Windows worker。 +独立的 `install-smoke` 工作流会通过自己的 `preflight` 作业复用同一个范围脚本。它将 smoke 覆盖拆分为 `run_fast_install_smoke` 和 `run_full_install_smoke`。对于拉取请求,Docker / 软件包相关区域、内置插件软件包 / manifest 改动,以及 Docker smoke 作业会覆盖到的核心插件 / 渠道 / Gateway 网关 / 插件 SDK 区域,会运行快速路径。仅源码的内置插件改动、仅测试改动和仅文档改动不会占用 Docker worker。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行 agents delete shared-workspace CLI smoke,运行容器化的 gateway-network e2e,验证一个内置扩展 build arg,并在总计 240 秒的命令超时上限内运行受限的内置插件 Docker 配置档,同时每个场景的 Docker run 也分别有单独上限。完整路径则保留 QR 软件包安装和安装器 Docker / 更新覆盖,用于夜间定时运行、手动触发、workflow-call 发布检查,以及真正触及安装器 / 软件包 / Docker 相关区域的拉取请求。推送到 `main`,包括合并提交,不会强制完整路径;当变更范围逻辑在一次推送中本会请求完整覆盖时,工作流仍只保留快速 Docker smoke,把完整 install smoke 留给夜间任务或发布验证。较慢的 Bun 全局安装 image-provider smoke 由 `run_bun_global_install_smoke` 单独控制;它会在夜间定时任务和发布检查工作流中运行,手动触发 `install-smoke` 时也可以选择开启,但拉取请求和推送到 `main` 时不会运行它。QR 和安装器 Docker 测试继续使用各自专门的安装类 Dockerfile。本地 `test:docker:all` 会预构建一个共享的实时测试镜像,将 OpenClaw 仅打包一次为 npm tarball,并构建两个共享的 `scripts/e2e/Dockerfile` 镜像:一个是用于安装器 / 更新 / 插件依赖测试路径的裸 Node / Git 运行器,另一个是功能镜像,会把同一个 tarball 安装到 `/app` 中,供常规功能测试路径使用。Docker 测试路径定义位于 `scripts/lib/docker-e2e-scenarios.mjs`,规划器逻辑位于 `scripts/lib/docker-e2e-plan.mjs`,而运行器只执行所选计划。调度器会使用 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 和 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 为每个测试路径选择镜像,然后以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行这些测试路径;主池默认并发槽位数为 10,可通过 `OPENCLAW_DOCKER_ALL_PARALLELISM` 调整;对 provider 敏感的尾池默认并发槽位数也为 10,可通过 `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` 调整。重型测试路径上限默认是 `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` 和 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`,这样 npm install 和多服务测试路径就不会让 Docker 过度超配,同时较轻的测试路径仍可填满可用槽位。即便某个单独测试路径比有效上限更重,它也仍然可以从空池启动,只是会独占运行,直到释放容量。测试路径默认以 2 秒间隔错峰启动,以避免本地 Docker 守护进程在创建容器时出现风暴;可以通过 `OPENCLAW_DOCKER_ALL_START_STAGGER_MS=0` 或其他毫秒值覆盖。本地聚合运行会先对 Docker 执行预检,移除陈旧的 OpenClaw E2E 容器,输出活动测试路径状态,持久化测试路径耗时以支持“最长优先”的排序,并支持 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 进行调度器检查。默认情况下,它会在首次失败后停止调度新的池化测试路径;每个测试路径有 120 分钟的兜底超时,可通过 `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` 覆盖;选定的 live / tail 测试路径使用更严格的单路径上限。`OPENCLAW_DOCKER_ALL_LANES=` 会运行精确的调度器测试路径,包括仅发布时使用的测试路径,例如 `install-e2e`,以及拆分后的内置更新测试路径,例如 `bundled-channel-update-acpx`,同时跳过 cleanup smoke,便于智能体复现单个失败测试路径。可复用的实时 / E2E 工作流会先调用 `scripts/test-docker-all.mjs --plan-json`,询问需要哪种软件包、镜像类型、实时镜像、测试路径以及凭证覆盖,然后由 `scripts/docker-e2e.mjs` 将该计划转换为 GitHub outputs 和摘要。它可以通过 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw,下载当前运行的软件包制品,或从 `package_artifact_run_id` 下载软件包制品;验证 tarball 清单;当计划需要已安装软件包的测试路径时,通过 Blacksmith 的 Docker 层缓存构建并推送基于软件包摘要标签的 bare / functional GHCR Docker E2E 镜像;并在已有 `docker_e2e_bare_image` / `docker_e2e_functional_image` 输入或现成的软件包摘要镜像可用时直接复用,而不是重新构建。`Package Acceptance` 工作流是高级别的软件包门禁:它从 npm、可信的 `package_ref`、带 SHA-256 的 HTTPS tarball,或先前工作流制品中解析出一个候选项,然后将这个单一的 `package-under-test` 制品传递给可复用的 Docker E2E 工作流。它会将 `workflow_ref` 与 `package_ref` 分开,以便当前的验收逻辑能够验证较旧但可信的提交,而无需检出旧的工作流代码。发布检查会针对目标 ref 运行自定义的 Package Acceptance 差异集:针对已解析 tarball 的 bundled-channel 兼容性、离线插件夹具以及 Telegram 软件包 QA。发布路径 Docker 套件会以较小的分块作业运行,并设置 `OPENCLAW_SKIP_DOCKER_BUILD=1`,这样每个分块只会拉取自己需要的镜像类型,并通过同一个加权调度器执行多个测试路径(`OPENCLAW_DOCKER_ALL_PROFILE=release-path`、`OPENCLAW_DOCKER_ALL_CHUNK=core|package-update-openai|package-update-anthropic|package-update-core|plugins-runtime-core|plugins-runtime-install-a|plugins-runtime-install-b|bundled-channels`)。当完整发布路径覆盖请求 OpenWebUI 时,它会被并入 `plugins-runtime-core`;只有在仅针对 OpenWebUI 的触发场景中,才保留独立的 `openwebui` 分块。旧的聚合分块名称 `package-update`、`plugins-runtime` 和 `plugins-integrations` 仍然可以用于手动重跑,但发布工作流使用拆分后的分块,这样安装器 E2E 以及内置插件安装 / 卸载全量扫描就不会主导关键路径。`install-e2e` 测试路径别名仍然是两个 provider 安装器测试路径的聚合手动重跑别名。`bundled-channels` 分块运行的是拆分后的 `bundled-channel-*` 和 `bundled-channel-update-*` 测试路径,而不是串行的一体化 `bundled-channel-deps` 测试路径。每个分块都会上传 `.artifacts/docker-tests/`,其中包含测试路径日志、耗时、`summary.json`、`failures.json`、阶段耗时、调度器计划 JSON、慢路径表,以及每个测试路径的重跑命令。工作流的 `docker_lanes` 输入会针对已准备好的镜像运行所选测试路径,而不是运行整个分块作业,这样失败测试路径的调试就可以限制在单个目标 Docker 作业内,并为该次运行准备、下载或复用软件包制品;如果所选测试路径属于实时 Docker 测试路径,那么目标作业会为这次重跑在本地构建实时测试镜像。生成的每测试路径 GitHub 重跑命令会在相关值存在时包含 `package_artifact_run_id`、`package_artifact_name` 以及已准备好的镜像输入,这样失败测试路径就能复用失败运行中的完全相同的软件包和镜像。使用 `pnpm test:docker:rerun ` 可以从某个 GitHub 运行下载 Docker 制品,并输出组合的 / 每测试路径的目标重跑命令;使用 `pnpm test:docker:timings ` 可以查看慢测试路径和阶段关键路径摘要。定时的实时 / E2E 工作流每天都会运行完整的发布路径 Docker 套件。内置更新矩阵会按更新目标拆分,以便重复的 npm update 和 doctor 修复轮次能够与其他内置检查并行分片运行。 -本地 changed-lane 逻辑位于 `scripts/changed-lanes.mjs`,由 `scripts/check-changed.mjs` 执行。该本地检查门禁在架构边界方面比广义的 CI 平台作用域更严格:core 生产变更会运行 core 生产和 core 测试 typecheck,以及 core lint/guards;core 纯测试变更只运行 core 测试 typecheck 和 core lint;扩展生产变更会运行扩展生产和扩展测试 typecheck,以及扩展 lint;扩展纯测试变更只运行扩展测试 typecheck 和扩展 lint。公开的插件 SDK 或插件契约变更会扩展到扩展 typecheck,因为扩展依赖这些 core 契约,但 Vitest 扩展全量扫描属于显式测试工作。仅发布元数据的版本号提升会运行定向的版本/配置/根依赖检查。未知的根目录/配置变更会以安全优先方式退回到所有检查流水线。 +当前的发布 Docker 分块包括 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-core`、`plugins-runtime-install-a`、`plugins-runtime-install-b`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`。聚合的 `bundled-channels` 分块仍可用于手动一次性重跑,但发布工作流使用的是拆分后的分块,这样渠道 smoke、更新目标以及设置 / 运行时契约检查就可以并行运行。目标 `docker_lanes` 触发也会在一次共享的软件包 / 镜像准备步骤之后,将多个所选测试路径拆分为并行作业;而 bundled-channel 更新测试路径会在 npm 网络瞬时故障时重试一次。 -手动 CI 分发会将 `checks-node-compat-node22` 作为发布候选兼容性覆盖来运行。常规拉取请求和 `main` 推送会跳过该流水线,并让矩阵聚焦于 Node 24 测试/渠道流水线。 +本地 changed-lane 逻辑位于 `scripts/changed-lanes.mjs`,并由 `scripts/check-changed.mjs` 执行。这个本地检查门禁在架构边界方面比广义的 CI 平台范围更严格:核心生产改动会运行核心生产和核心测试 typecheck,再加上核心 lint / guards;核心仅测试改动只会运行核心测试 typecheck 加核心 lint;扩展生产改动会运行扩展生产和扩展测试 typecheck,再加上扩展 lint;扩展仅测试改动只会运行扩展测试 typecheck 加扩展 lint。公开的插件 SDK 或插件契约变更会扩展到扩展 typecheck,因为扩展依赖这些核心契约,但 Vitest 扩展全量扫描仍属于显式测试工作。仅发布元数据的版本号提升会运行有针对性的版本 / 配置 / 根依赖检查。未知的根目录 / 配置改动会以安全优先方式退回到全部检查测试路径。 -最慢的 Node 测试族已被拆分或重新平衡,因此每个作业都能保持较小规模,同时避免过度预留 runner:渠道契约以三个加权分片运行,内置插件测试在六个扩展 worker 之间平衡分配,小型 core 单元流水线成对组合,自动回复以四个平衡 worker 运行,并将 reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片,而 agentic Gateway 网关/插件配置则分散到现有的仅源码 agentic Node 作业中执行,而不是等待已构建产物。宽范围的 browser、QA、media 以及杂项插件测试使用各自专用的 Vitest 配置,而不是共享的插件兜底配置。扩展分片作业一次最多运行两个插件配置组,每组使用一个 Vitest worker,并配备更大的 Node 堆,以避免导入密集型的插件批次产生额外的 CI 作业。宽范围的 agents 流水线使用共享的 Vitest 文件级并行调度器,因为它主要受导入/调度支配,而不是由某一个慢测试文件主导。`runtime-config` 与 infra core-runtime 分片一起运行,以避免共享运行时分片成为尾部瓶颈。include-pattern 分片会使用 CI 分片名记录耗时条目,因此 `.artifacts/vitest-shard-timings.json` 可以区分整个配置与某个过滤分片。`check-additional` 将 package-boundary 的 compile/canary 工作保持在一起,并将运行时拓扑架构与 gateway watch 覆盖拆开;boundary guard 分片会在一个作业内并发运行其较小且相互独立的守卫。Gateway watch、渠道测试以及 core support-boundary 分片会在 `dist/` 和 `dist-runtime/` 已经构建完成之后,在 `build-artifacts` 内并发运行;这样既保留了它们原有的检查名称作为轻量验证器作业,又避免了额外占用两个 Blacksmith worker 和第二条产物消费者队列。 +手动触发的 CI 会运行 `checks-node-compat-node22`,作为发布候选版本的兼容性覆盖。常规拉取请求和推送到 `main` 会跳过这条测试路径,并让矩阵聚焦在 Node 24 的测试 / 渠道测试路径上。 -Android CI 会运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play debug APK。第三方 flavor 没有单独的源码集或 manifest;它的单元测试流水线仍会使用 SMS/通话记录 BuildConfig 标志编译该 flavor,同时避免在每次与 Android 相关的 push 上重复执行一次 debug APK 打包作业。 +最慢的 Node 测试家族会被拆分或做负载均衡,以便每个作业都保持较小规模,同时避免过度预留运行器:渠道契约以 3 个加权分片运行,内置插件测试在 6 个扩展 worker 之间做均衡,小型核心单元测试路径会成对组合,auto-reply 以 4 个平衡 worker 运行,并将 reply 子树拆分为 agent-runner、dispatch 以及 commands / state-routing 分片,而 agentic Gateway 网关 / 插件配置则分散到现有的仅源码 agentic Node 作业中,而不是等待已构建制品。大范围的浏览器、QA、媒体以及杂项插件测试使用各自专用的 Vitest 配置,而不是共享的插件兜底配置。扩展分片作业一次最多运行两个插件配置组,每组使用一个 Vitest worker,并分配更大的 Node 堆,这样导入密集型插件批次就不会制造额外的 CI 作业。广泛的 agents 测试路径使用共享的 Vitest 文件级并行调度器,因为它的瓶颈在于导入 / 调度,而不是某一个单独的慢测试文件。`runtime-config` 与 infra core-runtime 分片一起运行,以避免共享运行时分片独占尾部耗时。基于 include-pattern 的分片会使用 CI 分片名称记录耗时条目,因此 `.artifacts/vitest-shard-timings.json` 可以区分整个配置与经过过滤的分片。`check-additional` 会将 package-boundary compile / canary 工作保留在一起,并将运行时拓扑架构与 gateway watch 覆盖分开;boundary guard 分片会在一个作业内并发运行其小型独立守卫。Gateway watch、渠道测试以及核心 support-boundary 分片会在 `dist/` 和 `dist-runtime/` 已构建完成后,在 `build-artifacts` 内并发运行,保留它们原有的检查名称作为轻量验证器作业,同时避免额外占用两个 Blacksmith worker,以及避免第二个制品消费者队列。 -当同一 PR 或 `main` ref 上有新的 push 到达时,GitHub 可能会将已被替代的作业标记为 `cancelled`。除非同一 ref 的最新运行也在失败,否则应将其视为 CI 噪声。聚合分片检查使用 `!cancelled() && always()`,因此它们仍会报告正常的分片失败,但在整个工作流已经被替代后不会继续排队。 +Android CI 会同时运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play debug APK。第三方 flavor 没有单独的 source set 或 manifest;它的单元测试路径仍会使用 SMS / call-log 的 BuildConfig 标志编译该 flavor,同时避免在每次与 Android 相关的推送中重复执行一个 debug APK 打包作业。 -自动 CI 并发键带有版本号(`CI-v7-*`),这样 GitHub 端旧队列组中的僵尸任务就不会无限期阻塞较新的 main 运行。手动完整套件运行使用 `CI-manual-v1-*`,并且不会取消进行中的运行。 +当同一个 PR 或 `main` ref 上有新的推送到达时,GitHub 可能会将被替代的作业标记为 `cancelled`。除非同一 ref 上最新的一次运行也失败了,否则请将这视为 CI 噪声。聚合分片检查使用 `!cancelled() && always()`,因此它们仍会正常报告分片失败,但在整个工作流已经被替代后不会继续排队。 -## Runner +自动 CI 并发键带有版本号(`CI-v7-*`),这样 GitHub 端旧队列组中的僵尸任务就不会无限期阻塞新的 main 运行。手动完整套件运行使用 `CI-manual-v1-*`,并且不会取消正在进行中的运行。 -| Runner | 作业 | -| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `ubuntu-24.04` | `preflight`、快速安全作业及其聚合作业(`security-scm-fast`、`security-dependency-audit`、`security-fast`)、快速 protocol/contract/bundled 检查、分片的渠道契约检查、除 lint 外的 `check` 分片、`check-additional` 分片及聚合作业、Node 测试聚合验证器、文档检查、Python Skills、workflow-sanity、labeler、auto-response;install-smoke preflight 也使用 GitHub 托管的 Ubuntu,这样 Blacksmith 矩阵可以更早开始排队 | +## 运行器 + +| 运行器 | 作业 | +| --- | --- | +| `ubuntu-24.04` | `preflight`、快速安全作业及其聚合项(`security-scm-fast`、`security-dependency-audit`、`security-fast`)、快速协议 / 契约 / 内置检查、分片的渠道契约检查、除 lint 之外的 `check` 分片、`check-additional` 分片及其聚合项、Node 测试聚合验证器、文档检查、Python Skills、workflow-sanity、labeler、auto-response;install-smoke preflight 也使用 GitHub 托管的 Ubuntu,这样 Blacksmith 矩阵可以更早进入排队 | | `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`、build-smoke、Linux Node 测试分片、内置插件测试分片、`android` | -| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`,它仍然对 CPU 足够敏感,以至于 8 vCPU 的成本高于节省;install-smoke Docker 构建也是如此,因为 32 vCPU 的排队时间成本高于收益 | +| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`,它对 CPU 仍然足够敏感,以至于 8 vCPU 反而得不偿失;install-smoke Docker 构建也是如此,因为 32 vCPU 的排队时间成本高于其收益 | | `blacksmith-16vcpu-windows-2025` | `checks-windows` | | `blacksmith-6vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-node`;fork 会回退到 `macos-latest` | | `blacksmith-12vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-swift`;fork 会回退到 `macos-latest` | @@ -189,11 +193,11 @@ Android CI 会运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest` ## 本地等效命令 ```bash -pnpm changed:lanes # 检查 origin/main...HEAD 的本地 changed-lane 分类器 -pnpm check:changed # 智能本地检查门禁:按边界流水线运行 changed typecheck/lint/guards +pnpm changed:lanes # 检查针对 origin/main...HEAD 的本地 changed-lane 分类器 +pnpm check:changed # 智能本地检查门禁:按边界测试路径运行变更后的 typecheck / lint / guards pnpm check # 快速本地门禁:生产 tsgo + 分片 lint + 并行快速 guards pnpm check:test-types -pnpm check:timed # 相同门禁,但附带各阶段耗时 +pnpm check:timed # 与上相同的门禁,但带每个阶段的耗时 pnpm build:strict-smoke pnpm check:architecture pnpm test:gateway:watch-regression @@ -201,13 +205,13 @@ pnpm test # Vitest 测试 pnpm test:changed # 廉价的智能 changed Vitest 目标 pnpm test:channels pnpm test:contracts:channels -pnpm check:docs # 文档格式 + lint + 失效链接 -pnpm build # 当 CI 产物/build-smoke 流水线相关时构建 dist -pnpm ci:timings # 汇总最近一次 origin/main push CI 运行 +pnpm check:docs # 文档格式 + lint + 损坏链接检查 +pnpm build # 当 CI 制品 / build-smoke 测试路径相关时,构建 dist +pnpm ci:timings # 汇总最近一次 origin/main 推送 CI 运行 pnpm ci:timings:recent # 比较最近成功的 main CI 运行 node scripts/ci-run-timings.mjs # 汇总总耗时、排队时间和最慢作业 -node scripts/ci-run-timings.mjs --latest-main # 忽略 issue/comment 噪声并选择 origin/main push CI -node scripts/ci-run-timings.mjs --recent 10 # 比较最近成功的 main CI 运行 +node scripts/ci-run-timings.mjs --latest-main # 忽略 issue / comment 噪声并选择 origin/main 推送 CI +node scripts/ci-run-timings.mjs --recent 10 # 比较最近成功的 10 次 main CI 运行 pnpm test:perf:groups --full-suite --allow-failures --output .artifacts/test-perf/baseline-before.json pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifacts/test-perf/after-agent.json ``` diff --git a/docs/zh-CN/help/testing.md b/docs/zh-CN/help/testing.md index fca64e35c..e325b4887 100644 --- a/docs/zh-CN/help/testing.md +++ b/docs/zh-CN/help/testing.md @@ -3,173 +3,137 @@ read_when: - 在本地或 CI 中运行测试 - 为模型 / 提供商缺陷添加回归测试 - 调试 Gateway 网关 + 智能体行为 -summary: 测试工具包:单元 / e2e / 实时测试套件、Docker 运行器,以及各项测试的覆盖范围 +summary: 测试工具包:单元 / e2e / 实时测试套件、Docker 运行器,以及各项测试的覆盖内容 title: 测试 x-i18n: - generated_at: "2026-04-27T19:38:38Z" + generated_at: "2026-04-27T22:50:29Z" model: gpt-5.4 provider: openai - source_hash: 142d45ff5b05c38c6a8220752ac683b9b0f4492eaa3f41dc9507f1d0d885c364 + source_hash: f5adf6c223bc489d8c9eceb5a5a5b5b2c0fb774a48f6a71f6b793361e2fd4911 source_path: help/testing.md workflow: 15 --- -OpenClaw 有三个 Vitest 测试套件(单元 / 集成、e2e、实时)以及一小组 Docker 运行器。本文档是一份“我们如何测试”的指南: +OpenClaw 有三个 Vitest 测试套件(单元 / 集成、e2e、实时),以及一小组 Docker 运行器。本文档是“我们如何测试”的指南: -- 各个测试套件覆盖什么(以及它们刻意 _不_ 覆盖什么)。 -- 常见工作流应运行哪些命令(本地、推送前、调试)。 +- 各个测试套件覆盖什么(以及它刻意**不**覆盖什么)。 +- 常见工作流(本地、推送前、调试)应运行哪些命令。 - 实时测试如何发现凭证并选择模型 / 提供商。 - 如何为真实世界中的模型 / 提供商问题添加回归测试。 -**QA 栈(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-specific runners](#qa-specific-runners))列出了具体的 `qa` 调用方式,并回指上述参考文档。 +本页涵盖常规测试套件以及 Docker / Parallels 运行器的运行方式。下面的 QA 专用运行器部分([QA 专用运行器](#qa-specific-runners))列出了具体的 `qa` 调用方式,并回链到上述参考文档。 ## 快速开始 大多数时候: -- 完整门禁(预期在推送前运行):`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` -- 当你正在迭代处理单个失败用例时,优先选择有针对性的运行方式。 +- 完整门禁(预期应在推送前运行):`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` +- 当你在迭代处理单个失败用例时,优先先跑有针对性的测试。 - 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` +- E2E 套件:`pnpm test:e2e` 当你在调试真实提供商 / 模型时(需要真实凭证): -- 实时测试套件(模型 + Gateway 网关工具 / 图像探测):`pnpm test:live` -- 安静地只运行一个实时测试文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts` -- Docker 实时模型扫描:`pnpm test:docker:live-models` - - 现在每个选中的模型都会运行一次文本轮次和一个小型的类文件读取探测。元数据声明支持 `image` 输入的模型还会运行一次微型图像轮次。 - 在隔离提供商故障时,可通过 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 +- 实时套件(模型 + 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` 和手动的 + - 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`,其中包括按提供商分片的独立 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 调用方中。 + - 将新的高信号提供商密钥添加到 `scripts/ci-hydrate-live-auth.sh`,同时更新 `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 及其定时 / 发布调用方。 - 原生 Codex 绑定聊天冒烟测试:`pnpm test:docker:live-codex-bind` - - 在 Codex app-server 路径上运行一个 Docker 实时通道,使用 `/codex bind` - 绑定一个合成 Slack 私信,会执行 `/codex fast` 和 - `/codex permissions`,然后验证普通回复和图像附件会通过原生插件绑定路由, - 而不是 ACP。 + - 在 Codex app-server 路径上运行 Docker 实时通道,绑定一个合成 Slack 私信,使用 `/codex bind`,执行 `/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、sub-agent 和 Guardian 探测。若要在隔离其他 Codex - app-server 故障时禁用 sub-agent 探测,可设置 - `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0`。若要只做一次聚焦的 - sub-agent 检查,请禁用其他探测: + - 通过插件拥有的 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`, - 否则它会在 sub-agent 探测后退出。 + 除非设置了 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`,否则该流程会在子智能体探测后退出。 - Crestodian 救援命令冒烟测试:`pnpm test:live:crestodian-rescue-channel` - - 针对消息渠道救援命令界面的可选双保险检查。它会执行 `/crestodian status`, - 排入一个持久模型变更,回复 `/crestodian yes`,并验证审计 / 配置写入路径。 -- Crestodian planner Docker 冒烟测试:`pnpm test:docker:crestodian-planner` - - 在一个没有配置的容器中运行 Crestodian,并在 `PATH` 上提供一个假的 Claude CLI, - 验证模糊 planner 回退会转换为一条带审计的类型化配置写入。 + - 这是消息渠道救援命令入口的可选双重保险检查。它会执行 `/crestodian status`,排队一个持久化模型变更,回复 `/crestodian yes`,并验证审计 / 配置写入路径。 +- Crestodian 规划器 Docker 冒烟测试:`pnpm test:docker:crestodian-planner` + - 在无配置容器中运行 Crestodian,并在 `PATH` 上放置假的 Claude CLI,验证模糊规划器回退会被转换为带审计记录的类型化配置写入。 - 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` - 得到覆盖。 + - 从空的 OpenClaw 状态目录启动,将裸 `openclaw` 路由到 + Crestodian,应用设置 / 模型 / 智能体 / 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 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`。 + 。验证 JSON 报告的是 Moonshot / K2.6,并且助手转录中存储了规范化的 `usage.cost`。 -当你只需要一个失败用例时,优先通过下面描述的 allowlist 环境变量来缩小实时测试范围。 +当你只需要一个失败用例时,优先使用下面描述的允许列表环境变量来缩小实时测试范围。 ## QA 专用运行器 -当你需要 qa-lab 级别的真实性时,这些命令与主测试套件并列使用: +当你需要 qa-lab 级别的真实环境时,这些命令与主测试套件配套使用: -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 通道。 +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 通道。 - `pnpm openclaw qa suite` - - 直接在主机上运行仓库支持的 QA 场景。 - - 默认会以隔离的 Gateway 网关工作进程并行运行多个选定场景。`qa-channel` - 默认并发数为 4(受所选场景数量限制)。使用 `--concurrency ` 调整工作进程数量, - 或使用 `--concurrency 1` 运行旧式串行通道。 - - 任一场景失败时会以非零状态退出。若你希望保留工件但不以失败退出,可使用 `--allow-failures`。 + - 直接在宿主机上运行仓库支持的 QA 场景。 + - 默认会使用隔离的 Gateway 网关工作进程并行运行多个已选场景。`qa-channel` 默认并发度为 4(受已选场景数量限制)。使用 `--concurrency ` 调整工作进程数,或使用 `--concurrency 1` 回到较早的串行通道。 + - 任一场景失败时将以非零状态退出。若你想保留制品但不希望退出码失败,可使用 `--allow-failures`。 - 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。 - `aimock` 会启动一个本地 AIMock 支持的 provider 服务,用于实验性的 - 固定装置和协议 mock 覆盖,而不会替代具备场景感知的 `mock-openai` 通道。 + `aimock` 会启动一个本地的 AIMock 支持提供商服务器,用于实验性的 fixture 和协议模拟覆盖,而不会替换具备场景感知能力的 `mock-openai` 通道。 - `pnpm openclaw qa suite --runner multipass` - - 在一个一次性的 Multipass Linux VM 中运行相同的 QA 测试套件。 - - 保持与主机上 `qa suite` 相同的场景选择行为。 + - 在一次性 Multipass Linux VM 中运行同一套 QA 测试。 + - 与宿主机上的 `qa suite` 保持相同的场景选择行为。 - 复用与 `qa suite` 相同的提供商 / 模型选择标志。 - - 实时运行会转发适合宾客环境的受支持 QA 认证输入: - 基于环境变量的 provider 密钥、QA 实时 provider 配置路径,以及存在时的 `CODEX_HOME`。 - - 输出目录必须保留在仓库根目录下,以便宾客环境能够通过挂载的工作区回写内容。 - - 会将常规 QA 报告 + 摘要以及 Multipass 日志写入 + - 实时运行会转发对来宾环境切实可行的受支持 QA 鉴权输入: + 基于环境变量的提供商密钥、QA 实时提供商配置路径,以及存在时的 `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-key 新手引导, - 默认配置 Telegram,验证启用插件时会按需安装运行时依赖,运行 doctor, - 并针对一个 mock 的 OpenAI 端点运行一次本地智能体轮次。 + - 从当前检出构建一个 npm tarball,在 Docker 中全局安装它,运行非交互式 OpenAI API 密钥新手引导,默认配置 Telegram,验证启用插件时会按需安装运行时依赖,运行 doctor,并针对模拟的 OpenAI 端点运行一次本地智能体轮次。 - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可在 Discord 上运行相同的打包安装通道。 - `pnpm test:docker:session-runtime-context` - - 针对嵌入式运行时上下文 transcript 运行一个确定性的 built-app Docker 冒烟测试。 - 它会验证隐藏的 OpenClaw 运行时上下文被持久化为一条非展示型自定义消息, - 而不是泄漏到可见的用户轮次中;随后会植入一个受影响的损坏 session JSONL, - 并验证 `openclaw doctor --fix` 会将其重写为当前活动分支,同时保留备份。 + - 为嵌入式运行时上下文转录运行一个确定性的已构建应用 Docker 冒烟测试。它会验证隐藏的 OpenClaw 运行时上下文被持久化为非显示型自定义消息,而不会泄漏到可见的用户轮次中;然后植入一个受影响的损坏会话 JSONL,并验证 + `openclaw doctor --fix` 会将其重写到当前活动分支,并保留备份。 - `pnpm test:docker:npm-telegram-live` - - 在 Docker 中安装一个 OpenClaw 包候选版本,运行已安装包的新手引导, - 通过已安装的 CLI 配置 Telegram,然后复用实时 Telegram QA 通道, - 将该已安装包作为被测 Gateway 网关。 - - 默认使用 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`;设置 + - 在 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_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_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` 仅为此通道覆盖共享的 `OPENCLAW_QA_CREDENTIAL_ROLE`。 - - GitHub Actions 也将此通道暴露为手动维护者工作流 + - 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 运行。 +- GitHub Actions 还提供 `Package Acceptance`,用于针对单个候选包执行旁路产品验证。它接受可信 ref、已发布的 npm 规格、HTTPS tarball URL 加 SHA-256,或来自另一个运行的 tarball 制品;随后上传规范化的 `openclaw-current.tgz` 作为 `package-under-test`,再运行现有的 Docker E2E 调度器,可选择 smoke、package、product、full 或自定义通道配置。设置 `telegram_mode=mock-openai` 或 `live-frontier`,即可让 Telegram QA 工作流针对同一个 `package-under-test` 制品运行。 - 最新 beta 产品验证: ```bash @@ -180,7 +144,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 \ @@ -190,7 +154,7 @@ gh workflow run package-acceptance.yml --ref main \ -f suite_profile=package ``` -- Artifact 验证会从另一个 Actions 运行下载一个 tarball artifact: +- 制品验证会从另一个 Actions 运行下载 tarball 制品: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -201,58 +165,58 @@ gh workflow run package-acceptance.yml --ref main \ ``` - `pnpm test:docker:bundled-channel-deps` - - 在 Docker 中打包并安装当前的 OpenClaw 构建版本,以配置好的 OpenAI 启动 Gateway 网关,然后通过编辑配置启用内置的渠道 / 插件。 - - 验证 setup 发现过程会让未配置插件的运行时依赖保持缺失状态;首次已配置的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖;第二次重启不会重新安装已经激活的依赖。 - - 还会安装一个已知的旧 npm 基线版本,在运行 `openclaw update --tag ` 之前启用 Telegram,并验证候选版本在更新后的 doctor 会修复内置渠道运行时依赖,而无需 harness 侧的 postinstall 修复。 + - 在 Docker 中打包并安装当前的 OpenClaw 构建,配置 OpenAI 后启动 Gateway 网关,然后通过编辑配置启用内置渠道 / 插件。 + - 验证设置发现流程会让未配置插件的运行时依赖保持缺失状态,首次配置后的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖,而第二次重启不会重新安装已经激活过的依赖。 + - 还会安装一个已知的旧版 npm 基线,在运行 `openclaw update --tag ` 之前启用 Telegram,并验证候选版本在更新后的 doctor 中会修复内置渠道运行时依赖,而无需 harness 侧的 postinstall 修复。 - `pnpm test:parallels:npm-update` - - 在 Parallels 来宾环境中运行原生打包安装更新冒烟测试。每个选定平台都会先安装所请求的基线包,然后在同一个来宾环境中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新状态、Gateway 网关就绪情况,以及一次本地智能体轮次。 - - 在迭代单个来宾环境时,使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 可获取摘要 artifact 路径和每个通道状态。 - - 默认情况下,OpenAI 通道会使用 `openai/gpt-5.5` 作为实时智能体轮次验证模型。若要有意验证其他 OpenAI 模型,请传入 `--model ` 或设置 `OPENCLAW_PARALLELS_OPENAI_MODEL`。 - - 在本地长时间运行时,请在主机侧加上超时包装,以避免 Parallels 传输卡顿耗尽剩余测试窗口: + - 在 Parallels 来宾环境中运行原生打包安装更新冒烟测试。每个选定平台都会先安装请求的基线包,然后在同一个来宾环境中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新状态、Gateway 网关就绪情况,以及一次本地智能体轮次。 + - 在只迭代单个来宾时,使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 可获取摘要制品路径和各通道状态。 + - OpenAI 通道默认使用 `openai/gpt-5.5` 进行实时智能体轮次验证。若要有意验证其他 OpenAI 模型,请传入 `--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 调试日志仍在推进,这仍然是健康状态。 + - 该脚本会将嵌套通道日志写入 `/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 加载。 + - 更新后的验证会运行常规的内置插件入口,因为语音、图像生成和媒体理解等能力 facade 是通过内置运行时 API 加载的,即使智能体轮次本身只检查简单的文本响应也是如此。 - `pnpm openclaw qa aimock` - - 仅启动本地 AIMock provider 服务,用于直接协议冒烟测试。 + - 仅启动本地 AIMock 提供商服务器,用于直接协议冒烟测试。 - `pnpm openclaw qa matrix` - - 针对一次性的 Docker 支持 Tuwunel homeserver 运行 Matrix 实时 QA 通道。仅适用于源代码检出 —— 打包安装版本不包含 `qa-lab`。 - - 完整 CLI、profile / 场景目录、环境变量和 artifact 布局:见 [Matrix QA](/zh-CN/concepts/qa-matrix)。 + - 针对一次性 Docker 支持的 Tuwunel homeserver 运行 Matrix 实时 QA 通道。仅支持源代码检出——打包安装不包含 `qa-lab`。 + - 完整的 CLI、配置文件 / 场景目录、环境变量和制品布局:参见 [Matrix QA](/zh-CN/concepts/qa-matrix)。 - `pnpm openclaw qa telegram` - - 使用来自环境变量的驱动器和 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。 + - 使用环境变量中的驱动机器人和 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` 以启用池化租约。 - - 任一场景失败时会以非零状态退出。若你希望保留 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。 + - 任一场景失败时将以非零状态退出。若你想保留制品但不希望退出码失败,可使用 `--allow-failures`。 + - 需要同一私有群组中的两个不同机器人,并且 SUT 机器人需要公开一个 Telegram 用户名。 + - 为了实现稳定的机器人到机器人观测,请在 `@BotFather` 中为两个机器人启用 Bot-to-Bot Communication Mode,并确保驱动机器人可以观测群组中的机器人流量。 + - 会在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 制品。回复类场景会包含从驱动发送请求到观测到 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 项目脚手架: +参考的 Convex 项目脚手架: - `qa/convex-credential-broker/` 必需的环境变量: - `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`) -- 为所选角色提供一个密钥: - - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` 用于 `maintainer` - - `OPENCLAW_QA_CONVEX_SECRET_CI` 用于 `ci` +- 为选定角色配置一个密钥: + - `maintainer` 对应 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` + - `ci` 对应 `OPENCLAW_QA_CONVEX_SECRET_CI` - 凭证角色选择: - CLI:`--credential-role maintainer|ci` - - 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认为 `ci`,否则为 `maintainer`) + - 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认为 `ci`,否则默认为 `maintainer`) 可选环境变量: @@ -262,14 +226,13 @@ gh workflow run package-acceptance.yml --ref main \ - `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS`(默认 `15000`) - `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX`(默认 `/qa-credentials/v1`) - `OPENCLAW_QA_CREDENTIAL_OWNER_ID`(可选追踪 id) -- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许在仅限本地开发时使用 loopback `http://` Convex URL。 +- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许仅用于本地开发的 loopback `http://` Convex URL。 -正常运行时,`OPENCLAW_QA_CONVEX_SITE_URL` 应使用 `https://`。 +在正常运行中,`OPENCLAW_QA_CONVEX_SITE_URL` 应使用 `https://`。 -维护者管理命令(池添加 / 删除 / 列表)需要专门使用 -`OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 +维护者管理命令(池添加 / 移除 / 列表)必须专门使用 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 -供维护者使用的 CLI 辅助命令: +面向维护者的 CLI 辅助命令: ```bash pnpm openclaw qa credentials doctor @@ -278,9 +241,9 @@ pnpm openclaw qa credentials list --kind telegram pnpm openclaw qa credentials remove --credential-id ``` -在实时运行前使用 `doctor`,可检查 Convex 站点 URL、broker 密钥、 -端点前缀、HTTP 超时以及管理 / 列表可达性,同时不会打印密钥值。使用 `--json` -可在脚本和 CI 工具中获得机器可读输出。 +在实时运行前使用 `doctor` 来检查 Convex 站点 URL、broker 密钥、 +端点前缀、HTTP 超时和管理 / 列表可达性,同时不会打印密钥值。 +在脚本和 CI 工具中使用 `--json` 可获得机器可读输出。 默认端点契约(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): @@ -294,106 +257,108 @@ pnpm openclaw qa credentials remove --credential-id - `POST /release` - 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken }` - 成功:`{ status: "ok" }`(或空的 `2xx`) -- `POST /admin/add`(仅维护者密钥) +- `POST /admin/add`(仅限 maintainer 密钥) - 请求:`{ kind, actorId, payload, note?, status? }` - 成功:`{ status: "ok", credential }` -- `POST /admin/remove`(仅维护者密钥) +- `POST /admin/remove`(仅限 maintainer 密钥) - 请求:`{ credentialId, actorId }` - 成功:`{ status: "ok", changed, credential }` - 活跃租约保护:`{ status: "error", code: "LEASE_ACTIVE", ... }` -- `POST /admin/list`(仅维护者密钥) +- `POST /admin/list`(仅限 maintainer 密钥) - 请求:`{ kind?, status?, includePayload?, limit? }` - 成功:`{ status: "ok", credentials, count }` Telegram 类型的 payload 结构: - `{ groupId: string, driverToken: string, sutToken: string }` -- `groupId` 必须是 Telegram chat 的数字 id 字符串。 -- `admin/add` 会为 `kind: "telegram"` 验证此结构,并拒绝格式错误的 payload。 +- `groupId` 必须是 Telegram 聊天数字 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 `,并在 `qa/scenarios/` 下编写场景。 +新渠道适配器的架构和场景辅助函数名称位于 [QA overview → Adding a channel](/zh-CN/concepts/qa-e2e-automation#adding-a-channel)。最低门槛是:在共享的 `qa-lab` 宿主接缝上实现传输运行器、在插件清单中声明 `qaRunners`、挂载为 `openclaw qa `,并在 `qa/scenarios/` 下编写场景。 ## 测试套件(各自运行位置) -可以将这些测试套件理解为“真实性逐步提高”(同时不稳定性 / 成本也逐步增加): +可以把这些测试套件理解为“真实性逐级增加”(同时波动性 / 成本也逐级增加): ### 单元 / 集成(默认) - 命令:`pnpm test` -- 配置:未定向运行使用 `vitest.full-*.config.ts` 分片集合,并且可能会将多项目分片展开为按项目划分的配置,以便并行调度 -- 文件:核心 / 单元清单位于 `src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts`;UI 单元测试在专用的 `unit-ui` 分片中运行 +- 配置:未指定目标的运行使用 `vitest.full-*.config.ts` 分片集合,并且可能会将多项目分片展开为按项目划分的配置,以便并行调度 +- 文件:核心 / 单元清单位于 `src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts`;UI 单元测试运行在专用的 `unit-ui` 分片中 - 范围: - 纯单元测试 - 进程内集成测试(Gateway 网关认证、路由、工具、解析、配置) - - 针对已知缺陷的确定性回归测试 + - 已知缺陷的确定性回归测试 - 预期: - 在 CI 中运行 - 不需要真实密钥 - - 应该快速且稳定 + - 应当快速且稳定 - - 未定向的 `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 `。仅发布元数据的版本升级会运行有针对性的版本 / 配置 / 根依赖检查,并带有一项保护:拒绝顶层 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 尾部耗时。 + - 未指定目标的 `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` 文件、显式源码映射以及本地导入图依赖项。配置 / setup / 包编辑不会广泛运行测试,除非你显式使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 + - `pnpm check:changed` 是窄范围工作时的常规智能本地检查门禁。它会将差异分类为核心、核心测试、扩展、扩展测试、应用、文档、发布元数据、实时 Docker 工具和工具链,然后运行匹配的类型检查、lint 和守卫命令。它不会运行 Vitest 测试;如需测试证明,请调用 `pnpm test:changed` 或显式执行 `pnpm test `。仅发布元数据的版本提升会运行有针对性的版本 / 配置 / 根依赖检查,并带有一个守卫,用于拒绝顶层版本字段之外的包变更。 + - 实时 Docker ACP harness 编辑会运行聚焦检查:实时 Docker 认证脚本的 shell 语法检查,以及实时 Docker 调度器 dry-run。只有当差异仅限于 `scripts["test:docker:live-*"]` 时才会包含 `package.json` 变更;依赖、导出、版本和其他包表面编辑仍然使用更广泛的守卫。 + - 来自智能体、commands、插件、auto-reply 辅助器、`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 尾部运行时间。 - 当你修改消息工具发现输入或 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 和 compaction 行为仍然通过真实的 `run.ts` / `compact.ts` 路径流转;仅有辅助函数测试并不足以替代这些集成路径。 + - 这些套件会验证作用域 id 和 compaction 行为仍然会流经真实的 `run.ts` / `compact.ts` 路径;仅有辅助器级测试并不足以替代这些集成路径。 - 基础 Vitest 配置默认使用 `threads`。 - - 共享 Vitest 配置固定设置 `isolate: false`,并在根项目、e2e 和实时配置中使用非隔离运行器。 - - 根 UI 通道保留其 `jsdom` setup 和优化器,但也运行在共享的非隔离运行器上。 + - 共享 Vitest 配置将 `isolate: false` 固定下来,并在根项目、e2e 和实时配置中使用非隔离运行器。 + - 根 UI 通道保留其 `jsdom` 设置和优化器,但也运行在共享的非隔离运行器上。 - 每个 `pnpm test` 分片都从共享 Vitest 配置继承相同的 `threads` + `isolate: false` 默认值。 - - `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可与原生 V8 行为进行对比。 + - `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。 + 设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可对比原生 V8 + 行为。 - - `pnpm changed:lanes` 会显示一个 diff 触发了哪些架构通道。 - - pre-commit 钩子仅负责格式化。它会重新暂存已格式化的文件,不会运行 lint、类型检查或测试。 + - `pnpm changed:lanes` 会显示某个差异会触发哪些架构通道。 + - 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`。 + - `pnpm test:changed` 默认通过低成本的作用域通道路由。仅当智能体判断某个 harness、配置、包或契约编辑确实需要更广泛的 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 test:perf:imports` 会启用 Vitest 导入耗时报告以及导入分解输出。 - - `pnpm test:perf:imports:changed` 会将相同的分析视图限定到自 `origin/main` 以来发生变化的文件。 + - `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 ` 会针对该已提交 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。 + 整个配置运行使用配置路径作为键;include-pattern CI 分片会追加分片名称,以便单独跟踪过滤后的分片。 + - 当某个热点测试仍然把大部分时间耗在启动导入上时,应将重依赖放在狭窄的本地 `*.runtime.ts` 接缝之后,并直接 mock 该接缝,而不是为了通过 `vi.mock(...)` 传递它们就去深度导入运行时辅助器。 + - `pnpm test:perf:changed:bench -- --ref ` 会针对该已提交差异,对比路由后的 `test:changed` 与原生根项目路径,并打印墙钟时间以及 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。 @@ -401,139 +366,139 @@ Telegram 类型的 payload 结构: ### 稳定性(Gateway 网关) - 命令:`pnpm test:stability:gateway` -- 配置:`vitest.gateway.config.ts`,强制使用单个工作进程 +- 配置:`vitest.gateway.config.ts`,强制单 worker - 范围: - - 启动一个真实的 loopback Gateway 网关,并默认启用诊断 - - 通过诊断事件路径驱动合成的 gateway message、memory 和 large-payload 抖动 + - 默认启用诊断功能,启动一个真实的 loopback Gateway 网关 + - 通过诊断事件路径驱动合成的 Gateway 网关消息、内存和大负载抖动 - 通过 Gateway 网关 WS RPC 查询 `diagnostics.stability` - - 覆盖诊断稳定性 bundle 持久化辅助工具 - - 断言记录器保持有界、合成 RSS 样本低于压力预算,并且每个 session 的队列深度会回落到零 + - 覆盖诊断稳定性 bundle 持久化辅助器 + - 断言记录器保持有界、合成 RSS 采样保持在压力预算之下,并且每个会话的队列深度最终回落到零 - 预期: - - 对 CI 安全且无需密钥 - - 这是用于稳定性回归跟进的狭窄通道,不可替代完整的 Gateway 网关测试套件 + - 对 CI 安全且无须密钥 + - 这是用于稳定性回归跟进的窄范围通道,不可替代完整 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`,与仓库其余部分保持一致。 - - 使用自适应工作进程(CI:最多 2 个,本地:默认 1 个)。 + - 使用 Vitest `threads`,并设置 `isolate: false`,与仓库其余部分保持一致。 + - 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。 - 默认以静默模式运行,以减少控制台 I/O 开销。 - 常用覆盖项: - - `OPENCLAW_E2E_WORKERS=`:强制设置工作进程数量(上限为 16)。 - - `OPENCLAW_E2E_VERBOSE=1`:重新启用详细控制台输出。 + - 使用 `OPENCLAW_E2E_WORKERS=` 强制设置 worker 数量(上限为 16)。 + - 使用 `OPENCLAW_E2E_VERBOSE=1` 重新启用详细控制台输出。 - 范围: - 多实例 Gateway 网关端到端行为 - - WebSocket / HTTP 界面、节点配对和更重型的网络行为 + - WebSocket / HTTP 表面、节点配对以及更重的网络交互 - 预期: - 会在 CI 中运行(当流水线启用时) - 不需要真实密钥 - - 比单元测试涉及更多运动部件(可能更慢) + - 相比单元测试有更多活动部件(可能更慢) ### E2E:OpenShell 后端冒烟测试 - 命令:`pnpm test:e2e:openshell` - 文件:`extensions/openshell/src/backend.e2e.test.ts` - 范围: - - 通过 Docker 在主机上启动一个隔离的 OpenShell Gateway 网关 + - 通过 Docker 在宿主机上启动一个隔离的 OpenShell Gateway 网关 - 从一个临时本地 Dockerfile 创建沙箱 - 通过真实的 `sandbox ssh-config` + SSH exec 运行 OpenClaw 的 OpenShell 后端 - - 通过沙箱文件系统桥接验证远程规范文件系统行为 + - 通过沙箱 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 二进制文件或包装脚本 + - 运行更广泛的 e2e 套件时,设置 `OPENCLAW_E2E_OPENSHELL=1` 启用该测试 + - 设置 `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` 以指向非默认 CLI 二进制或包装脚本 ### 实时(真实提供商 + 真实模型) - 命令:`pnpm test:live` - 配置:`vitest.live.config.ts` - 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件实时测试 -- 默认:由 `pnpm test:live` **启用**(设置 `OPENCLAW_LIVE_TEST=1`) +- 默认:由 `pnpm test:live` **启用**(会设置 `OPENCLAW_LIVE_TEST=1`) - 范围: - - “这个提供商 / 模型 _今天_ 用真实凭证是否真的可用?” - - 捕获提供商格式变化、工具调用怪癖、认证问题和速率限制行为 + - “这个提供商 / 模型在 _今天_ 搭配真实凭证是否真的可用?” + - 捕捉提供商格式变更、工具调用怪癖、认证问题以及限流行为 - 预期: - - 设计上不保证 CI 稳定(真实网络、真实提供商策略、配额、故障) - - 会花钱 / 消耗速率限制额度 - - 优先运行缩小范围的子集,而不是“全部运行” -- 实时运行会读取 `~/.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` 进行每次实时运行覆盖;测试会在收到速率限制响应时重试。 + - 按设计并不具备 CI 稳定性(真实网络、真实提供商策略、配额、故障) + - 会花钱 / 消耗速率限制 + - 优先运行收窄后的子集,而不是“全部都跑” +- 实时运行会加载 `~/.profile`,以拾取缺失的 API 密钥。 +- 默认情况下,实时运行仍会隔离 `HOME`,并将配置 / 认证材料复制到一个临时测试 home 中,这样单元测试 fixture 就不会修改你真实的 `~/.openclaw`。 +- 仅当你有意让实时测试使用真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。 +- `pnpm test:live` 现在默认采用更安静的模式:它会保留 `[live] ...` 进度输出,但会抑制额外的 `~/.profile` 提示,并静音 Gateway 网关引导日志 / Bonjour 噪声。如果你想恢复完整启动日志,可设置 `OPENCLAW_LIVE_TEST_QUIET=0`。 +- API 密钥轮换(按提供商区分):设置 `*_API_KEYS`(逗号 / 分号格式)或 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),或通过 `OPENCLAW_LIVE_*_KEY` 进行按实时测试覆盖;测试会在收到限流响应时重试。 - 进度 / 心跳输出: - - 实时测试套件现在会将进度行输出到 stderr,因此即使 Vitest 控制台捕获较安静,长时间的提供商调用也能明显显示仍在活动。 - - `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,因此提供商 / Gateway 网关进度行会在实时运行期间立即流式输出。 - - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整 direct-model 心跳。 - - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关 / probe 心跳。 + - 实时套件现在会将进度行输出到 stderr,因此即使 Vitest 控制台捕获很安静,长时间的提供商调用也能显示仍在活动。 + - `vitest.live.config.ts` 禁用了 Vitest 控制台拦截,因此提供商 / Gateway 网关进度行会在实时运行期间立即流出。 + - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整直接模型心跳。 + - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关 / 探测心跳。 ## 我应该运行哪个测试套件? -使用下面这张决策表: +使用这个决策表: -- 编辑逻辑 / 测试:运行 `pnpm test`(如果你改动很多,再运行 `pnpm test:coverage`) -- 触及 Gateway 网关网络 / WS 协议 / 配对:额外运行 `pnpm test:e2e` -- 调试“我的 bot 挂了” / 提供商特定故障 / 工具调用:运行一个缩小范围的 `pnpm test:live` +- 编辑逻辑 / 测试:运行 `pnpm test`(如果改动较多,再加上 `pnpm test:coverage`) +- 触及 Gateway 网关网络 / WS 协议 / 配对:再加上 `pnpm test:e2e` +- 调试“我的机器人挂了” / 提供商特定故障 / 工具调用:运行收窄后的 `pnpm test:live` ## 实时(触网)测试 -有关实时模型矩阵、CLI 后端冒烟测试、ACP 冒烟测试、Codex app-server +关于实时模型矩阵、CLI 后端冒烟测试、ACP 冒烟测试、Codex app-server harness,以及所有媒体提供商实时测试(Deepgram、BytePlus(国际版)、ComfyUI、图像、 -音乐、视频、media harness)—— 以及实时运行的凭证处理 —— 请参阅 +音乐、视频、媒体 harness)——以及实时运行的凭证处理——请参见 [Testing — live suites](/zh-CN/help/testing-live)。 ## 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` 中,用于 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` 之后的包,这些路径都会被视为严格失败。 + `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` 时选择要打包的源提交 / 分支 / 标签;这样当前的 acceptance 逻辑就能验证较早但可信的提交。各个配置文件按覆盖广度排序:`smoke` 是快速的安装 / 渠道 / 智能体加 Gateway 网关 / 配置检查,`package` 覆盖包 / 更新 / 插件契约,并且是大多数 Parallels 包 / 更新覆盖的默认原生替代方案,`product` 会加入 MCP 渠道、cron / 子智能体清理、OpenAI Web 搜索和 OpenWebUI,而 `full` 会运行带 OpenWebUI 的发布路径 Docker 分块。发布验证会运行自定义的 package delta(`bundled-channel-deps-compat plugins-offline`)加 Telegram package QA,因为发布路径 Docker 分块已经覆盖了重叠的包 / 更新 / 插件通道。根据制品生成的定向 GitHub Docker 重跑命令,在可用时会包含先前的包制品和已准备好的镜像输入,因此失败通道可以避免重新构建包和镜像。 +- 构建和发布检查会在 tsdown 之后运行 `scripts/check-cli-bootstrap-imports.mjs`。该守卫会从 `dist/entry.js` 和 `dist/cli/run-main.js` 遍历静态构建图,并在命令分发之前的启动导入阶段,如果发现导入了 Commander、提示 UI、undici 或日志记录等包依赖,就会失败。打包后的 CLI 冒烟测试还覆盖根 help、onboard help、doctor help、status、config schema 和 model-list 命令。 +- `Package Acceptance` 旧版兼容性上限为 `2026.4.25`(包含 `2026.4.25-beta.*`)。在这个截止点之前,harness 仅容忍已发布包中的元数据缺口:省略的私有 QA 清单条目、缺失的 `gateway install --wrapper`、从 tarball 派生的 git fixture 中缺失的补丁文件、缺失的持久化 `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 中,以便外部 CLI OAuth 可以刷新 token,而不会修改主机认证存储: +实时模型 Docker 运行器还会只绑定挂载所需的 CLI 认证 home 目录(如果运行未收窄,则挂载所有受支持的目录),然后在运行前将它们复制到容器 home 中,这样外部 CLI OAuth 就可以刷新令牌,而不会修改宿主机认证存储: - 直接模型:`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,若需严格的 Droid / OpenCode 覆盖,可使用 `pnpm test:docker:live-acp-bind:droid` 和 `pnpm test:docker:live-acp-bind:opencode`) +- 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 网关 + dev 智能体:`pnpm test:docker:live-gateway`(脚本:`scripts/test-live-gateway-models-docker.sh`) -- 可观测性冒烟测试:`pnpm qa:otel:smoke` 是私有的 QA 源代码检出通道。它故意不属于 package Docker 发布通道的一部分,因为 npm tarball 不包含 QA Lab。 +- Gateway 网关 + 开发智能体:`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 会修复已激活插件的运行时依赖,并运行一次 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` 最小推理回归测试:`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`) +- 新手引导向导(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 镜像。 +- 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` 最小推理回归测试:`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 渠道 bridge(植入的 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` 覆盖默认 package。 -- 插件更新未变更冒烟测试:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-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 的独立更新通道。发布工作流还会拆分 provider 安装器分块以及内置插件安装 / 卸载分块;旧版 `package-update`、`plugins-runtime` 和 `plugins-integrations` 分块仍保留为手动重跑的聚合别名。直接运行内置通道时,可使用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 缩小渠道矩阵,或使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 缩小更新场景。该通道还会验证 `channels..enabled=false` 和 `plugins.entries..enabled=false` 会抑制 doctor / 运行时依赖修复。 -- 在迭代时,如需缩小内置插件运行时依赖覆盖范围,可禁用无关场景,例如: +- 内置插件运行时依赖:`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 聚合运行器和发布路径内置渠道分块会先统一预打包这个 tarball,然后将内置渠道检查分片为独立通道,其中包括针对 Telegram、Discord、Slack、Feishu、memory-lancedb 和 ACPX 的独立更新通道。发布分块会将渠道冒烟测试、更新目标和设置 / 运行时契约拆分为 `bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`;聚合的 `bundled-channels` 分块仍可用于手动重跑。发布工作流还会拆分提供商安装器分块和内置插件安装 / 卸载分块;旧版的 `package-update`、`plugins-runtime` 和 `plugins-integrations` 分块仍保留为手动重跑时的聚合别名。直接运行内置通道时,可使用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 缩小渠道矩阵,或使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 缩小更新场景。该通道还会验证 `channels..enabled=false` 和 `plugins.entries..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`。 如需手动预构建并复用共享功能镜像: @@ -543,141 +508,141 @@ 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,因为它们验证的是 package / 安装行为,而不是共享的 built-app 运行时。 +诸如 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE` 之类的套件专用镜像覆盖项在设置时仍然优先生效。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果它尚未存在于本地,这些脚本会先拉取它。QR 和安装器 Docker 测试保留各自的 Dockerfile,因为它们验证的是包 / 安装行为,而不是共享的已构建应用运行时。 -实时模型 Docker 运行器还会以只读方式绑定挂载当前检出内容,并在容器内将其暂存到一个临时工作目录中。这样既能保持运行时镜像精简,又仍然可以针对你精确的本地源码 / 配置运行 Vitest。暂存步骤会跳过大型本地专用缓存和应用构建输出,例如 `.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及应用本地 `.build` 或 Gradle 输出目录,因此 Docker 实时运行不会花数分钟复制特定于机器的 artifact。 +实时模型 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` -(默认是 `~/.profile`)是在 Docker 化运行中提供该密钥的主要方式。 -成功运行会打印一小段 JSON payload,例如 `{ "ok": true, "model": +`test:docker:live-models` 仍然运行 `pnpm test:live`,因此当你需要缩小或排除该 Docker 通道中的 Gateway 网关实时覆盖时,也要透传 `OPENCLAW_LIVE_GATEWAY_*`。 +`test:docker:openwebui` 是一个更高层的兼容性冒烟测试:它会启动一个启用了 OpenAI 兼容 HTTP 端点的 OpenClaw Gateway 网关容器,再针对该 Gateway 网关启动一个固定版本的 Open WebUI 容器,通过 Open WebUI 登录,验证 `/api/models` 暴露 `openclaw/default`,然后通过 Open WebUI 的 `/api/chat/completions` 代理发送一个真实聊天请求。 +首次运行可能会明显更慢,因为 Docker 可能需要拉取 Open WebUI 镜像,而 Open WebUI 也可能需要完成自己的冷启动设置。 +这个通道需要一个可用的实时模型密钥,而 `OPENCLAW_PROFILE_FILE` +(默认为 `~/.profile`)是在 Docker 化运行中提供该密钥的主要方式。 +成功运行会打印一个小型 JSON 负载,例如 `{ "ok": true, "model": "openclaw/default", ... }`。 -`test:docker:mcp-channels` 是有意设计为确定性的,不需要真实的 Telegram、Discord 或 iMessage 账号。它会启动一个已植入的 Gateway 网关容器,再启动第二个容器来生成 `openclaw mcp serve`,然后通过真实的 stdio MCP bridge 验证路由后的会话发现、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 子进程会在每次运行后退出。 +`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 子进程会在每次运行后退出。 -手动 ACP 自然语言线程冒烟测试(不在 CI 中运行): +手动 ACP 自然语言线程冒烟测试(非 CI): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- 将此脚本保留用于回归 / 调试工作流。它未来可能仍然需要用于 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 安装 +- `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/...` - 默认目录:`.minimax` - 默认文件:`~/.codex/auth.json`、`~/.codex/config.toml`、`.claude.json`、`~/.claude/.credentials.json`、`~/.claude/settings.json`、`~/.claude/settings.local.json` - - 缩小范围的 provider 运行只会挂载从 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录 / 文件 + - 收窄后的提供商运行只会挂载从 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录 / 文件 - 可通过 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none` 或逗号列表(如 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex`)手动覆盖 -- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` 用于缩小运行范围 -- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` 用于在容器内筛选 provider -- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于复用现有的 `openclaw:local-live` 镜像,以便在无需重新构建时重跑 +- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` 用于收窄运行范围 +- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` 用于在容器内筛选提供商 +- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于复用现有的 `openclaw:local-live` 镜像,以便在不需要重建时重跑 - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用于确保凭证来自 profile 存储(而不是环境变量) - `OPENCLAW_OPENWEBUI_MODEL=...` 用于选择 Gateway 网关为 Open WebUI 冒烟测试暴露的模型 -- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试所使用的 nonce 检查提示词 +- `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 网关工具调用(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”) +- 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”) ## 智能体可靠性评估(Skills) 我们已经有一些对 CI 安全的测试,它们的行为类似“智能体可靠性评估”: -- 通过真实的 Gateway 网关 + Agent loop 进行 mock 工具调用(`src/gateway/gateway.test.ts`)。 -- 验证会话接线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。 +- 通过真实 Gateway 网关 + Agent loop 的模拟工具调用(`src/gateway/gateway.test.ts`)。 +- 验证会话布线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。 -对于 Skills(见 [Skills](/zh-CN/tools/skills)),仍然缺少的是: +Skills 方面仍然缺少的内容(参见 [Skills](/zh-CN/tools/skills)): -- **决策能力:** 当提示词中列出 Skills 时,智能体是否会选择正确的 Skills(或避开无关的 Skills)? -- **合规性:** 智能体是否会在使用前读取 `SKILL.md`,并遵循要求的步骤 / 参数? -- **工作流契约:** 断言工具顺序、会话历史延续和沙箱边界的多轮场景。 +- **决策**:当提示词中列出 Skills 时,智能体是否会选择正确的 Skills(或避免选择无关的 Skills)? +- **合规性**:智能体是否会在使用前读取 `SKILL.md` 并遵循所需步骤 / 参数? +- **工作流契约**:断言工具顺序、会话历史延续和沙箱边界的多轮场景。 -未来的评估应优先保持确定性: +未来的评估应当优先保持确定性: -- 一个使用 mock provider 的场景运行器,用于断言工具调用 + 顺序、skill 文件读取和会话接线。 -- 一小组聚焦 Skills 的场景(使用 vs 避免、门控、提示注入)。 -- 只有在对 CI 安全的测试套件到位之后,才添加可选的实时评估(需显式启用并受环境变量门控)。 +- 一个使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、技能文件读取和会话布线。 +- 一小组以 Skills 为重点的场景(使用 vs 避免、门控、提示注入)。 +- 仅在对 CI 安全的套件就绪之后,才添加可选的实时评估(显式启用、由环境变量控制)。 ## 契约测试(插件和渠道形状) -契约测试用于验证每个已注册插件和渠道都符合其接口契约。它们会遍历所有已发现的插件,并运行一套形状和行为断言。默认的 `pnpm test` 单元通道会刻意跳过这些共享接缝和冒烟文件;当你修改共享渠道或 provider 界面时,请显式运行契约命令。 +契约测试会验证每个已注册的插件和渠道都符合其接口契约。它们会遍历所有已发现的插件,并运行一组形状和行为断言。默认的 `pnpm test` 单元测试通道会有意跳过这些共享接缝和冒烟测试文件;当你修改共享渠道或提供商表面时,请显式运行契约命令。 ### 命令 -- 所有契约:`pnpm test:contracts` -- 仅渠道契约:`pnpm test:contracts:channels` -- 仅 provider 契约:`pnpm test:contracts:plugins` +- 所有契约测试:`pnpm test:contracts` +- 仅渠道契约测试:`pnpm test:contracts:channels` +- 仅提供商契约测试:`pnpm test:contracts:plugins` -### 渠道契约 +### 渠道契约测试 位于 `src/channels/plugins/contracts/*.contract.test.ts`: -- **plugin** - 基本插件形状(id、name、capabilities) +- **plugin** - 基础插件形状(id、名称、能力) - **setup** - 设置向导契约 - **session-binding** - 会话绑定行为 - **outbound-payload** - 消息负载结构 - **inbound** - 入站消息处理 -- **actions** - 渠道操作处理器 +- **actions** - 渠道动作处理器 - **threading** - 线程 ID 处理 - **directory** - 目录 / roster API -- **group-policy** - 群组策略强制执行 +- **group-policy** - 群组策略执行 -### Provider Status 契约 +### 提供商 Status 契约测试 位于 `src/plugins/contracts/*.contract.test.ts`。 - **status** - 渠道 Status 探测 - **registry** - 插件注册表形状 -### Provider 契约 +### 提供商契约测试 位于 `src/plugins/contracts/*.contract.test.ts`: - **auth** - 认证流程契约 -- **auth-choice** - 认证选择 / 选择逻辑 +- **auth-choice** - 认证方式 / 选择 - **catalog** - 模型目录 API - **discovery** - 插件发现 - **loader** - 插件加载 -- **runtime** - provider 运行时 +- **runtime** - 提供商运行时 - **shape** - 插件形状 / 接口 - **wizard** - 设置向导 ### 何时运行 -- 修改 `plugin-sdk` 导出或子路径之后 -- 添加或修改渠道或 provider 插件之后 -- 重构插件注册或发现逻辑之后 +- 在更改 plugin-sdk 导出或子路径之后 +- 在添加或修改渠道或提供商插件之后 +- 在重构插件注册或发现逻辑之后 -契约测试会在 CI 中运行,并且不需要真实 API key。 +契约测试会在 CI 中运行,并且不需要真实 API 密钥。 -## 添加回归测试(指导) +## 添加回归测试(指南) -当你修复一个在实时环境中发现的 provider / model 问题时: +当你修复一个在实时环境中发现的提供商 / 模型问题时: -- 如果可能,添加一个对 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 时故意失败,以确保新类别不会被静默跳过。 +- 如果可能,添加一个对 CI 安全的回归测试(模拟 / stub 提供商,或捕获精确的请求形状转换) +- 如果它本质上只能在实时环境中复现(限流、认证策略),则让该实时测试保持收窄,并通过环境变量显式启用 +- 优先定位到能捕捉该缺陷的最小层级: + - 提供商请求转换 / 重放缺陷 → 直接模型测试 + - Gateway 网关会话 / 历史 / 工具流水线缺陷 → Gateway 网关实时冒烟测试或对 CI 安全的 Gateway 网关模拟测试 +- SecretRef 遍历防护: + - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言遍历段 exec id 会被拒绝。 + - 如果你在 `src/secrets/target-registry-data.ts` 中添加了新的 `includeInPlan` SecretRef 目标族,请更新该测试中的 `classifyTargetClass`。该测试会有意在未分类目标 id 上失败,这样新类别就不会被悄悄跳过。 ## 相关内容 diff --git a/docs/zh-CN/logging.md b/docs/zh-CN/logging.md index 70470e7f1..37ad2bebd 100644 --- a/docs/zh-CN/logging.md +++ b/docs/zh-CN/logging.md @@ -1,27 +1,27 @@ --- read_when: - - 你需要一份适合初学者的 OpenClaw 日志概览 + - 你需要一份面向初学者的 OpenClaw 日志概览 - 你想要配置日志级别、格式或脱敏处理 - 你正在进行故障排除,需要快速找到日志 -summary: 文件日志、控制台输出、CLI 尾部日志查看,以及 Control UI 日志标签页 +summary: 文件日志、控制台输出、CLI 尾随输出以及 Control UI 的“日志”标签页 title: 日志 x-i18n: - generated_at: "2026-04-26T22:05:00Z" + generated_at: "2026-04-27T22:50:25Z" model: gpt-5.4 provider: openai - source_hash: 6fb71b94a5c4fb8db9c704552f73f364b45c9d19bfb74c92abe1f22576fe1480 + source_hash: 5c6f0e325540e6daca228a2e9cc6c032ccc27a3c2a38be13a29e87a6a1227081 source_path: logging.md workflow: 15 --- -OpenClaw 有两个主要的日志界面: +OpenClaw 有两个主要的日志展示面: -- **文件日志**(JSON 行格式),由 Gateway 网关写入。 -- **控制台输出**,显示在终端和 Gateway 网关调试 UI 中。 +- 由 Gateway 网关写入的**文件日志**(JSON 行)。 +- 在终端和 Gateway 网关调试 UI 中显示的**控制台输出**。 -Control UI 的 **Logs** 标签页会尾随 gateway 文件日志。本页说明日志位于哪里、如何读取日志,以及如何配置日志级别和格式。 +Control UI 的**日志**标签页会尾随显示 gateway 文件日志。本页说明日志位于哪里、如何读取,以及如何配置日志级别和格式。 -## 日志位于哪里 +## 日志存放位置 默认情况下,Gateway 网关会在以下路径写入滚动日志文件: @@ -29,7 +29,7 @@ Control UI 的 **Logs** 标签页会尾随 gateway 文件日志。本页说明 日期使用 gateway 主机的本地时区。 -每个文件在达到 `logging.maxFileBytes`(默认:100 MB)时会轮转。OpenClaw 最多会在活动文件旁保留五个带编号的归档文件,例如 `openclaw-YYYY-MM-DD.1.log`,并继续写入一个新的活动日志文件,而不是抑制诊断信息。 +每个文件在达到 `logging.maxFileBytes`(默认:100 MB)时会轮转。OpenClaw 会在活动文件旁保留最多五个带编号的归档文件,例如 `openclaw-YYYY-MM-DD.1.log`,并继续写入一个新的活动日志文件,而不是抑制诊断信息。 你可以在 `~/.openclaw/openclaw.json` 中覆盖此设置: @@ -59,24 +59,24 @@ openclaw logs --follow 输出模式: -- **TTY 会话**:美观、彩色、结构化的日志行。 +- **TTY 会话**:美观、带颜色、结构化的日志行。 - **非 TTY 会话**:纯文本。 - `--json`:按行分隔的 JSON(每行一个日志事件)。 - `--plain`:在 TTY 会话中强制使用纯文本。 - `--no-color`:禁用 ANSI 颜色。 -当你传入显式的 `--url` 时,CLI 不会自动应用配置或环境变量中的凭证;如果目标 Gateway 网关需要认证,请自行包含 `--token`。 +当你显式传入 `--url` 时,CLI 不会自动应用配置或环境变量中的凭证;如果目标 Gateway 网关需要认证,请自行附带 `--token`。 -在 JSON 模式下,CLI 会输出带有 `type` 标记的对象: +在 JSON 模式下,CLI 会输出带有 `type` 标签的对象: - `meta`:流元数据(文件、游标、大小) - `log`:已解析的日志条目 - `notice`:截断 / 轮转提示 - `raw`:未解析的日志行 -如果 local loopback Gateway 网关请求配对,`openclaw logs` 会自动回退到已配置的本地日志文件。显式 `--url` 目标不会使用此回退机制。 +如果本地 local loopback Gateway 网关请求配对,`openclaw logs` 会自动回退到已配置的本地日志文件。显式 `--url` 目标不会使用此回退机制。 -如果无法连接到 Gateway 网关,CLI 会打印一个简短提示,建议运行: +如果 Gateway 网关不可达,CLI 会输出一条简短提示,建议运行: ```bash openclaw doctor @@ -84,8 +84,7 @@ openclaw doctor ### Control UI(网页) -Control UI 的 **Logs** 标签页会使用 `logs.tail` 尾随同一个文件。 -有关如何打开它,请参见 [/web/control-ui](/zh-CN/web/control-ui)。 +Control UI 的**日志**标签页会使用 `logs.tail` 尾随同一个文件。有关如何打开它,请参阅 [/web/control-ui](/zh-CN/web/control-ui)。 ### 仅渠道日志 @@ -101,33 +100,33 @@ openclaw channels logs --channel whatsapp 日志文件中的每一行都是一个 JSON 对象。CLI 和 Control UI 会解析这些条目,以渲染结构化输出(时间、级别、子系统、消息)。 -文件日志的 JSONL 记录在可用时还包含可供机器过滤的顶层字段: +文件日志的 JSONL 记录在可用时还包含便于机器过滤的顶级字段: - `hostname`:gateway 主机名。 -- `message`:扁平化的日志消息文本,用于全文搜索。 +- `message`:扁平化的日志消息文本,用于全文检索。 - `agent_id`:当日志调用携带智能体上下文时的活动智能体 id。 - `session_id`:当日志调用携带会话上下文时的活动会话 id/key。 - `channel`:当日志调用携带渠道上下文时的活动渠道。 -OpenClaw 会保留这些字段旁边原始的结构化日志参数,因此现有的解析器如果读取带编号的 tslog 参数键,仍然可以继续工作。 +OpenClaw 会在保留这些字段的同时保留原始结构化日志参数,因此现有读取带编号 `tslog` 参数键的解析器仍然可以正常工作。 ### 控制台输出 -控制台日志会**感知 TTY**,并为可读性进行格式化: +控制台日志**会感知 TTY**,并针对可读性进行格式化: - 子系统前缀(例如 `gateway/channels/whatsapp`) - 级别着色(info/warn/error) -- 可选的紧凑模式或 JSON 模式 +- 可选的紧凑或 JSON 模式 控制台格式由 `logging.consoleStyle` 控制。 -### Gateway WebSocket 日志 +### Gateway 网关 WebSocket 日志 -`openclaw gateway` 也提供用于 RPC 流量的 WebSocket 协议日志: +`openclaw gateway` 还提供用于 RPC 流量的 WebSocket 协议日志: - 普通模式:仅记录重要结果(错误、解析错误、慢调用) -- `--verbose`:所有请求/响应流量 -- `--ws-log auto|compact|full`:选择详细日志的渲染样式 +- `--verbose`:记录所有请求/响应流量 +- `--ws-log auto|compact|full`:选择详细渲染样式 - `--compact`:`--ws-log compact` 的别名 示例: @@ -158,58 +157,58 @@ openclaw gateway --verbose --ws-log full ### 日志级别 - `logging.level`:**文件日志**(JSONL)级别。 -- `logging.consoleLevel`:**控制台**详细程度级别。 +- `logging.consoleLevel`:**控制台**详细级别。 -你可以通过 **`OPENCLAW_LOG_LEVEL`** 环境变量覆盖这两个设置(例如 `OPENCLAW_LOG_LEVEL=debug`)。该环境变量优先于配置文件,因此你可以在不编辑 `openclaw.json` 的情况下,仅对单次运行提高详细程度。你也可以传递全局 CLI 选项 **`--log-level `**(例如 `openclaw --log-level debug gateway run`),它会在该命令中覆盖环境变量。 +你可以通过 **`OPENCLAW_LOG_LEVEL`** 环境变量覆盖这两个设置(例如 `OPENCLAW_LOG_LEVEL=debug`)。该环境变量优先于配置文件,因此你可以在不编辑 `openclaw.json` 的情况下,仅针对单次运行提高详细程度。你还可以传入全局 CLI 选项 **`--log-level `**(例如 `openclaw --log-level debug gateway run`),它会在该命令中覆盖环境变量。 `--verbose` 仅影响控制台输出和 WS 日志详细程度;它不会更改文件日志级别。 ### 跟踪关联 -文件日志采用 JSONL 格式。当一次日志调用携带有效的诊断跟踪上下文时,OpenClaw 会将跟踪字段写为顶层 JSON 键(`traceId`、`spanId`、`parentSpanId`、`traceFlags`),这样外部日志处理器就可以将该行与 OTEL spans 以及提供商 `traceparent` 传播关联起来。 +文件日志采用 JSONL 格式。当一次日志调用携带有效的诊断跟踪上下文时,OpenClaw 会将跟踪字段写为顶级 JSON 键(`traceId`、`spanId`、`parentSpanId`、`traceFlags`),以便外部日志处理器将该行与 OTEL span 以及提供商的 `traceparent` 传播关联起来。 -Gateway 网关 HTTP 请求和 Gateway 网关 WebSocket 帧会建立内部请求跟踪作用域。在该异步作用域内发出的日志和诊断事件,如果没有传入显式跟踪上下文,就会继承请求跟踪。智能体运行和模型调用跟踪会成为活动请求跟踪的子级,因此本地日志、诊断快照、OTEL spans,以及受信任提供商的 `traceparent` 请求头都可以通过 `traceId` 关联起来,而无需记录原始请求或模型内容。 +Gateway 网关 HTTP 请求和 Gateway 网关 WebSocket 帧会建立内部请求跟踪作用域。在该异步作用域内发出的日志和诊断事件,如果未显式传入跟踪上下文,就会继承该请求跟踪。智能体运行和模型调用跟踪会成为当前请求跟踪的子级,因此本地日志、诊断快照、OTEL span 以及受信任提供商的 `traceparent` 标头都可以通过 `traceId` 关联,而无需记录原始请求或模型内容。 -### 模型调用大小和时序 +### 模型调用大小与耗时 -模型调用诊断会记录有边界的请求/响应测量数据,而不会捕获原始提示词或响应内容: +模型调用诊断会记录有界的请求/响应测量值,而不会捕获原始提示词或响应内容: - `requestPayloadBytes`:最终模型请求载荷的 UTF-8 字节大小 - `responseStreamBytes`:流式模型响应事件的 UTF-8 字节大小 - `timeToFirstByteMs`:收到第一个流式响应事件前的耗时 - `durationMs`:模型调用总时长 -启用诊断导出后,这些字段可用于诊断快照、模型调用插件钩子,以及 OTEL 模型调用 spans/metrics。 +启用诊断导出时,这些字段可用于诊断快照、模型调用插件钩子以及 OTEL 模型调用 span/指标。 ### 控制台样式 `logging.consoleStyle`: -- `pretty`:适合人工阅读,带颜色和时间戳。 +- `pretty`:适合人类阅读,带颜色并包含时间戳。 - `compact`:更紧凑的输出(最适合长时间会话)。 -- `json`:每行一个 JSON(供日志处理器使用)。 +- `json`:每行一个 JSON(适用于日志处理器)。 -### 脱敏处理 +### 脱敏 -OpenClaw 可以在敏感令牌进入控制台输出、文件日志、OTLP 日志记录或持久化的会话转录文本之前进行脱敏: +OpenClaw 可以在敏感令牌进入控制台输出、文件日志、OTLP 日志记录、持久化的会话转录文本或 Control UI 工具事件载荷(工具启动参数、部分/最终结果载荷、派生的执行输出和补丁摘要)之前对其进行脱敏: - `logging.redactSensitive`:`off` | `tools`(默认:`tools`) -- `logging.redactPatterns`:用于覆盖默认集合的正则表达式字符串列表 +- `logging.redactPatterns`:用于覆盖默认集合的正则字符串列表。自定义模式会叠加到 Control UI 工具载荷的内置默认模式之上,因此添加模式绝不会削弱对那些已被默认规则捕获值的脱敏效果。 -文件日志和会话转录仍保持为 JSONL,但匹配到的敏感值会在该行或消息写入磁盘之前被掩码处理。脱敏处理是尽力而为的:它适用于携带文本的消息内容和日志字符串,但不适用于每个标识符或二进制载荷字段。 +文件日志和会话转录仍然保持 JSONL 格式,但在将行或消息写入磁盘之前,匹配的密钥值会被掩码处理。脱敏是尽力而为的:它适用于承载文本的消息内容和日志字符串,而不是每一个标识符或二进制载荷字段。 -## Diagnostics 和 OpenTelemetry +## 诊断与 OpenTelemetry -Diagnostics 是用于模型运行和消息流遥测(webhooks、排队、会话状态)的结构化、机器可读事件。它们**不会**替代日志——而是为指标、跟踪和导出器提供输入。无论你是否导出它们,这些事件都会在进程内发出。 +诊断是针对模型运行和消息流遥测(webhook、排队、会话状态)的结构化、机器可读事件。它们**不会**替代日志——而是为指标、跟踪和导出器提供数据。无论你是否导出,这些事件都会在进程内发出。 -两个相邻的界面: +相邻的两个展示面: -- **OpenTelemetry 导出** —— 通过 OTLP/HTTP 将指标、跟踪和日志发送到任何兼容 OpenTelemetry 的收集器或后端(Grafana、Datadog、Honeycomb、New Relic、Tempo 等)。完整配置、信号目录、指标/span 名称、环境变量以及隐私模型位于专门页面中: - [OpenTelemetry export](/zh-CN/gateway/opentelemetry)。 -- **Diagnostics 标志** —— 将额外日志定向到 `logging.file` 的定向调试日志标志,而无需提高 `logging.level`。这些标志不区分大小写,并支持通配符(`telegram.*`、`*`)。可在 `diagnostics.flags` 下配置,或通过 `OPENCLAW_DIAGNOSTICS=...` 环境变量覆盖。完整指南: - [Diagnostics flags](/zh-CN/diagnostics/flags)。 +- **OpenTelemetry 导出**——通过 OTLP/HTTP 将指标、跟踪和日志发送到任何兼容 OpenTelemetry 的收集器或后端(Grafana、Datadog、Honeycomb、New Relic、Tempo 等)。完整配置、信号目录、指标 / span 名称、环境变量以及隐私模型位于专门页面中: + [OpenTelemetry 导出](/zh-CN/gateway/opentelemetry)。 +- **诊断标志**——将额外日志定向写入 `logging.file` 的定向调试日志标志,而无需提高 `logging.level`。标志不区分大小写,并支持通配符(`telegram.*`、`*`)。可在 `diagnostics.flags` 下配置,或通过 `OPENCLAW_DIAGNOSTICS=...` 环境变量覆盖。完整指南: + [诊断标志](/zh-CN/diagnostics/flags)。 -要在不启用 OTLP 导出的情况下,为插件或自定义接收端启用 Diagnostics 事件: +要在不启用 OTLP 导出的情况下,为插件或自定义接收端启用诊断事件: ```json5 { @@ -217,17 +216,17 @@ Diagnostics 是用于模型运行和消息流遥测(webhooks、排队、会话 } ``` -有关导出到收集器的 OTLP 配置,请参见 [OpenTelemetry export](/zh-CN/gateway/opentelemetry)。 +如需将 OTLP 导出到收集器,请参阅 [OpenTelemetry 导出](/zh-CN/gateway/opentelemetry)。 ## 故障排除提示 -- **无法连接到 Gateway 网关?** 先运行 `openclaw doctor`。 -- **日志为空?** 检查 Gateway 网关是否正在运行,并且正在写入 `logging.file` 中的文件路径。 -- **需要更多细节?** 将 `logging.level` 设置为 `debug` 或 `trace` 后重试。 +- **Gateway 网关无法访问?** 先运行 `openclaw doctor`。 +- **日志为空?** 检查 Gateway 网关是否正在运行,并且是否正在向 `logging.file` 中的文件路径写入。 +- **需要更多细节?** 将 `logging.level` 设为 `debug` 或 `trace` 后重试。 ## 相关内容 -- [OpenTelemetry export](/zh-CN/gateway/opentelemetry) — OTLP/HTTP 导出、指标/span 目录、隐私模型 -- [Diagnostics flags](/zh-CN/diagnostics/flags) — 定向调试日志标志 -- [Gateway logging internals](/zh-CN/gateway/logging) — WS 日志样式、子系统前缀和控制台捕获 -- [Configuration reference](/zh-CN/gateway/configuration-reference#diagnostics) — 完整的 `diagnostics.*` 字段参考 +- [OpenTelemetry 导出](/zh-CN/gateway/opentelemetry) — OTLP/HTTP 导出、指标 / span 目录、隐私模型 +- [诊断标志](/zh-CN/diagnostics/flags) — 定向调试日志标志 +- [Gateway 网关日志内部机制](/zh-CN/gateway/logging) — WS 日志样式、子系统前缀和控制台捕获 +- [配置参考](/zh-CN/gateway/configuration-reference#diagnostics) — 完整的 `diagnostics.*` 字段参考 diff --git a/docs/zh-CN/plugins/sdk-subpaths.md b/docs/zh-CN/plugins/sdk-subpaths.md index 644667d8d..ea61dc8a2 100644 --- a/docs/zh-CN/plugins/sdk-subpaths.md +++ b/docs/zh-CN/plugins/sdk-subpaths.md @@ -1,34 +1,34 @@ --- read_when: - - 为插件导入选择合适的 plugin-sdk 子路径 - - 审查 bundled-plugin 子路径和辅助接口 + - 为插件导入选择正确的 plugin-sdk 子路径 + - 审计 bundled-plugin 子路径和辅助接口 summary: 插件 SDK 子路径目录:按领域分组,哪些导入位于哪里 title: 插件 SDK 子路径 x-i18n: - generated_at: "2026-04-27T22:22:33Z" + generated_at: "2026-04-27T22:50:25Z" model: gpt-5.4 provider: openai - source_hash: 56f76f2371500ab77dc791ba862cb628daec596059f1f9def7227fecb2826347 + source_hash: cbe2016ada89a5738f9786cd3c31091ea7cddc3131f13e949b63cee228b44913 source_path: plugins/sdk-subpaths.md workflow: 15 --- - 插件 SDK 以 `openclaw/plugin-sdk/` 下的一组窄子路径形式对外暴露。 - 本页按用途分组,汇总常用子路径。生成的完整列表包含 200 多个子路径,位于 `scripts/lib/plugin-sdk-entrypoints.json`; - 其中也会列出保留的 bundled-plugin 辅助子路径,但除非某个文档页面明确将其作为公开能力介绍,否则它们都属于实现细节。 + 插件 SDK 通过 `openclaw/plugin-sdk/` 下的一组精简子路径对外公开。 + 本页按用途对常用子路径进行归类整理。完整的 200+ 子路径生成列表位于 `scripts/lib/plugin-sdk-entrypoints.json`; + 其中也包含保留的 bundled-plugin 辅助子路径,但除非某个文档页面明确将其作为公开能力介绍,否则它们都属于实现细节。 - 关于插件编写指南,参见 [插件 SDK 概览](/zh-CN/plugins/sdk-overview)。 + 关于插件编写指南,请参阅 [插件 SDK 概览](/zh-CN/plugins/sdk-overview)。 ## 插件入口 - | 子路径 | 关键导出 | + | 子路径 | 关键导出 | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `plugin-sdk/plugin-entry` | `definePluginEntry` | | `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` | | `plugin-sdk/config-schema` | `OpenClawSchema` | | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | - | `plugin-sdk/migration` | 迁移提供商条目辅助函数,例如 `createMigrationItem`、原因常量、条目状态标记、脱敏辅助函数,以及 `summarizeMigrationItems` | - | `plugin-sdk/migration-runtime` | 运行时迁移辅助函数,例如 `copyMigrationFileItem` 和 `writeMigrationReport` | + | `plugin-sdk/migration` | 迁移提供商条目辅助工具,例如 `createMigrationItem`、原因常量、条目状态标记、脱敏辅助工具,以及 `summarizeMigrationItems` | + | `plugin-sdk/migration-runtime` | 运行时迁移辅助工具,例如 `copyMigrationFileItem` 和 `writeMigrationReport` | @@ -37,205 +37,205 @@ x-i18n: | `plugin-sdk/channel-core` | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | | `plugin-sdk/config-schema` | 根级 `openclaw.json` Zod schema 导出(`OpenClawSchema`) | | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`, `createOptionalChannelSetupWizard`,以及 `DEFAULT_ACCOUNT_ID`, `createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, `splitSetupEntries` | - | `plugin-sdk/setup` | 共享设置向导辅助函数、allowlist 提示、设置状态构建器 | + | `plugin-sdk/setup` | 共享设置向导辅助工具、允许列表提示、设置状态构建器 | | `plugin-sdk/setup-runtime` | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | | `plugin-sdk/setup-adapter-runtime` | `createEnvPatchedAccountSetupAdapter` | | `plugin-sdk/setup-tools` | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | - | `plugin-sdk/account-core` | 多账户配置 / 动作门控辅助函数,默认账户回退辅助函数 | - | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`,账户 ID 规范化辅助函数 | - | `plugin-sdk/account-resolution` | 账户查找 + 默认回退辅助函数 | - | `plugin-sdk/account-helpers` | 窄范围的账户列表 / 账户操作辅助函数 | + | `plugin-sdk/account-core` | 多账户配置 / 操作门控辅助工具,以及默认账户回退辅助工具 | + | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`,账户 ID 规范化辅助工具 | + | `plugin-sdk/account-resolution` | 账户查找 + 默认值回退辅助工具 | + | `plugin-sdk/account-helpers` | 精简的账户列表 / 账户操作辅助工具 | | `plugin-sdk/channel-pairing` | `createChannelPairingController` | | `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` | | `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` | | `plugin-sdk/channel-config-schema` | 共享渠道配置 schema 原语和通用构建器 | - | `plugin-sdk/channel-config-schema-legacy` | 已弃用的 bundled-channel 配置 schema,仅用于保持内置兼容性 | - | `plugin-sdk/telegram-command-config` | Telegram 自定义命令规范化 / 校验辅助函数,并带有 bundled 合同回退 | - | `plugin-sdk/command-gating` | 窄范围命令授权门控辅助函数 | + | `plugin-sdk/channel-config-schema-legacy` | 已弃用的 bundled-channel 配置 schema,仅为保持内置兼容性而保留 | + | `plugin-sdk/telegram-command-config` | Telegram 自定义命令规范化 / 校验辅助工具,带有 bundled contract 回退 | + | `plugin-sdk/command-gating` | 精简的命令授权门控辅助工具 | | `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` | - | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink`,草稿流生命周期 / 收尾辅助函数 | - | `plugin-sdk/inbound-envelope` | 共享入站路由 + envelope 构建辅助函数 | - | `plugin-sdk/inbound-reply-dispatch` | 共享入站记录与派发辅助函数 | - | `plugin-sdk/messaging-targets` | 目标解析 / 匹配辅助函数 | - | `plugin-sdk/outbound-media` | 共享出站媒体加载辅助函数 | + | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink`、草稿流生命周期 / 收尾辅助工具 | + | `plugin-sdk/inbound-envelope` | 共享入站路由 + envelope 构建辅助工具 | + | `plugin-sdk/inbound-reply-dispatch` | 共享入站记录与分发辅助工具 | + | `plugin-sdk/messaging-targets` | 目标解析 / 匹配辅助工具 | + | `plugin-sdk/outbound-media` | 共享出站媒体加载辅助工具 | | `plugin-sdk/outbound-send-deps` | 面向渠道适配器的轻量级出站发送依赖查找 | - | `plugin-sdk/outbound-runtime` | 出站投递、身份、发送委托、会话、格式化和载荷规划辅助函数 | - | `plugin-sdk/poll-runtime` | 窄范围投票规范化辅助函数 | - | `plugin-sdk/thread-bindings-runtime` | 线程绑定生命周期和适配器辅助函数 | - | `plugin-sdk/agent-media-payload` | 旧版智能体媒体载荷构建器 | - | `plugin-sdk/conversation-runtime` | 会话 / 线程绑定、配对和已配置绑定辅助函数 | - | `plugin-sdk/runtime-config-snapshot` | 运行时配置快照辅助函数 | - | `plugin-sdk/runtime-group-policy` | 运行时群组策略解析辅助函数 | - | `plugin-sdk/channel-status` | 共享渠道 Status 快照 / 摘要辅助函数 | - | `plugin-sdk/channel-config-primitives` | 窄范围渠道配置 schema 原语 | - | `plugin-sdk/channel-config-writes` | 渠道配置写入授权辅助函数 | + | `plugin-sdk/outbound-runtime` | 出站投递、身份、发送委托、会话、格式化和负载规划辅助工具 | + | `plugin-sdk/poll-runtime` | 精简的投票规范化辅助工具 | + | `plugin-sdk/thread-bindings-runtime` | 线程绑定生命周期和适配器辅助工具 | + | `plugin-sdk/agent-media-payload` | 旧版智能体媒体负载构建器 | + | `plugin-sdk/conversation-runtime` | 会话 / 线程绑定、配对和已配置绑定辅助工具 | + | `plugin-sdk/runtime-config-snapshot` | 运行时配置快照辅助工具 | + | `plugin-sdk/runtime-group-policy` | 运行时群组策略解析辅助工具 | + | `plugin-sdk/channel-status` | 共享渠道 Status 快照 / 摘要辅助工具 | + | `plugin-sdk/channel-config-primitives` | 精简的渠道配置 schema 原语 | + | `plugin-sdk/channel-config-writes` | 渠道配置写入授权辅助工具 | | `plugin-sdk/channel-plugin-common` | 共享渠道插件前导导出 | - | `plugin-sdk/allowlist-config-edit` | allowlist 配置编辑 / 读取辅助函数 | - | `plugin-sdk/group-access` | 共享群组访问决策辅助函数 | - | `plugin-sdk/direct-dm` | 共享直接私信授权 / 守卫辅助函数 | - | `plugin-sdk/interactive-runtime` | 语义化消息呈现、投递和旧版交互式回复辅助函数。参见 [消息呈现](/zh-CN/plugins/message-presentation) | - | `plugin-sdk/channel-inbound` | 面向入站去抖动、提及匹配、提及策略辅助函数和 envelope 辅助函数的兼容性 barrel | - | `plugin-sdk/channel-inbound-debounce` | 窄范围入站去抖动辅助函数 | - | `plugin-sdk/channel-mention-gating` | 窄范围提及策略、提及标记和提及文本辅助函数,不包含更广泛的入站运行时接口 | - | `plugin-sdk/channel-envelope` | 窄范围入站 envelope 格式化辅助函数 | - | `plugin-sdk/channel-location` | 渠道位置上下文和格式化辅助函数 | - | `plugin-sdk/channel-logging` | 用于入站丢弃及输入中 / 确认失败的渠道日志辅助函数 | + | `plugin-sdk/allowlist-config-edit` | 允许列表配置编辑 / 读取辅助工具 | + | `plugin-sdk/group-access` | 共享群组访问决策辅助工具 | + | `plugin-sdk/direct-dm` | 共享直接私信认证 / 保护辅助工具 | + | `plugin-sdk/interactive-runtime` | 语义消息呈现、投递和旧版交互式回复辅助工具。请参阅 [消息呈现](/zh-CN/plugins/message-presentation) | + | `plugin-sdk/channel-inbound` | 兼容性 barrel,包含入站去抖动、提及匹配、提及策略辅助工具和 envelope 辅助工具 | + | `plugin-sdk/channel-inbound-debounce` | 精简的入站去抖动辅助工具 | + | `plugin-sdk/channel-mention-gating` | 精简的提及策略、提及标记和提及文本辅助工具,不包含更宽泛的入站运行时接口 | + | `plugin-sdk/channel-envelope` | 精简的入站 envelope 格式化辅助工具 | + | `plugin-sdk/channel-location` | 渠道位置上下文和格式化辅助工具 | + | `plugin-sdk/channel-logging` | 用于入站丢弃和 typing / ack 失败的渠道日志辅助工具 | | `plugin-sdk/channel-send-result` | 回复结果类型 | - | `plugin-sdk/channel-actions` | 渠道消息操作辅助函数,以及为保持插件兼容性而保留的已弃用原生 schema 辅助函数 | - | `plugin-sdk/channel-targets` | 目标解析 / 匹配辅助函数 | - | `plugin-sdk/channel-contract` | 渠道合同类型 | - | `plugin-sdk/channel-feedback` | 反馈 / 反应接线 | - | `plugin-sdk/channel-secret-runtime` | 窄范围密钥合同辅助函数,例如 `collectSimpleChannelFieldAssignments`、`getChannelSurface`、`pushAssignment` 和密钥目标类型 | + | `plugin-sdk/channel-actions` | 渠道消息操作辅助工具,以及为插件兼容性保留的已弃用原生 schema 辅助工具 | + | `plugin-sdk/channel-targets` | 目标解析 / 匹配辅助工具 | + | `plugin-sdk/channel-contract` | 渠道 contract 类型 | + | `plugin-sdk/channel-feedback` | 反馈 / reaction 接线 | + | `plugin-sdk/channel-secret-runtime` | 精简的 secret contract 辅助工具,例如 `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment`,以及 secret target 类型 | | 子路径 | 关键导出 | | --- | --- | | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | - | `plugin-sdk/lmstudio` | 受支持的 LM Studio 提供商外观层,用于设置、目录发现和运行时模型准备 | - | `plugin-sdk/lmstudio-runtime` | 受支持的 LM Studio 运行时外观层,用于本地服务器默认值、模型发现、请求头和已加载模型辅助函数 | - | `plugin-sdk/provider-setup` | 精选的本地 / 自托管提供商设置辅助函数 | - | `plugin-sdk/self-hosted-provider-setup` | 面向 OpenAI 兼容自托管提供商的专用设置辅助函数 | + | `plugin-sdk/lmstudio` | 受支持的 LM Studio 提供商门面,用于设置、目录发现和运行时模型准备 | + | `plugin-sdk/lmstudio-runtime` | 受支持的 LM Studio 运行时门面,用于本地服务器默认值、模型发现、请求头和已加载模型辅助工具 | + | `plugin-sdk/provider-setup` | 精选的本地 / 自托管提供商设置辅助工具 | + | `plugin-sdk/self-hosted-provider-setup` | 专用于兼容 OpenAI 的自托管提供商设置辅助工具 | | `plugin-sdk/cli-backend` | CLI 后端默认值 + watchdog 常量 | - | `plugin-sdk/provider-auth-runtime` | 面向提供商插件的运行时 API 密钥解析辅助函数 | - | `plugin-sdk/provider-auth-api-key` | API 密钥新手引导 / 配置文件写入辅助函数,例如 `upsertApiKeyProfile` | - | `plugin-sdk/provider-auth-result` | 标准 OAuth 认证结果构建器 | - | `plugin-sdk/provider-auth-login` | 面向提供商插件的共享交互式登录辅助函数 | - | `plugin-sdk/provider-env-vars` | 提供商认证环境变量查找辅助函数 | + | `plugin-sdk/provider-auth-runtime` | 面向提供商插件的运行时 API key 解析辅助工具 | + | `plugin-sdk/provider-auth-api-key` | API key 新手引导 / 配置档写入辅助工具,例如 `upsertApiKeyProfile` | + | `plugin-sdk/provider-auth-result` | 标准 OAuth auth-result 构建器 | + | `plugin-sdk/provider-auth-login` | 面向提供商插件的共享交互式登录辅助工具 | + | `plugin-sdk/provider-env-vars` | 提供商认证环境变量查找辅助工具 | | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile`, `upsertApiKeyProfile`, `writeOAuthCredentials` | - | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`,共享 replay-policy 构建器、提供商端点辅助函数,以及模型 ID 规范化辅助函数,例如 `normalizeNativeXaiModelId` | - | `plugin-sdk/provider-catalog-runtime` | 提供商目录运行时钩子和插件提供商注册表接口,用于合同测试 | + | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`、共享 replay-policy 构建器、provider-endpoint 辅助工具,以及诸如 `normalizeNativeXaiModelId` 之类的 model-id 规范化辅助工具 | + | `plugin-sdk/provider-catalog-runtime` | 用于 contract 测试的提供商目录运行时钩子和 plugin-provider registry 接缝 | | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | - | `plugin-sdk/provider-http` | 通用提供商 HTTP / 端点能力辅助函数、提供商 HTTP 错误,以及音频转录 multipart form 辅助函数 | - | `plugin-sdk/provider-web-fetch-contract` | 窄范围 web-fetch 配置 / 选择合同辅助函数,例如 `enablePluginInConfig` 和 `WebFetchProviderPlugin` | - | `plugin-sdk/provider-web-fetch` | web-fetch 提供商注册 / 缓存辅助函数 | - | `plugin-sdk/provider-web-search-config-contract` | 面向无需插件启用接线的提供商的窄范围 web-search 配置 / 凭证辅助函数 | - | `plugin-sdk/provider-web-search-contract` | 窄范围 web-search 配置 / 凭证合同辅助函数,例如 `createWebSearchProviderContractFields`、`enablePluginInConfig`、`resolveProviderWebSearchPluginConfig`,以及带作用域的凭证设置器 / 读取器 | - | `plugin-sdk/provider-web-search` | web-search 提供商注册 / 缓存 / 运行时辅助函数 | - | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`,Gemini schema 清理 + 诊断,以及 xAI 兼容性辅助函数,例如 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` | - | `plugin-sdk/provider-usage` | `fetchClaudeUsage` 及类似函数 | - | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`、流包装器类型,以及共享的 Anthropic / Bedrock / DeepSeek V4 / Google / Kilocode / Moonshot / OpenAI / OpenRouter / Z.A.I / MiniMax / Copilot 包装器辅助函数 | - | `plugin-sdk/provider-transport-runtime` | 原生提供商传输辅助函数,例如受保护的 fetch、传输消息转换和可写传输事件流 | - | `plugin-sdk/provider-onboard` | 新手引导配置补丁辅助函数 | - | `plugin-sdk/global-singleton` | 进程内 singleton / map / cache 辅助函数 | - | `plugin-sdk/group-activation` | 窄范围群组激活模式和命令解析辅助函数 | + | `plugin-sdk/provider-http` | 通用提供商 HTTP / endpoint 能力辅助工具、提供商 HTTP 错误,以及音频转录 multipart form 辅助工具 | + | `plugin-sdk/provider-web-fetch-contract` | 精简的 web-fetch 配置 / 选择 contract 辅助工具,例如 `enablePluginInConfig` 和 `WebFetchProviderPlugin` | + | `plugin-sdk/provider-web-fetch` | web-fetch 提供商注册 / 缓存辅助工具 | + | `plugin-sdk/provider-web-search-config-contract` | 面向无需插件启用接线的提供商的精简 web-search 配置 / 凭证辅助工具 | + | `plugin-sdk/provider-web-search-contract` | 精简的 web-search 配置 / 凭证 contract 辅助工具,例如 `createWebSearchProviderContractFields`, `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`,以及作用域化凭证 setter / getter | + | `plugin-sdk/provider-web-search` | web-search 提供商注册 / 缓存 / 运行时辅助工具 | + | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`、Gemini schema 清理 + 诊断,以及诸如 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` 之类的 xAI 兼容辅助工具 | + | `plugin-sdk/provider-usage` | `fetchClaudeUsage` 及类似导出 | + | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`、流包装器类型,以及共享的 Anthropic / Bedrock / DeepSeek V4 / Google / Kilocode / Moonshot / OpenAI / OpenRouter / Z.A.I / MiniMax / Copilot 包装器辅助工具 | + | `plugin-sdk/provider-transport-runtime` | 原生提供商传输辅助工具,例如受保护的 fetch、传输消息转换和可写传输事件流 | + | `plugin-sdk/provider-onboard` | 新手引导配置补丁辅助工具 | + | `plugin-sdk/global-singleton` | 进程本地 singleton / map / cache 辅助工具 | + | `plugin-sdk/group-activation` | 精简的群组激活模式和命令解析辅助工具 | | 子路径 | 关键导出 | | --- | --- | - | `plugin-sdk/command-auth` | `resolveControlCommandGate`、命令注册表辅助函数(包括动态参数菜单格式化)、发送者授权辅助函数 | + | `plugin-sdk/command-auth` | `resolveControlCommandGate`、命令注册表辅助工具(包括动态参数菜单格式化)、发送者授权辅助工具 | | `plugin-sdk/command-status` | 命令 / 帮助消息构建器,例如 `buildCommandsMessagePaginated` 和 `buildHelpMessage` | - | `plugin-sdk/approval-auth-runtime` | 审批人解析和同一聊天中的操作认证辅助函数 | - | `plugin-sdk/approval-client-runtime` | 原生 exec 审批配置文件 / 过滤器辅助函数 | + | `plugin-sdk/approval-auth-runtime` | 审批人解析和同一聊天中的操作认证辅助工具 | + | `plugin-sdk/approval-client-runtime` | 原生 exec 审批配置档 / 过滤器辅助工具 | | `plugin-sdk/approval-delivery-runtime` | 原生审批能力 / 投递适配器 | - | `plugin-sdk/approval-gateway-runtime` | 共享审批 Gateway 网关解析辅助函数 | - | `plugin-sdk/approval-handler-adapter-runtime` | 面向热渠道入口点的轻量级原生审批适配器加载辅助函数 | - | `plugin-sdk/approval-handler-runtime` | 范围更广的审批处理器运行时辅助函数;如果更窄的 adapter / gateway 接口已经足够,优先使用它们 | - | `plugin-sdk/approval-native-runtime` | 原生审批目标 + 账户绑定辅助函数 | - | `plugin-sdk/approval-reply-runtime` | exec / 插件审批回复载荷辅助函数 | - | `plugin-sdk/approval-runtime` | exec / 插件审批载荷辅助函数、原生审批路由 / 运行时辅助函数,以及结构化审批显示辅助函数,例如 `formatApprovalDisplayPath` | - | `plugin-sdk/reply-dedupe` | 窄范围入站回复去重重置辅助函数 | - | `plugin-sdk/channel-contract-testing` | 不含广泛测试 barrel 的窄范围渠道合同测试辅助函数 | - | `plugin-sdk/command-auth-native` | 原生命令认证、动态参数菜单格式化和原生会话目标辅助函数 | - | `plugin-sdk/command-detection` | 共享命令检测辅助函数 | - | `plugin-sdk/command-primitives-runtime` | 面向热渠道路径的轻量级命令文本谓词 | - | `plugin-sdk/command-surface` | 命令体规范化和命令接口辅助函数 | + | `plugin-sdk/approval-gateway-runtime` | 共享审批 Gateway 网关解析辅助工具 | + | `plugin-sdk/approval-handler-adapter-runtime` | 面向高频渠道入口点的轻量级原生审批适配器加载辅助工具 | + | `plugin-sdk/approval-handler-runtime` | 范围更广的审批处理器运行时辅助工具;如果更精简的 adapter / gateway 接缝已足够,优先使用它们 | + | `plugin-sdk/approval-native-runtime` | 原生审批目标 + 账户绑定辅助工具 | + | `plugin-sdk/approval-reply-runtime` | exec / 插件审批回复负载辅助工具 | + | `plugin-sdk/approval-runtime` | exec / 插件审批负载辅助工具、原生审批路由 / 运行时辅助工具,以及诸如 `formatApprovalDisplayPath` 之类的结构化审批展示辅助工具 | + | `plugin-sdk/reply-dedupe` | 精简的入站回复去重重置辅助工具 | + | `plugin-sdk/channel-contract-testing` | 精简的渠道 contract 测试辅助工具,不包含宽泛的测试 barrel | + | `plugin-sdk/command-auth-native` | 原生命令认证、动态参数菜单格式化和原生会话目标辅助工具 | + | `plugin-sdk/command-detection` | 共享命令检测辅助工具 | + | `plugin-sdk/command-primitives-runtime` | 面向高频渠道路径的轻量级命令文本判定辅助工具 | + | `plugin-sdk/command-surface` | 命令体规范化和命令接口辅助工具 | | `plugin-sdk/allow-from` | `formatAllowFromLowercase` | - | `plugin-sdk/channel-secret-runtime` | 面向渠道 / 插件密钥接口的窄范围密钥合同收集辅助函数 | - | `plugin-sdk/secret-ref-runtime` | 面向密钥合同 / 配置解析的窄范围 `coerceSecretRef` 和 `SecretRef` 类型辅助函数 | - | `plugin-sdk/security-runtime` | 共享信任、私信门控、外部内容、敏感文本脱敏、常量时间密钥比较和密钥收集辅助函数 | - | `plugin-sdk/ssrf-policy` | 主机 allowlist 和私有网络 SSRF 策略辅助函数 | - | `plugin-sdk/ssrf-dispatcher` | 不含广泛基础设施运行时接口的窄范围 pinned-dispatcher 辅助函数 | - | `plugin-sdk/ssrf-runtime` | pinned-dispatcher、受 SSRF 保护的 fetch、SSRF 错误和 SSRF 策略辅助函数 | - | `plugin-sdk/secret-input` | 密钥输入解析辅助函数 | - | `plugin-sdk/webhook-ingress` | webhook 请求 / 目标辅助函数,以及原始 websocket / body 强制转换 | - | `plugin-sdk/webhook-request-guards` | 请求体大小 / 超时辅助函数 | + | `plugin-sdk/channel-secret-runtime` | 面向渠道 / 插件 secret 接口的精简 secret contract 收集辅助工具 | + | `plugin-sdk/secret-ref-runtime` | 精简的 `coerceSecretRef` 和 SecretRef 类型辅助工具,用于 secret contract / 配置解析 | + | `plugin-sdk/security-runtime` | 共享 trust、私信门控、外部内容、敏感文本脱敏、常量时间 secret 比较和 secret 收集辅助工具 | + | `plugin-sdk/ssrf-policy` | 主机允许列表和私有网络 SSRF 策略辅助工具 | + | `plugin-sdk/ssrf-dispatcher` | 精简的 pinned-dispatcher 辅助工具,不包含宽泛的基础设施运行时接口 | + | `plugin-sdk/ssrf-runtime` | pinned-dispatcher、受 SSRF 保护的 fetch、SSRF 错误和 SSRF 策略辅助工具 | + | `plugin-sdk/secret-input` | secret 输入解析辅助工具 | + | `plugin-sdk/webhook-ingress` | webhook 请求 / 目标辅助工具,以及原始 websocket / 请求体强制转换 | + | `plugin-sdk/webhook-request-guards` | 请求体大小 / 超时辅助工具 | | 子路径 | 关键导出 | | --- | --- | - | `plugin-sdk/runtime` | 范围广泛的运行时 / 日志 / 备份 / 插件安装辅助函数 | - | `plugin-sdk/runtime-env` | 窄范围运行时环境、logger、超时、重试和退避辅助函数 | - | `plugin-sdk/browser-config` | 受支持的浏览器配置外观层,用于规范化的配置文件 / 默认值、CDP URL 解析和浏览器控制认证辅助函数 | - | `plugin-sdk/channel-runtime-context` | 通用渠道运行时上下文注册和查找辅助函数 | + | `plugin-sdk/runtime` | 范围较广的运行时 / 日志 / 备份 / 插件安装辅助工具 | + | `plugin-sdk/runtime-env` | 精简的运行时环境、日志器、超时、重试和退避辅助工具 | + | `plugin-sdk/browser-config` | 受支持的浏览器配置门面,用于规范化后的配置档 / 默认值、CDP URL 解析和浏览器控制认证辅助工具 | + | `plugin-sdk/channel-runtime-context` | 通用渠道运行时上下文注册和查找辅助工具 | | `plugin-sdk/runtime-store` | `createPluginRuntimeStore` | - | `plugin-sdk/plugin-runtime` | 共享插件命令 / 钩子 / HTTP / 交互式辅助函数 | - | `plugin-sdk/hook-runtime` | 共享 webhook / 内部钩子流水线辅助函数 | - | `plugin-sdk/lazy-runtime` | 惰性运行时导入 / 绑定辅助函数,例如 `createLazyRuntimeModule`、`createLazyRuntimeMethod` 和 `createLazyRuntimeSurface` | - | `plugin-sdk/process-runtime` | 进程 exec 辅助函数 | - | `plugin-sdk/cli-runtime` | CLI 格式化、等待、版本、参数调用和惰性命令组辅助函数 | - | `plugin-sdk/gateway-runtime` | Gateway 网关客户端、Gateway 网关 CLI RPC、Gateway 网关协议错误和渠道 Status 补丁辅助函数 | - | `plugin-sdk/config-types` | 仅类型的配置接口,用于插件配置结构,例如 `OpenClawConfig` 以及渠道 / 提供商配置类型 | - | `plugin-sdk/plugin-config-runtime` | 运行时插件配置查找辅助函数,例如 `requireRuntimeConfig`、`resolvePluginConfigObject` 和 `resolveLivePluginConfigObject` | - | `plugin-sdk/config-mutation` | 事务性配置变更辅助函数,例如 `mutateConfigFile`、`replaceConfigFile` 和 `logConfigUpdated` | - | `plugin-sdk/runtime-config-snapshot` | 当前进程配置快照辅助函数,例如 `getRuntimeConfig`、`getRuntimeConfigSnapshot` 和测试快照设置器 | - | `plugin-sdk/telegram-command-config` | Telegram 命令名称 / 描述规范化,以及重复 / 冲突检查,即使内置 Telegram 合同接口不可用也可使用 | - | `plugin-sdk/text-autolink-runtime` | 不依赖广泛 text-runtime barrel 的文件引用自动链接检测 | - | `plugin-sdk/approval-runtime` | exec / 插件审批辅助函数、审批能力构建器、认证 / 配置文件辅助函数、原生路由 / 运行时辅助函数,以及结构化审批显示路径格式化 | - | `plugin-sdk/reply-runtime` | 共享入站 / 回复运行时辅助函数、分块、派发、heartbeat、回复规划器 | - | `plugin-sdk/reply-dispatch-runtime` | 窄范围回复派发 / 收尾和会话标签辅助函数 | - | `plugin-sdk/reply-history` | 共享短时间窗口回复历史辅助函数和标记,例如 `buildHistoryContext`、`HISTORY_CONTEXT_MARKER`、`recordPendingHistoryEntry` 和 `clearHistoryEntriesIfEnabled` | + | `plugin-sdk/plugin-runtime` | 共享插件命令 / hook / HTTP / 交互式辅助工具 | + | `plugin-sdk/hook-runtime` | 共享 webhook / 内部 hook 流水线辅助工具 | + | `plugin-sdk/lazy-runtime` | 延迟运行时导入 / 绑定辅助工具,例如 `createLazyRuntimeModule`, `createLazyRuntimeMethod` 和 `createLazyRuntimeSurface` | + | `plugin-sdk/process-runtime` | 进程 exec 辅助工具 | + | `plugin-sdk/cli-runtime` | CLI 格式化、等待、版本、参数调用和延迟命令组辅助工具 | + | `plugin-sdk/gateway-runtime` | Gateway 网关客户端、Gateway 网关 CLI RPC、Gateway 网关协议错误和渠道 Status 补丁辅助工具 | + | `plugin-sdk/config-types` | 仅类型的配置接口,用于插件配置形状,例如 `OpenClawConfig` 以及渠道 / 提供商配置类型 | + | `plugin-sdk/plugin-config-runtime` | 运行时插件配置查找辅助工具,例如 `requireRuntimeConfig`, `resolvePluginConfigObject` 和 `resolveLivePluginConfigObject` | + | `plugin-sdk/config-mutation` | 事务性配置变更辅助工具,例如 `mutateConfigFile`, `replaceConfigFile` 和 `logConfigUpdated` | + | `plugin-sdk/runtime-config-snapshot` | 当前进程配置快照辅助工具,例如 `getRuntimeConfig`, `getRuntimeConfigSnapshot` 和测试快照 setter | + | `plugin-sdk/telegram-command-config` | Telegram 命令名称 / 描述规范化以及重复 / 冲突检查,即使内置的 Telegram contract 接口不可用时也适用 | + | `plugin-sdk/text-autolink-runtime` | 文件引用自动链接检测,不包含宽泛的 text-runtime barrel | + | `plugin-sdk/approval-runtime` | exec / 插件审批辅助工具、审批能力构建器、认证 / 配置档辅助工具、原生路由 / 运行时辅助工具,以及结构化审批显示路径格式化 | + | `plugin-sdk/reply-runtime` | 共享入站 / 回复运行时辅助工具、分块、分发、心跳、回复规划器 | + | `plugin-sdk/reply-dispatch-runtime` | 精简的回复分发 / 完成和会话标签辅助工具 | + | `plugin-sdk/reply-history` | 共享的短窗口回复历史辅助工具和标记,例如 `buildHistoryContext`, `HISTORY_CONTEXT_MARKER`, `recordPendingHistoryEntry` 和 `clearHistoryEntriesIfEnabled` | | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | - | `plugin-sdk/reply-chunking` | 窄范围文本 / Markdown 分块辅助函数 | - | `plugin-sdk/session-store-runtime` | 会话存储路径、会话键、更新时间和存储变更辅助函数 | - | `plugin-sdk/cron-store-runtime` | Cron 存储路径 / 加载 / 保存辅助函数 | - | `plugin-sdk/state-paths` | 状态 / OAuth 目录路径辅助函数 | - | `plugin-sdk/routing` | 路由 / 会话键 / 账户绑定辅助函数,例如 `resolveAgentRoute`、`buildAgentSessionKey` 和 `resolveDefaultAgentBoundAccountId` | - | `plugin-sdk/status-helpers` | 共享渠道 / 账户 Status 摘要辅助函数、运行时状态默认值和问题元数据辅助函数 | - | `plugin-sdk/target-resolver-runtime` | 共享目标解析器辅助函数 | - | `plugin-sdk/string-normalization-runtime` | slug / 字符串规范化辅助函数 | + | `plugin-sdk/reply-chunking` | 精简的文本 / Markdown 分块辅助工具 | + | `plugin-sdk/session-store-runtime` | 会话存储路径、会话键、更新时间和存储变更辅助工具 | + | `plugin-sdk/cron-store-runtime` | Cron 存储路径 / 加载 / 保存辅助工具 | + | `plugin-sdk/state-paths` | 状态 / OAuth 目录路径辅助工具 | + | `plugin-sdk/routing` | 路由 / 会话键 / 账户绑定辅助工具,例如 `resolveAgentRoute`, `buildAgentSessionKey` 和 `resolveDefaultAgentBoundAccountId` | + | `plugin-sdk/status-helpers` | 共享渠道 / 账户 Status 摘要辅助工具、运行时状态默认值和问题元数据辅助工具 | + | `plugin-sdk/target-resolver-runtime` | 共享目标解析器辅助工具 | + | `plugin-sdk/string-normalization-runtime` | slug / 字符串规范化辅助工具 | | `plugin-sdk/request-url` | 从 fetch / request 类输入中提取字符串 URL | - | `plugin-sdk/run-command` | 带超时的命令运行器,返回规范化的 stdout / stderr 结果 | + | `plugin-sdk/run-command` | 带超时的命令运行器,输出已规范化的 stdout / stderr 结果 | | `plugin-sdk/param-readers` | 常用工具 / CLI 参数读取器 | - | `plugin-sdk/tool-payload` | 从工具结果对象中提取规范化载荷 | - | `plugin-sdk/tool-send` | 从工具参数中提取标准发送目标字段 | - | `plugin-sdk/temp-path` | 共享临时下载路径辅助函数 | - | `plugin-sdk/logging-core` | 子系统 logger 和脱敏辅助函数 | - | `plugin-sdk/markdown-table-runtime` | Markdown 表格模式和转换辅助函数 | - | `plugin-sdk/model-session-runtime` | 模型 / 会话覆盖辅助函数,例如 `applyModelOverrideToSessionEntry` 和 `resolveAgentMaxConcurrent` | - | `plugin-sdk/talk-config-runtime` | Talk 提供商配置解析辅助函数 | - | `plugin-sdk/json-store` | 小型 JSON 状态读写辅助函数 | - | `plugin-sdk/file-lock` | 可重入文件锁辅助函数 | - | `plugin-sdk/persistent-dedupe` | 磁盘支持的去重缓存辅助函数 | - | `plugin-sdk/acp-runtime` | ACP 运行时 / 会话和回复派发辅助函数 | - | `plugin-sdk/acp-binding-resolve-runtime` | 不引入生命周期启动导入的只读 ACP 绑定解析 | - | `plugin-sdk/agent-config-primitives` | 窄范围 agent 运行时配置 schema 原语 | + | `plugin-sdk/tool-payload` | 从工具结果对象中提取规范化负载 | + | `plugin-sdk/tool-send` | 从工具参数中提取规范的发送目标字段 | + | `plugin-sdk/temp-path` | 共享临时下载路径辅助工具 | + | `plugin-sdk/logging-core` | 子系统日志器和脱敏辅助工具 | + | `plugin-sdk/markdown-table-runtime` | Markdown 表格模式和转换辅助工具 | + | `plugin-sdk/model-session-runtime` | 模型 / 会话覆盖辅助工具,例如 `applyModelOverrideToSessionEntry` 和 `resolveAgentMaxConcurrent` | + | `plugin-sdk/talk-config-runtime` | Talk 提供商配置解析辅助工具 | + | `plugin-sdk/json-store` | 小型 JSON 状态读写辅助工具 | + | `plugin-sdk/file-lock` | 可重入文件锁辅助工具 | + | `plugin-sdk/persistent-dedupe` | 磁盘支持的去重缓存辅助工具 | + | `plugin-sdk/acp-runtime` | ACP 运行时 / 会话和回复分发辅助工具 | + | `plugin-sdk/acp-binding-resolve-runtime` | 只读 ACP 绑定解析,不引入生命周期启动导入 | + | `plugin-sdk/agent-config-primitives` | 精简的智能体运行时配置 schema 原语 | | `plugin-sdk/boolean-param` | 宽松布尔参数读取器 | - | `plugin-sdk/dangerous-name-runtime` | 危险名称匹配解析辅助函数 | - | `plugin-sdk/device-bootstrap` | 设备引导和配对令牌辅助函数 | + | `plugin-sdk/dangerous-name-runtime` | 危险名称匹配解析辅助工具 | + | `plugin-sdk/device-bootstrap` | 设备引导和配对令牌辅助工具 | | `plugin-sdk/extension-shared` | 共享被动渠道、Status 和环境代理辅助原语 | - | `plugin-sdk/models-provider-runtime` | `/models` 命令 / 提供商回复辅助函数 | - | `plugin-sdk/skill-commands-runtime` | Skills 命令列表辅助函数 | - | `plugin-sdk/native-command-registry` | 原生命令注册表 / 构建 / 序列化辅助函数 | - | `plugin-sdk/agent-harness` | 面向低层智能体 harness 的实验性可信插件接口:harness 类型、活动运行 steer / abort 辅助函数、OpenClaw 工具桥接辅助函数、运行时规划工具策略辅助函数、终端结果分类、工具进度格式化 / 详情辅助函数,以及尝试结果工具函数 | - | `plugin-sdk/provider-zai-endpoint` | Z.A.I 端点检测辅助函数 | - | `plugin-sdk/async-lock-runtime` | 面向小型运行时状态文件的进程内 async 锁辅助函数 | - | `plugin-sdk/channel-activity-runtime` | 渠道活动遥测辅助函数 | - | `plugin-sdk/concurrency-runtime` | 有界异步任务并发辅助函数 | - | `plugin-sdk/dedupe-runtime` | 内存去重缓存辅助函数 | - | `plugin-sdk/delivery-queue-runtime` | 出站待投递清空辅助函数 | - | `plugin-sdk/file-access-runtime` | 安全的本地文件和媒体源路径辅助函数 | - | `plugin-sdk/heartbeat-runtime` | heartbeat 事件和可见性辅助函数 | - | `plugin-sdk/number-runtime` | 数值强制转换辅助函数 | - | `plugin-sdk/secure-random-runtime` | 安全令牌 / UUID 辅助函数 | - | `plugin-sdk/system-event-runtime` | 系统事件队列辅助函数 | - | `plugin-sdk/transport-ready-runtime` | 传输就绪等待辅助函数 | - | `plugin-sdk/infra-runtime` | 已弃用的兼容性垫片;请改用上面更聚焦的运行时子路径 | - | `plugin-sdk/collection-runtime` | 小型有界缓存辅助函数 | - | `plugin-sdk/diagnostic-runtime` | 诊断标记、事件和 trace-context 辅助函数 | - | `plugin-sdk/error-runtime` | 错误图、格式化、共享错误分类辅助函数、`isApprovalNotFoundError` | - | `plugin-sdk/fetch-runtime` | 封装的 fetch、代理和 pinned 查找辅助函数 | - | `plugin-sdk/runtime-fetch` | 不引入代理 / 受保护 fetch 导入的 dispatcher 感知型运行时 fetch | - | `plugin-sdk/response-limit-runtime` | 不依赖广泛媒体运行时接口的有界响应体读取器 | + | `plugin-sdk/models-provider-runtime` | `/models` 命令 / 提供商回复辅助工具 | + | `plugin-sdk/skill-commands-runtime` | Skills 命令列表辅助工具 | + | `plugin-sdk/native-command-registry` | 原生命令注册表构建 / 序列化辅助工具 | + | `plugin-sdk/agent-harness` | 面向可信插件的实验性低层 Agent harness 接口:harness 类型、活动运行 steer / abort 辅助工具、OpenClaw 工具桥接辅助工具、运行时计划工具策略辅助工具、终端结果分类、工具进度格式化 / 细节辅助工具,以及尝试结果实用工具 | + | `plugin-sdk/provider-zai-endpoint` | Z.A.I endpoint 检测辅助工具 | + | `plugin-sdk/async-lock-runtime` | 面向小型运行时状态文件的进程本地异步锁辅助工具 | + | `plugin-sdk/channel-activity-runtime` | 渠道活动遥测辅助工具 | + | `plugin-sdk/concurrency-runtime` | 有界异步任务并发辅助工具 | + | `plugin-sdk/dedupe-runtime` | 内存中的去重缓存辅助工具 | + | `plugin-sdk/delivery-queue-runtime` | 出站待投递排空辅助工具 | + | `plugin-sdk/file-access-runtime` | 安全本地文件和媒体源路径辅助工具 | + | `plugin-sdk/heartbeat-runtime` | 心跳事件和可见性辅助工具 | + | `plugin-sdk/number-runtime` | 数值强制转换辅助工具 | + | `plugin-sdk/secure-random-runtime` | 安全令牌 / UUID 辅助工具 | + | `plugin-sdk/system-event-runtime` | 系统事件队列辅助工具 | + | `plugin-sdk/transport-ready-runtime` | 传输就绪等待辅助工具 | + | `plugin-sdk/infra-runtime` | 已弃用的兼容性 shim;请使用上面更聚焦的运行时子路径 | + | `plugin-sdk/collection-runtime` | 小型有界缓存辅助工具 | + | `plugin-sdk/diagnostic-runtime` | 诊断标记、事件和跟踪上下文辅助工具 | + | `plugin-sdk/error-runtime` | 错误图、格式化、共享错误分类辅助工具,`isApprovalNotFoundError` | + | `plugin-sdk/fetch-runtime` | 包装后的 fetch、代理和 pinned 查找辅助工具 | + | `plugin-sdk/runtime-fetch` | 感知 dispatcher 的运行时 fetch,不引入 proxy / guarded-fetch 导入 | + | `plugin-sdk/response-limit-runtime` | 有界响应体读取器,不包含宽泛的媒体运行时接口 | | `plugin-sdk/session-binding-runtime` | 当前会话绑定状态,不包含已配置绑定路由或配对存储 | - | `plugin-sdk/session-store-runtime` | 不引入广泛配置写入 / 维护导入的会话存储辅助函数 | - | `plugin-sdk/context-visibility-runtime` | 不依赖广泛配置 / 安全导入的上下文可见性解析和补充上下文过滤 | - | `plugin-sdk/string-coerce-runtime` | 不依赖 markdown / logging 导入的窄范围原始记录 / 字符串强制转换和规范化辅助函数 | - | `plugin-sdk/host-runtime` | 主机名和 SCP 主机规范化辅助函数 | - | `plugin-sdk/retry-runtime` | 重试配置和重试执行器辅助函数 | - | `plugin-sdk/agent-runtime` | 智能体目录 / 身份 / Agent 工作区辅助函数 | + | `plugin-sdk/session-store-runtime` | 会话存储辅助工具,不引入宽泛的配置写入 / 维护导入 | + | `plugin-sdk/context-visibility-runtime` | 上下文可见性解析和补充上下文过滤,不引入宽泛的配置 / 安全导入 | + | `plugin-sdk/string-coerce-runtime` | 精简的原始记录 / 字符串强制转换和规范化辅助工具,不引入 markdown / 日志导入 | + | `plugin-sdk/host-runtime` | 主机名和 SCP 主机规范化辅助工具 | + | `plugin-sdk/retry-runtime` | 重试配置和重试运行器辅助工具 | + | `plugin-sdk/agent-runtime` | 智能体目录 / 身份 / Agent 工作区辅助工具 | | `plugin-sdk/directory-runtime` | 基于配置的目录查询 / 去重 | | `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` | @@ -243,64 +243,64 @@ x-i18n: | 子路径 | 关键导出 | | --- | --- | - | `plugin-sdk/media-runtime` | 共享媒体获取 / 转换 / 存储辅助函数,以及媒体载荷构建器 | - | `plugin-sdk/media-store` | 窄范围媒体存储辅助函数,例如 `saveMediaBuffer` | - | `plugin-sdk/media-generation-runtime` | 共享媒体生成故障转移辅助函数、候选项选择和缺失模型提示消息 | + | `plugin-sdk/media-runtime` | 共享媒体获取 / 转换 / 存储辅助工具,以及媒体负载构建器 | + | `plugin-sdk/media-store` | 精简的媒体存储辅助工具,例如 `saveMediaBuffer` | + | `plugin-sdk/media-generation-runtime` | 共享媒体生成故障转移辅助工具、候选项选择和缺失模型提示 | | `plugin-sdk/media-understanding` | 媒体理解提供商类型,以及面向提供商的图像 / 音频辅助导出 | - | `plugin-sdk/text-runtime` | 共享文本 / Markdown / 日志辅助函数,例如对助手可见文本的剥离、Markdown 渲染 / 分块 / 表格辅助函数、脱敏辅助函数、directive-tag 辅助函数和安全文本工具 | - | `plugin-sdk/text-chunking` | 出站文本分块辅助函数 | - | `plugin-sdk/speech` | 语音提供商类型,以及面向提供商的指令、注册表、校验和语音辅助导出 | - | `plugin-sdk/speech-core` | 共享语音提供商类型、注册表、指令、规范化和语音辅助导出 | - | `plugin-sdk/realtime-transcription` | 实时转写提供商类型、注册表辅助函数和共享 WebSocket 会话辅助函数 | - | `plugin-sdk/realtime-voice` | 实时语音提供商类型和注册表辅助函数 | + | `plugin-sdk/text-runtime` | 共享文本 / Markdown / 日志辅助工具,例如对智能体可见文本的剥离、Markdown 渲染 / 分块 / 表格辅助工具、脱敏辅助工具、directive tag 辅助工具和安全文本实用工具 | + | `plugin-sdk/text-chunking` | 出站文本分块辅助工具 | + | `plugin-sdk/speech` | 语音提供商类型,以及面向提供商的 directive、注册表、校验和语音辅助导出 | + | `plugin-sdk/speech-core` | 共享语音提供商类型、注册表、directive、规范化和语音辅助导出 | + | `plugin-sdk/realtime-transcription` | 实时转录提供商类型、注册表辅助工具和共享 WebSocket 会话辅助工具 | + | `plugin-sdk/realtime-voice` | 实时语音提供商类型和注册表辅助工具 | | `plugin-sdk/image-generation` | 图像生成提供商类型 | - | `plugin-sdk/image-generation-core` | 共享图像生成类型、故障转移、认证和注册表辅助函数 | + | `plugin-sdk/image-generation-core` | 共享图像生成类型、故障转移、认证和注册表辅助工具 | | `plugin-sdk/music-generation` | 音乐生成提供商 / 请求 / 结果类型 | - | `plugin-sdk/music-generation-core` | 共享音乐生成类型、故障转移辅助函数、提供商查找和 model-ref 解析 | + | `plugin-sdk/music-generation-core` | 共享音乐生成类型、故障转移辅助工具、提供商查找和 model-ref 解析 | | `plugin-sdk/video-generation` | 视频生成提供商 / 请求 / 结果类型 | - | `plugin-sdk/video-generation-core` | 共享视频生成类型、故障转移辅助函数、提供商查找和 model-ref 解析 | - | `plugin-sdk/webhook-targets` | webhook 目标注册表和路由安装辅助函数 | - | `plugin-sdk/webhook-path` | webhook 路径规范化辅助函数 | - | `plugin-sdk/web-media` | 共享远程 / 本地媒体加载辅助函数 | + | `plugin-sdk/video-generation-core` | 共享视频生成类型、故障转移辅助工具、提供商查找和 model-ref 解析 | + | `plugin-sdk/webhook-targets` | webhook 目标注册表和路由安装辅助工具 | + | `plugin-sdk/webhook-path` | webhook 路径规范化辅助工具 | + | `plugin-sdk/web-media` | 共享远程 / 本地媒体加载辅助工具 | | `plugin-sdk/zod` | 为插件 SDK 使用者重新导出的 `zod` | - | `plugin-sdk/testing` | 公共扩展测试辅助函数,包括插件注册表 / 运行时 mock、fetch / 环境变量 / 临时 fixture、schema / 媒体 / 实时测试辅助函数、`installCommonResolveTargetErrorCases`、`writeSkill`、`createTestRegistry` 以及实时生成环境加载。扩展 `*.test-support.ts` 辅助函数应保留在该路径或聚焦的 SDK 子路径上,而不是核心内部 | + | `plugin-sdk/testing` | 公共扩展测试辅助工具,包括插件注册表 / 运行时 mock、提供商注册捕获、设置向导辅助工具、fetch / env / 临时目录 / 时间 fixtures、schema / media / 实时测试辅助工具、`installCommonResolveTargetErrorCases`、`writeSkill`、`createTestRegistry`,以及实时生成环境加载。扩展 `*.test-support.ts` 辅助工具应保留在这里或聚焦的 SDK 子路径上,而不是放到核心内部模块 | | 子路径 | 关键导出 | | --- | --- | - | `plugin-sdk/memory-core` | 内置 memory-core 辅助接口,用于 manager / config / file / CLI 辅助函数 | - | `plugin-sdk/memory-core-engine-runtime` | Memory 索引 / 搜索运行时外观层 | - | `plugin-sdk/memory-core-host-engine-foundation` | Memory 主机基础引擎导出 | - | `plugin-sdk/memory-core-host-engine-embeddings` | Memory 主机 embedding 合同、注册表访问、本地提供商以及通用批处理 / 远程辅助函数 | - | `plugin-sdk/memory-core-host-engine-qmd` | Memory 主机 QMD 引擎导出 | - | `plugin-sdk/memory-core-host-engine-storage` | Memory 主机存储引擎导出 | - | `plugin-sdk/memory-core-host-multimodal` | Memory 主机多模态辅助函数 | - | `plugin-sdk/memory-core-host-query` | Memory 主机查询辅助函数 | - | `plugin-sdk/memory-core-host-secret` | Memory 主机密钥辅助函数 | - | `plugin-sdk/memory-core-host-events` | Memory 主机事件日志辅助函数 | - | `plugin-sdk/memory-core-host-status` | Memory 主机 Status 辅助函数 | - | `plugin-sdk/memory-core-host-runtime-cli` | Memory 主机 CLI 运行时辅助函数 | - | `plugin-sdk/memory-core-host-runtime-core` | Memory 主机核心运行时辅助函数 | - | `plugin-sdk/memory-core-host-runtime-files` | Memory 主机文件 / 运行时辅助函数 | - | `plugin-sdk/memory-host-core` | 面向厂商中立的别名,用于 Memory 主机核心运行时辅助函数 | - | `plugin-sdk/memory-host-events` | 面向厂商中立的别名,用于 Memory 主机事件日志辅助函数 | - | `plugin-sdk/memory-host-files` | 面向厂商中立的别名,用于 Memory 主机文件 / 运行时辅助函数 | - | `plugin-sdk/memory-host-markdown` | 面向 Memory 邻近插件的共享托管 Markdown 辅助函数 | - | `plugin-sdk/memory-host-search` | 用于访问搜索管理器的活动 Memory 运行时外观层 | - | `plugin-sdk/memory-host-status` | 面向厂商中立的别名,用于 Memory 主机 Status 辅助函数 | + | `plugin-sdk/memory-core` | 内置 memory-core 辅助接口,用于 manager / config / file / CLI 辅助工具 | + | `plugin-sdk/memory-core-engine-runtime` | Memory 索引 / 搜索运行时门面 | + | `plugin-sdk/memory-core-host-engine-foundation` | Memory host foundation engine 导出 | + | `plugin-sdk/memory-core-host-engine-embeddings` | Memory host embedding contracts、注册表访问、本地提供商和通用批处理 / 远程辅助工具 | + | `plugin-sdk/memory-core-host-engine-qmd` | Memory host QMD engine 导出 | + | `plugin-sdk/memory-core-host-engine-storage` | Memory host storage engine 导出 | + | `plugin-sdk/memory-core-host-multimodal` | Memory host 多模态辅助工具 | + | `plugin-sdk/memory-core-host-query` | Memory host 查询辅助工具 | + | `plugin-sdk/memory-core-host-secret` | Memory host secret 辅助工具 | + | `plugin-sdk/memory-core-host-events` | Memory host 事件日志辅助工具 | + | `plugin-sdk/memory-core-host-status` | Memory host Status 辅助工具 | + | `plugin-sdk/memory-core-host-runtime-cli` | Memory host CLI 运行时辅助工具 | + | `plugin-sdk/memory-core-host-runtime-core` | Memory host 核心运行时辅助工具 | + | `plugin-sdk/memory-core-host-runtime-files` | Memory host 文件 / 运行时辅助工具 | + | `plugin-sdk/memory-host-core` | 面向供应商中立的别名,对应 Memory host 核心运行时辅助工具 | + | `plugin-sdk/memory-host-events` | 面向供应商中立的别名,对应 Memory host 事件日志辅助工具 | + | `plugin-sdk/memory-host-files` | 面向供应商中立的别名,对应 Memory host 文件 / 运行时辅助工具 | + | `plugin-sdk/memory-host-markdown` | 面向 Memory 邻接插件的共享托管 Markdown 辅助工具 | + | `plugin-sdk/memory-host-search` | 用于访问 search-manager 的活动 Memory 运行时门面 | + | `plugin-sdk/memory-host-status` | 面向供应商中立的别名,对应 Memory host Status 辅助工具 | | `plugin-sdk/memory-lancedb` | 内置 memory-lancedb 辅助接口 | - | 系列 | 当前子路径 | 预期用途 | + | 类别 | 当前子路径 | 预期用途 | | --- | --- | --- | - | 浏览器 | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | 内置浏览器插件支持辅助函数。`browser-profiles` 导出 `resolveBrowserConfig`、`resolveProfile`、`ResolvedBrowserConfig`、`ResolvedBrowserProfile` 和 `ResolvedBrowserTabCleanupConfig`,用于规范化后的 `browser.tabCleanup` 结构。`browser-support` 仍作为兼容性 barrel。 | + | Browser | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | 内置浏览器插件支持辅助工具。`browser-profiles` 导出 `resolveBrowserConfig`、`resolveProfile`、`ResolvedBrowserConfig`、`ResolvedBrowserProfile` 和 `ResolvedBrowserTabCleanupConfig`,用于规范化后的 `browser.tabCleanup` 结构。`browser-support` 仍然是兼容性 barrel。 | | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | 内置 Matrix 辅助 / 运行时接口 | | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | 内置 LINE 辅助 / 运行时接口 | | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | 内置 IRC 辅助接口 | - | 渠道专用辅助函数 | `plugin-sdk/googlechat`, `plugin-sdk/googlechat-runtime-shared`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu`, `plugin-sdk/feishu-conversation`, `plugin-sdk/feishu-setup`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/telegram-command-ui`, `plugin-sdk/tlon`, `plugin-sdk/twitch`, `plugin-sdk/zalo`, `plugin-sdk/zalo-setup` | 已弃用的内置渠道兼容性 / 辅助接口。新插件应导入通用 SDK 子路径或插件本地 barrel。 | - | 认证 / 插件专用辅助函数 | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diagnostics-prometheus`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/memory-core`, `plugin-sdk/memory-lancedb`, `plugin-sdk/opencode`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | 内置功能 / 插件辅助接口;`plugin-sdk/github-copilot-token` 当前导出 `DEFAULT_COPILOT_API_BASE_URL`、`deriveCopilotApiBaseUrlFromToken` 和 `resolveCopilotApiToken` | + | 渠道专用辅助工具 | `plugin-sdk/googlechat`, `plugin-sdk/googlechat-runtime-shared`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu`, `plugin-sdk/feishu-conversation`, `plugin-sdk/feishu-setup`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/telegram-command-ui`, `plugin-sdk/tlon`, `plugin-sdk/twitch`, `plugin-sdk/zalo`, `plugin-sdk/zalo-setup` | 已弃用的内置渠道兼容 / 辅助接缝。新插件应导入通用 SDK 子路径或插件本地 barrel。 | + | 认证 / 插件专用辅助工具 | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diagnostics-prometheus`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/memory-core`, `plugin-sdk/memory-lancedb`, `plugin-sdk/opencode`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | 内置功能 / 插件辅助接缝;`plugin-sdk/github-copilot-token` 当前导出 `DEFAULT_COPILOT_API_BASE_URL`、`deriveCopilotApiBaseUrlFromToken` 和 `resolveCopilotApiToken` | diff --git a/docs/zh-CN/plugins/sdk-testing.md b/docs/zh-CN/plugins/sdk-testing.md index 14730cecd..b3275268a 100644 --- a/docs/zh-CN/plugins/sdk-testing.md +++ b/docs/zh-CN/plugins/sdk-testing.md @@ -1,24 +1,24 @@ --- read_when: - 你正在为一个插件编写测试 - - 你需要来自插件 SDK 的测试工具 + - 你需要使用来自插件 SDK 的测试工具 - 你想了解内置插件的契约测试 sidebarTitle: Testing summary: OpenClaw 插件的测试工具与模式 title: 插件测试 x-i18n: - generated_at: "2026-04-27T22:22:37Z" + generated_at: "2026-04-27T22:50:25Z" model: gpt-5.4 provider: openai - source_hash: 358a1e76d6a8e78ad503b040d49bab7f66fa8bfb2f1fe7dcb6088ef932e56860 + source_hash: ad2e95d9db988610931391c37f1fef12014dff717ceb1647bca241a1a438aeae source_path: plugins/sdk-testing.md workflow: 15 --- -OpenClaw 插件的测试工具、模式以及 lint 强制规则参考。 +OpenClaw 插件的测试工具、模式和 lint 强制规则参考。 - **在找测试示例?** 操作指南中包含了完整的测试示例: + **在找测试示例?** 操作指南包含了完整的测试示例: [渠道插件测试](/zh-CN/plugins/sdk-channel-plugins#step-6-test) 和 [提供商插件测试](/zh-CN/plugins/sdk-provider-plugins#step-6-test)。 @@ -27,7 +27,7 @@ OpenClaw 插件的测试工具、模式以及 lint 强制规则参考。 **导入:** `openclaw/plugin-sdk/testing` -测试子路径为插件作者导出了一组精简的辅助工具: +该测试子路径为插件作者导出了一组精简的辅助工具: ```typescript import { @@ -39,26 +39,33 @@ import { ### 可用导出 -| 导出 | 用途 | -| -------------------------------------- | ---------------------------- | -| `installCommonResolveTargetErrorCases` | 用于目标解析错误处理的共享测试用例 | -| `shouldAckReaction` | 检查某个渠道是否应添加 ack reaction | -| `removeAckReactionAfterReply` | 在回复送达后移除 ack reaction | -| `createTestRegistry` | 构建渠道插件注册表 fixture | -| `createEmptyPluginRegistry` | 构建空的插件注册表 fixture | -| `setActivePluginRegistry` | 为插件运行时测试安装注册表 fixture | +| 导出 | 用途 | +| -------------------------------------- | ------------------------------ | +| `installCommonResolveTargetErrorCases` | 目标解析错误处理的共享测试用例 | +| `shouldAckReaction` | 检查某个渠道是否应添加确认反应 | +| `removeAckReactionAfterReply` | 在回复送达后移除确认反应 | +| `createTestRegistry` | 构建渠道插件注册表夹具 | +| `createEmptyPluginRegistry` | 构建空的插件注册表夹具 | +| `setActivePluginRegistry` | 为插件运行时测试安装注册表夹具 | | `createRequestCaptureJsonFetch` | 在媒体辅助工具测试中捕获 JSON fetch 请求 | -| `withFetchPreconnect` | 在安装了 preconnect hooks 的情况下运行 fetch 测试 | -| `withEnv` / `withEnvAsync` | 临时修改环境变量 | -| `createTempHomeEnv` / `withTempDir` | 创建隔离的文件系统测试 fixture | -| `createMockServerResponse` | 创建一个最小化的 HTTP 服务器响应 mock | -| `registerSingleProviderPlugin` | 在 loader 冒烟测试中注册一个提供商插件 | -| `createRuntimeTaskFlow` | 创建隔离的运行时任务流状态 | -| `typedCases` | 为表驱动测试保留字面量类型 | +| `withFetchPreconnect` | 在安装了预连接钩子的情况下运行 fetch 测试 | +| `withEnv` / `withEnvAsync` | 临时修改环境变量 | +| `createTempHomeEnv` / `withTempDir` | 创建隔离的文件系统测试夹具 | +| `createMockServerResponse` | 创建最小化的 HTTP 服务器响应 mock | +| `registerSingleProviderPlugin` | 在加载器冒烟测试中注册一个提供商插件 | +| `registerProviderPlugin` | 从一个插件中捕获所有提供商类型 | +| `requireRegisteredProvider` | 断言提供商集合包含某个 id | +| `createProviderUsageFetch` | 构建提供商用量 fetch 夹具 | +| `useFrozenTime` / `useRealTime` | 为时间敏感测试冻结和恢复计时器 | +| `createRuntimeEnv` | 构建一个 mock 的 CLI/插件运行时环境 | +| `createTestWizardPrompter` | 构建一个 mock 的设置向导提示器 | +| `createPluginSetupWizardStatus` | 为渠道插件构建设置状态辅助工具 | +| `createRuntimeTaskFlow` | 创建隔离的运行时任务流状态 | +| `typedCases` | 为表驱动测试保留字面量类型 | ### 类型 -测试子路径还会重新导出在测试文件中有用的类型: +该测试子路径还会重新导出测试文件中有用的类型: ```typescript import type { @@ -99,13 +106,15 @@ describe("my-channel target resolution", () => { ### 测试注册契约 -把手写的 `api` mock 传给 `register(api)` 的单元测试,并不能覆盖 OpenClaw 的 loader 接受门禁。对于你的插件依赖的每个注册入口,至少添加一个基于 loader 的冒烟测试,尤其是 hooks 和 memory 这类独占能力。 +将手写的 `api` mock 传给 `register(api)` 的单元测试,并不会覆盖 OpenClaw 加载器的接受门禁。对于你的插件所依赖的每个注册表面,至少添加一个基于加载器的冒烟测试,尤其是钩子和诸如 memory 之类的独占能力。 -真实的 loader 会在缺少必需元数据,或插件调用了其并不拥有的能力 API 时,使插件注册失败。例如,`api.registerHook(...)` 需要一个 hook 名称,而 `api.registerMemoryCapability(...)` 则要求插件 manifest 或导出的入口声明 `kind: "memory"`。 +真实加载器会在缺少必需元数据,或插件调用了其并不拥有的能力 API 时使插件注册失败。例如, +`api.registerHook(...)` 需要一个钩子名称,而 +`api.registerMemoryCapability(...)` 则要求插件清单或导出的入口声明 `kind: "memory"`。 ### 测试运行时配置访问 -在测试内置插件时,优先使用仓库测试辅助工具中的共享插件运行时 mock。它的已弃用 `runtime.config.loadConfig()` 和 `runtime.config.writeConfigFile(...)` mocks 默认会抛错,这样测试就能捕获对兼容性 API 的新使用。只有在测试明确覆盖旧版兼容行为时,才覆盖这些 mocks。 +在测试内置插件时,优先使用仓库测试辅助工具中共享的插件运行时 mock。它的已弃用 `runtime.config.loadConfig()` 和 `runtime.config.writeConfigFile(...)` mocks 默认会抛错,这样测试就能捕获对兼容性 API 的新增使用。只有当测试明确覆盖旧版兼容行为时,才应重写这些 mocks。 ### 渠道插件的单元测试 @@ -204,12 +213,12 @@ store.setRuntime(mockRuntime); store.clearRuntime(); ``` -### 使用按实例设置的 stub 进行测试 +### 使用按实例 stub 进行测试 -优先使用按实例设置的 stub,而不是修改原型: +优先使用按实例 stub,而不是修改原型: ```typescript -// 推荐:按实例设置 stub +// 推荐:按实例 stub const client = new MyChannelClient(); client.sendMessage = vi.fn().mockResolvedValue({ id: "msg-1" }); @@ -229,18 +238,18 @@ pnpm test -- src/plugins/contracts/ - 哪些插件注册了哪些提供商 - 哪些插件注册了哪些语音提供商 -- 注册形状的正确性 -- 运行时契约符合性 +- 注册结构的正确性 +- 运行时契约合规性 -### 运行限定范围测试 +### 运行限定范围的测试 -针对某个特定插件: +针对特定插件: ```bash pnpm test -- /my-channel/ ``` -只运行契约测试: +仅运行契约测试: ```bash pnpm test -- src/plugins/contracts/shape.contract.test.ts @@ -250,9 +259,9 @@ pnpm test -- src/plugins/contracts/runtime.contract.test.ts ## lint 强制规则(仓库内插件) -`pnpm check` 会对仓库内插件强制执行三条规则: +对于仓库内插件,`pnpm check` 会强制执行三条规则: -1. **禁止整体式根导入** —— 拒绝使用 `openclaw/plugin-sdk` 根 barrel +1. **禁止使用单体根导入** —— 拒绝使用 `openclaw/plugin-sdk` 根 barrel 2. **禁止直接导入 `src/`** —— 插件不能直接导入 `../../src/` 3. **禁止自导入** —— 插件不能导入自己的 `plugin-sdk/` 子路径 @@ -272,7 +281,7 @@ pnpm test -- /my-channel/src/channel.test.ts # 使用特定测试名称过滤器运行 pnpm test -- /my-channel/ -t "resolves account" -# 运行并收集覆盖率 +# 运行并生成覆盖率 pnpm test:coverage ``` @@ -284,7 +293,7 @@ OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test ## 相关内容 -- [SDK 概览](/zh-CN/plugins/sdk-overview) —— 导入约定 -- [SDK 渠道插件](/zh-CN/plugins/sdk-channel-plugins) —— 渠道插件接口 -- [SDK 提供商插件](/zh-CN/plugins/sdk-provider-plugins) —— 提供商插件钩子 -- [构建插件](/zh-CN/plugins/building-plugins) —— 入门指南 +- [SDK 概览](/zh-CN/plugins/sdk-overview) -- 导入约定 +- [SDK 渠道插件](/zh-CN/plugins/sdk-channel-plugins) -- 渠道插件接口 +- [SDK 提供商插件](/zh-CN/plugins/sdk-provider-plugins) -- 提供商插件钩子 +- [构建插件](/zh-CN/plugins/building-plugins) -- 入门指南 diff --git a/docs/zh-CN/reference/RELEASING.md b/docs/zh-CN/reference/RELEASING.md index 6b26774e6..f6d73ba15 100644 --- a/docs/zh-CN/reference/RELEASING.md +++ b/docs/zh-CN/reference/RELEASING.md @@ -1,24 +1,24 @@ --- read_when: - - 正在查找公开发布渠道定义 - - 正在运行发布验证或软件包验收 - - 正在查找版本命名和发布节奏 -summary: 发布流程通道、运维人员检查清单、验证框、版本命名和发布节奏 + - 查找公开发布渠道定义 + - 运行发布验证或软件包验收 + - 查找版本命名和发布节奏 +summary: 发布通道、操作员检查清单、验证框、版本命名和发布节奏 title: 发布策略 x-i18n: - generated_at: "2026-04-27T21:04:56Z" + generated_at: "2026-04-27T22:50:25Z" model: gpt-5.4 provider: openai - source_hash: f3ff3c7887c59005a977522e3a0e80ea3458e29d12f6976397b0749d8001d914 + source_hash: d007af3cf645d1dd84013e686b7a0513fa97f58a5ad1c5758b70a7c93e2458f4 source_path: reference/RELEASING.md workflow: 15 --- -OpenClaw 有三个公开发布流程通道: +OpenClaw 有三个公开发布通道: - stable:带标签的发布,默认发布到 npm `beta`,或在明确要求时发布到 npm `latest` - beta:预发布标签,发布到 npm `beta` -- dev:`main` 的持续更新头部版本 +- dev:`main` 的滚动最新版本 ## 版本命名 @@ -28,113 +28,120 @@ OpenClaw 有三个公开发布流程通道: - Git 标签:`vYYYY.M.D-N` - Beta 预发布版本:`YYYY.M.D-beta.N` - Git 标签:`vYYYY.M.D-beta.N` -- 月份或日期不要补零 -- `latest` 表示当前已提升为正式版本的 stable npm 发布 +- 月和日不要补零 +- `latest` 表示当前已提升为正式版的 stable npm 发布 - `beta` 表示当前 beta 安装目标 -- Stable 和 stable 修正发布默认发布到 npm `beta`;发布运维人员可以显式指定 `latest`,或在之后提升一个经过验证的 beta 构建 -- 每个 stable OpenClaw 发布都会同时发布 npm 软件包和 macOS 应用; - beta 发布通常会先验证并发布 npm/软件包路径,而 macOS 应用的构建/签名/公证通常保留给 stable,除非有明确要求 +- Stable 和 stable 修正发布默认发布到 npm `beta`;发布操作员也可以显式指定 `latest`,或在之后提升一个已验证的 beta 构建 +- 每个 stable OpenClaw 发布都会同时交付 npm 包和 macOS 应用; + beta 发布通常会先验证并发布 npm / package 路径,而 macOS 应用的构建 / 签名 / 公证通常保留给 stable,除非另有明确要求 ## 发布节奏 - 发布采用 beta 优先 -- 只有在最新 beta 完成验证后,才会继续 stable -- 维护者通常会从当前 `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。 + 并确认当前 `main` 的 CI 足够绿色,可以从其创建分支。 +2. 使用 `/changelog` 根据真实提交历史重写 `CHANGELOG.md` 的顶部章节, + 保持条目面向用户,提交它,推送它,然后在创建分支前再执行一次 rebase / pull。 3. 检查 `src/plugins/compat/registry.ts` 和 - `src/commands/doctor/shared/deprecation-compat.ts` 中的发布兼容性记录。只有在升级路径仍被覆盖时才移除已过期的兼容项,否则记录为什么要有意保留它。 + `src/commands/doctor/shared/deprecation-compat.ts` 中的发布兼容性记录。仅在升级路径仍然被覆盖时移除已过期的兼容性, + 否则记录为何要有意保留它。 4. 从当前 `main` 创建 `release/YYYY.M.D`;不要直接在 `main` 上进行常规发布工作。 -5. 为目标标签更新所有必需的版本位置,然后运行本地确定性预检: +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. 如果验证失败,在发布分支上修复,并重新运行能证明修复有效的最小失败文件、通道、工作流任务、软件包配置、提供商或模型允许列表。只有当变更范围使之前的证据失效时,才重新运行完整的总体验证。 -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 说明,以及执行发布公告步骤。 +6. 以 `preflight_only=true` 运行 `OpenClaw NPM Release`。在标签尚不存在时, + 可以使用完整的 40 位发布分支 SHA 进行仅验证用途的预检。保存成功的 `preflight_run_id`。 +7. 针对发布分支、标签或完整提交 SHA,使用 `Full Release Validation` 启动所有预发布测试。这是四个大型发布验证框的唯一手动入口: + Vitest、Docker、QA Lab 和 Package。 +8. 如果验证失败,在发布分支上修复,并重新运行能证明修复成立的最小失败文件、lane、工作流作业、package 配置、provider 或模型 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`,以便在更快的本地 `pnpm check` 门禁之外,测试 TypeScript 仍然得到覆盖 -- 在发布预检之前运行 `pnpm check:architecture`,以便在更快的本地门禁之外,更广泛的导入循环和架构边界检查保持绿色 -- 在 `pnpm release:check` 之前运行 `pnpm build && pnpm ui:build`,以便打包验证步骤所需的 `dist/*` 发布产物和 Control UI bundle 已存在 -- 在发布审批前运行手动 `Full Release Validation` 工作流,以便通过一个入口点启动所有预发布验证框。它接受分支、标签或完整提交 SHA,会派发手动 `CI`,并派发 `OpenClaw Release Checks`,用于安装冒烟测试、软件包验收、Docker 发布路径测试套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram 通道。只有在软件包已经发布且还需要运行发布后的 Telegram E2E 时,才提供 `npm_telegram_package_spec`。当私有证据报告需要证明验证与某个已发布的 npm 软件包匹配、但又不强制运行 Telegram E2E 时,提供 `evidence_package_spec`。 - 示例: +- 在发布预检之前运行 `pnpm check:test-types`,这样测试 TypeScript 就能在更快的本地 `pnpm check` gate 之外继续得到覆盖 +- 在发布预检之前运行 `pnpm check:architecture`,这样更广泛的导入循环和架构边界检查就能在更快的本地 gate 之外保持绿色 +- 在 `pnpm release:check` 之前运行 `pnpm build && pnpm ui:build`,这样打包验证步骤所需的 `dist/*` 发布产物和 Control UI bundle 就会存在 +- 在发布审批前运行手动 `Full Release Validation` 工作流,以便通过一个入口点启动所有预发布测试框。它接受分支、标签或完整提交 SHA,分发手动 `CI`,并分发 `OpenClaw Release Checks`,用于安装冒烟测试、软件包验收、Docker 发布路径测试套件、live / E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram lanes。只有在软件包已经发布且还需要运行发布后的 Telegram E2E 时,才提供 `npm_telegram_package_spec`。当私有证据报告需要证明该验证与已发布的 npm 包一致,但不强制运行 Telegram E2E 时,提供 `evidence_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;对带必填 SHA-256 的 HTTPS tarball 使用 `source=url`;对由其他 GitHub Actions 运行上传的 tarball 使用 `source=artifact`。该工作流会将候选解析为 `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` +- 当你希望在发布工作继续进行时,为某个软件包候选提供旁路证明,就运行手动 `Package Acceptance` 工作流。对 `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`。该工作流会将候选解析为 `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 搜索和 OpenWebUI - - `full`:包含 OpenWebUI 的 Docker 发布路径分块 + - `smoke`:安装 / 渠道 / 智能体、Gateway 网关网络和配置重载 lanes + - `package`:原生基于产物的软件包 / 更新 / 插件 lanes,不包含 OpenWebUI 或 live ClawHub + - `product`:在 package 配置基础上增加 MCP 渠道、cron / subagent 清理、OpenAI web search 和 OpenWebUI + - `full`:带 OpenWebUI 的 Docker 发布路径分块 - `custom`:精确选择 `docker_lanes`,用于聚焦重跑 -- 当你只需要对发布候选进行完整的常规 CI 覆盖时,直接运行手动 `CI` 工作流。手动触发的 CI 会绕过 changed 范围限制,并强制运行 Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟测试、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n 通道。 +- 当你只需要为发布候选获取完整的常规 CI 覆盖时,直接运行手动 `CI` 工作流。手动触发的 CI 会绕过 changed 范围限制,并强制运行 Linux Node 分片、bundled-plugin 分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟测试、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n lanes。 示例:`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` - 发布检查现在在单独的手动工作流中运行: `OpenClaw Release Checks` -- `OpenClaw Release Checks` 也会在发布审批前运行 QA Lab mock parity 门禁,以及快速 live Matrix 配置和 Telegram QA 通道。live 通道使用 `qa-live-shared` 环境;Telegram 还使用 Convex CI 凭证租约。当你希望并行运行完整的 Matrix 传输、媒体和 E2EE 清单时,请运行手动 `QA-Lab - All Lanes` 工作流,并设置 `matrix_profile=all` 和 `matrix_shards=true`。 -- 跨操作系统的安装和升级运行时验证属于公开的 `OpenClaw Release Checks` 和 `Full Release Validation` 的一部分,它们会直接调用可复用工作流 `.github/workflows/openclaw-cross-os-release-checks-reusable.yml` -- 这种拆分是有意为之:让真正的 npm 发布路径保持简短、确定性强并聚焦产物,而较慢的 live 检查留在它们自己的通道中,这样就不会拖慢或阻塞发布 -- 含有密钥的发布检查应通过 `Full Release Validation` 派发,或者从 `main`/发布工作流引用派发,以便工作流逻辑和密钥保持受控 -- `OpenClaw Release Checks` 接受分支、标签或完整提交 SHA,只要解析出的提交可从某个 OpenClaw 分支或发布标签到达即可 -- `OpenClaw NPM Release` 的仅验证预检也接受当前工作流分支的完整 40 位提交 SHA,而不要求已有推送的标签 +- `OpenClaw Release Checks` 还会在发布审批前运行 QA Lab mock parity gate,以及快速 live Matrix 配置和 Telegram QA lane。live lanes 使用 `qa-live-shared` 环境;Telegram 还会使用 Convex CI 凭证租约。当你需要并行运行完整 Matrix 传输、媒体和 E2EE 清单时,运行手动 `QA-Lab - All Lanes` 工作流,并设置 `matrix_profile=all` 和 `matrix_shards=true`。 +- 跨操作系统的安装和升级运行时验证属于公开的 `OpenClaw Release Checks` 和 `Full Release Validation`,它们会直接调用可复用工作流 + `.github/workflows/openclaw-cross-os-release-checks-reusable.yml` +- 这种拆分是有意设计的:让真实的 npm 发布路径保持简短、确定且聚焦产物,而较慢的 live 检查保留在自己的 lane 中,这样它们就不会拖慢或阻塞发布 +- 带有机密的发布检查应通过 `Full Release Validation` 分发,或从 `main` / release 工作流 ref 分发,以便工作流逻辑和机密保持受控 +- `OpenClaw Release Checks` 接受分支、标签或完整提交 SHA,只要解析后的提交可从某个 OpenClaw 分支或发布标签到达 +- `OpenClaw NPM Release` 的仅验证预检也接受当前工作流分支的完整 40 位提交 SHA,而不要求已经推送标签 - 该 SHA 路径仅用于验证,不能提升为真实发布 -- 在 SHA 模式下,工作流仅为软件包元数据检查合成 `v`;真实发布仍然需要真实的发布标签 -- 两个工作流都会将真正的发布和提升路径保留在 GitHub 托管 runner 上,而非变更性的验证路径可以使用更大的 Blacksmith Linux runner -- 该工作流会使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 工作流密钥运行 +- 在 SHA 模式下,该工作流只会为软件包元数据检查合成 `v`;真实发布仍然需要真实的发布标签 +- 两个工作流都会将真实发布和提升路径保留在 GitHub-hosted runners 上,而非变更性的验证路径可以使用更大的 Blacksmith Linux runners +- 该工作流会运行 `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache` -- npm 发布预检不再等待单独的发布检查通道 + ,并同时使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 工作流机密 +- npm 发布预检不再等待单独的发布检查 lane - 在审批前运行 `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts` - (或对应的 beta/修正标签) + (或对应的 beta / 修正标签) - npm 发布后,运行 `node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D` - (或对应的 beta/修正版本),以在新的临时前缀中验证已发布的 registry 安装路径 + (或对应的 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` 工作流运行相同的发布后检查。它被有意设为仅手动运行,不会在每次合并时执行。 -- 维护者发布自动化现在使用“先预检再提升”: + ,以针对已发布的 npm 包验证已安装软件包的新手引导、Telegram 设置以及真实 Telegram E2E,并使用共享租赁的 Telegram 凭证池。本地维护者的一次性运行可以省略 Convex 变量,直接传入三个 `OPENCLAW_QA_TELEGRAM_*` 环境变量凭证。 +- 维护者也可以通过 GitHub Actions 中的手动 `NPM Telegram Beta E2E` 工作流运行相同的发布后检查。它是有意仅限手动运行的,不会在每次合并时运行。 +- 维护者发布自动化现在使用 “先预检再提升”: - 真实 npm 发布必须通过成功的 npm `preflight_run_id` - - 真实 npm 发布必须从与成功预检运行相同的 `main` 或 `release/YYYY.M.D` 分支派发 + - 真实 npm 发布必须从与成功预检运行相同的 `main` 或 `release/YYYY.M.D` 分支分发 - stable npm 发布默认指向 `beta` - stable npm 发布可以通过工作流输入显式指定 `latest` - - 基于 token 的 npm dist-tag 修改现在位于 + - 基于 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 `preflight_run_id` 和 `validate_run_id` - 真实发布路径会提升已准备好的产物,而不是再次重新构建它们 -- 对于像 `YYYY.M.D-N` 这样的 stable 修正发布,发布后验证器还会检查从 `YYYY.M.D` 到 `YYYY.M.D-N` 的同一临时前缀升级路径,这样发布修正就不会悄悄让旧的全局安装仍停留在基础 stable 负载上 -- npm 发布预检会以失败关闭,除非 tarball 同时包含 `dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 内容,这样我们就不会再次发布一个空的浏览器仪表盘 -- 发布后验证还会检查已发布的 registry 安装是否在根级 `dist/*` 布局下包含非空的内置插件运行时依赖。若某个发布缺少这些依赖负载,或其内容为空,将无法通过发布后验证器,也不能被提升到 `latest`。 -- `pnpm test:install:smoke` 还会对候选更新 tarball 强制执行 npm pack 的 `unpackedSize` 预算,因此安装器 e2e 能在发布路径之前捕获意外的打包膨胀 -- 如果发布工作涉及 CI 规划、扩展时序清单或扩展测试矩阵,请在审批前重新生成并审查来自 `.github/workflows/ci.yml` 的 planner 管理 `checks-node-extensions` 工作流矩阵输出,以免发布说明描述的是过时的 CI 布局 +- 对于像 `YYYY.M.D-N` 这样的 stable 修正发布,发布后验证器还会检查相同临时前缀中从 `YYYY.M.D` 到 `YYYY.M.D-N` 的升级路径,这样发布修正就不会悄悄让旧的全局安装仍停留在基础 stable 载荷上 +- 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 布局 - stable macOS 发布就绪还包括更新器相关表面: - GitHub release 最终必须包含打包好的 `.zip`、`.dmg` 和 `.dSYM.zip` - 发布后,`main` 上的 `appcast.xml` 必须指向新的 stable zip - - 打包后的应用必须保持非调试 bundle id、非空的 Sparkle feed URL,以及不低于该发布版本规范 Sparkle build 基线的 `CFBundleVersion` + - 打包后的应用必须保持非调试 bundle id、非空 Sparkle feed URL,以及不低于该发布版本规范 Sparkle build floor 的 `CFBundleVersion` -## 发布验证框 +## 发布测试框 -`Full Release Validation` 是运维人员通过单一入口点启动所有预发布测试的方式。从可信的 `main` 工作流引用运行它,并将发布分支、标签或完整提交 SHA 作为 `ref` 传入: +`Full Release Validation` 是操作员用来通过单一入口点启动所有预发布测试的方式。请从受信任的 `main` 工作流 ref 运行它,并将发布分支、标签或完整提交 SHA 作为 `ref` 传入: ```bash gh workflow run full-release-validation.yml \ @@ -145,27 +152,28 @@ gh workflow run full-release-validation.yml \ -f evidence_package_spec=openclaw@YYYY.M.D-beta.N ``` -该工作流会解析目标 ref,使用 `target_ref=` 派发手动 `CI`,派发 `OpenClaw Release Checks`,并且在设置了 `npm_telegram_package_spec` 时可选派发独立的发布后 Telegram E2E。随后,`OpenClaw Release Checks` 会展开安装冒烟测试、跨操作系统发布检查、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 workflow-ref 输入;通过选择工作流运行 ref 来选择可信 harness。 +该工作流会解析目标 ref,使用 +`target_ref=` 分发手动 `CI`,分发 `OpenClaw Release Checks`,并在设置了 `npm_telegram_package_spec` 时可选分发独立的发布后 Telegram E2E。随后,`OpenClaw Release Checks` 会展开安装冒烟测试、跨操作系统发布检查、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。 根据发布阶段使用以下变体: ```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 \ @@ -176,20 +184,23 @@ gh workflow run full-release-validation.yml \ -f npm_telegram_provider_mode=mock-openai ``` -不要在聚焦修复之后,把完整总体验证作为第一次重跑。如果某个验证框失败,请使用失败的子工作流、任务、Docker 通道、软件包配置、模型提供商或 QA 通道来获取下一轮证明。只有当修复改变了共享发布编排,或者让先前的全框证据失效时,才再次运行完整总体验证。总体验证的最终校验器会重新检查已记录的子工作流运行 id,因此在某个子工作流成功重跑后,只需重新运行失败的 `Verify full validation` 父任务。 +在进行一次聚焦修复后的第一次重跑时,不要使用完整总流程。如果某个框失败,下一次证明应使用失败的子工作流、作业、Docker lane、软件包配置、模型提供商或 QA lane。只有当修复改变了共享发布编排,或让先前的全框证据失效时,才再次运行完整总流程。该总流程的最终验证器会重新检查记录的子工作流运行 id,因此在某个子工作流成功重跑后,只需重新运行失败的 `Verify full validation` 父作业。 + +对于有界恢复,向总工作流传入 `rerun_group`。`all` 是真实的发布候选运行,`ci` 只运行常规 CI 子项,`release-checks` 运行所有发布验证框,而更窄的发布分组包括 `install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live`,以及在提供独立软件包 Telegram lane 时使用的 `npm-telegram`。 ### Vitest -Vitest 验证框是手动 `CI` 子工作流。手动 CI 会有意绕过 changed 范围限制,并对发布候选强制执行常规测试图:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟测试、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。 +Vitest 验证框是手动 `CI` 子工作流。手动 CI 会有意绕过 changed 范围限制,并为发布候选强制运行常规测试图:Linux Node 分片、bundled-plugin 分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟测试、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。 -使用这个验证框来回答“源代码树是否通过了完整的常规测试套件?”它不同于发布路径的产品验证。需要保留的证据: +使用这个验证框来回答“源代码树是否通过了完整的常规测试套件?” +它不同于发布路径的产品验证。需要保留的证据包括: -- 显示已派发 `CI` 运行 URL 的 `Full Release Validation` 摘要 +- 显示已分发 `CI` 运行 URL 的 `Full Release Validation` 摘要 - 在精确目标 SHA 上为绿色的 `CI` 运行 -- 在调查回归问题时,CI 任务中的失败或缓慢分片名称 -- 当某次运行需要性能分析时,保留诸如 `.artifacts/vitest-shard-timings.json` 这样的 Vitest 时序产物 +- 在调查回归时,来自 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 @@ -197,58 +208,67 @@ 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` 工作流。它通过已打包的 Docker 环境来验证发布候选,而不只是源码级测试。 发布 Docker 覆盖包括: -- 启用了慢速 Bun 全局安装冒烟测试的完整安装冒烟测试 -- 仓库 E2E 通道 +- 启用了较慢 Bun 全局安装冒烟测试的完整安装冒烟测试 +- 仓库 E2E lanes - 发布路径 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-channels` 分块中, - 而不是使用串行的一体化内置渠道通道 -- 将内置插件安装/卸载通道拆分为 + `plugins-runtime-install-a`、`plugins-runtime-install-b`、 + `bundled-channels-core`、`bundled-channels-update-a`、 + `bundled-channels-update-b` 和 `bundled-channels-contracts` +- 在请求时,`plugins-runtime-core` 分块中的 OpenWebUI 覆盖 +- 将 bundled-channel 依赖 lanes 拆分为 channel-smoke、update-target, + 以及 setup / runtime contract 分块,而不是一个大型 bundled-channel 作业 +- 拆分后的 bundled plugin 安装 / 卸载 lanes: `bundled-plugin-install-uninstall-0` 到 `bundled-plugin-install-uninstall-7` -- 当发布检查包含 live 测试套件时,提供商 live/E2E 测试套件和 Docker live 模型覆盖 +- 当发布检查包含 live 套件时,live / E2E provider 套件和 Docker live 模型覆盖 -重跑前先使用 Docker 产物。发布路径调度器会上传 `.artifacts/docker-tests/`,其中包含通道日志、`summary.json`、`failures.json`、阶段耗时、调度器计划 JSON 以及重跑命令。对于聚焦恢复,请在可复用的 live/E2E 工作流上使用 `docker_lanes=`,而不是重跑所有发布分块。生成的重跑命令会在可用时包含先前的 `package_artifact_run_id` 和已准备好的 Docker 镜像输入,因此失败的通道可以复用同一个 tarball 和 GHCR 镜像。 +重跑前先使用 Docker 产物。发布路径调度器会上传 +`.artifacts/docker-tests/`,其中包含 lane 日志、`summary.json`、`failures.json`、 +阶段时序、调度器计划 JSON 和重跑命令。对于聚焦恢复,在可复用的 live / E2E 工作流上使用 `docker_lanes=`,而不是重跑所有发布分块。生成的重跑命令会在可用时包含先前的 `package_artifact_run_id` 和已准备好的 Docker 镜像输入,因此失败的 lane 可以复用同一个 tarball 和 GHCR 镜像。 ### QA Lab -QA Lab 验证框也是 `OpenClaw Release Checks` 的一部分。它是智能体行为和渠道级别的发布门禁,与 Vitest 以及 Docker 软件包机制分离。 +QA Lab 验证框也是 `OpenClaw Release Checks` 的一部分。它是智能体行为和渠道级别的发布 gate,与 Vitest 和 Docker 的软件包机制分开。 发布 QA Lab 覆盖包括: -- 使用 agentic parity 包,将 OpenAI 候选通道与 Opus 4.6 基线进行比较的 mock parity 门禁 +- 使用 agentic parity pack,将 OpenAI 候选 lane 与 Opus 4.6 基线进行比较的 mock parity gate - 使用 `qa-live-shared` 环境的快速 live Matrix QA 配置 -- 使用 Convex CI 凭证租约的 live Telegram QA 通道 -- 当发布遥测需要明确的本地证明时,运行 `pnpm qa:otel:smoke` +- 使用 Convex CI 凭证租约的 live Telegram QA lane +- 当发布遥测需要显式本地证明时,运行 `pnpm qa:otel:smoke` -使用这个验证框来回答“该发布在 QA 场景和 live 渠道流程中是否表现正确?”在批准发布时,保留 parity、Matrix 和 Telegram 通道的产物 URL。完整 Matrix 覆盖仍可通过手动分片的 QA-Lab 运行获得,而不是作为默认的发布关键通道。 +使用这个验证框来回答“该发布在 QA 场景和 live 渠道流程中是否行为正确?” +在批准发布时,保留 parity、Matrix 和 Telegram lanes 的产物 URL。完整的 Matrix 覆盖仍然可通过手动分片的 QA-Lab 运行获得,而不是默认的关键发布 lane。 ### Package -Package 验证框是可安装产品的门禁。它由 `Package Acceptance` 和解析器 `scripts/resolve-openclaw-package-candidate.mjs` 提供支持。该解析器会将候选统一规范为供 Docker E2E 使用的 `package-under-test` tarball,验证软件包清单,记录软件包版本和 SHA-256,并将工作流 harness ref 与软件包来源 ref 分开。 +Package 验证框是可安装产品的 gate。它由 +`Package Acceptance` 和解析器 +`scripts/resolve-openclaw-package-candidate.mjs` 支持。该解析器会将候选规范化为供 Docker E2E 使用的 `package-under-test` tarball,验证软件包清单,记录软件包版本和 SHA-256,并将工作流 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=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=`、`suite_profile=custom`、 `docker_lanes=bundled-channel-deps-compat plugins-offline` 和 -`telegram_mode=mock-openai` 运行 Package Acceptance。发布路径 Docker 分块会覆盖重叠的安装、更新和插件更新通道;Package Acceptance 则会针对同一个已解析 tarball,保留原生产物的内置渠道兼容性、离线插件夹具以及 Telegram 软件包 QA。它是 GitHub 原生方案,用于替代此前大多数需要 Parallels 的软件包/更新覆盖。跨操作系统发布检查对于特定操作系统的新手引导、安装器和平台行为仍然重要,但软件包/更新产品验证应优先使用 Package Acceptance。 +`telegram_mode=mock-openai` 运行 Package Acceptance。发布路径 Docker 分块覆盖了重叠的安装、更新和插件更新 lanes;Package Acceptance 则保留原生产物的 bundled-channel 兼容性、离线插件 fixtures,以及针对同一个已解析 tarball 的 Telegram 软件包 QA。它是此前多数需要 Parallels 才能完成的软件包 / 更新覆盖的 GitHub 原生替代方案。跨操作系统发布检查对特定操作系统的新手引导、安装器和平台行为仍然重要,但软件包 / 更新的产品验证应优先使用 Package Acceptance。 -旧版 package-acceptance 宽容路径被刻意限制为有时限。直到 `2026.4.25` 的软件包可以使用兼容路径来处理已发布到 npm 的元数据缺口:tarball 中缺失的私有 QA 清单条目、缺失的 `gateway install --wrapper`、源自 tarball 的 git 夹具中缺失的补丁文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。`2026.4.25` 之后的软件包必须满足现代软件包契约;这些同样的缺口会导致发布验证失败。 +旧版 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 配置: +当发布问题与实际可安装软件包有关时,使用更广的 Package Acceptance 配置: ```bash gh workflow run package-acceptance.yml \ @@ -259,59 +279,64 @@ gh workflow run package-acceptance.yml \ -f suite_profile=product ``` -常见的软件包配置: +常见软件包配置: -- `smoke`:快速软件包安装/渠道/智能体、Gateway 网关网络和配置热重载通道 -- `package`:不包含 live ClawHub 的安装/更新/插件软件包契约;这是发布检查默认值 -- `product`:`package` 加上 MCP 渠道、cron/subagent 清理、OpenAI Web 搜索和 OpenWebUI -- `full`:包含 OpenWebUI 的 Docker 发布路径分块 -- `custom`:用于聚焦重跑的精确 `docker_lanes` 列表 +- `smoke`:快速的软件包安装 / 渠道 / 智能体、Gateway 网关网络和配置重载 lanes +- `package`:不含 live ClawHub 的安装 / 更新 / 插件软件包契约;这是发布检查默认值 +- `product`:`package` 加上 MCP 渠道、cron / subagent 清理、OpenAI web search 和 OpenWebUI +- `full`:带 OpenWebUI 的 Docker 发布路径分块 +- `custom`:精确的 `docker_lanes` 列表,用于聚焦重跑 -若要获取软件包候选的 Telegram 证明,请在 Package Acceptance 上启用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier`。该工作流会将已解析的 `package-under-test` tarball 传入 Telegram 通道;独立的 Telegram 工作流仍然接受已发布的 npm 规格用于发布后检查。 +对于软件包候选的 Telegram 证明,在 Package Acceptance 上启用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier`。该工作流会将已解析的 `package-under-test` tarball 传入 Telegram lane;独立的 Telegram 工作流仍然接受已发布的 npm 规格,用于发布后检查。 ## NPM 工作流输入 -`OpenClaw NPM Release` 接受以下由运维人员控制的输入: +`OpenClaw NPM Release` 接受以下由操作员控制的输入: -- `tag`:必填发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或 - `v2026.4.2-beta.1`;当 `preflight_only=true` 时,也可以是当前工作流分支的完整 40 位提交 SHA,用于仅验证的预检 -- `preflight_only`:`true` 表示仅进行验证/构建/打包,`false` 表示真实发布路径 -- `preflight_run_id`:真实发布路径中必填,以便工作流复用成功预检运行中准备好的 tarball -- `npm_dist_tag`:发布路径的 npm 目标标签;默认值为 `beta` +- `tag`:必需的发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或 + `v2026.4.2-beta.1`;当 `preflight_only=true` 时,它也可以是当前工作流分支的完整 40 位提交 SHA,用于仅验证的预检 +- `preflight_only`:`true` 表示仅进行验证 / 构建 / 打包,`false` 表示真实发布路径 +- `preflight_run_id`:在真实发布路径中必需,以便工作流复用成功预检运行中已准备好的 tarball +- `npm_dist_tag`:发布路径的 npm 目标标签;默认为 `beta` -`OpenClaw Release Checks` 接受以下由运维人员控制的输入: +`OpenClaw Release Checks` 接受以下由操作员控制的输入: -- `ref`:要验证的分支、标签或完整提交 SHA。含密钥的检查要求解析出的提交必须可从某个 OpenClaw 分支或发布标签到达。 +- `ref`:要验证的分支、标签或完整提交 SHA。带机密的检查要求解析后的提交必须可从某个 OpenClaw 分支或发布标签到达。 规则: - 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`; + 工作流会在继续发布前验证该元数据 ## Stable npm 发布顺序 在切 stable npm 发布时: -1. 以 `preflight_only=true` 运行 `OpenClaw NPM Release` - - 在标签尚不存在前,你可以使用当前工作流分支的完整提交 SHA,对预检工作流进行仅验证的 dry run -2. 在正常的 beta 优先流程中选择 `npm_dist_tag=beta`,只有在你明确想要直接发布 stable 时才选择 `latest` -3. 当你希望通过一个手动工作流获得常规 CI 加 live prompt cache、Docker、QA Lab、Matrix 和 Telegram 覆盖时,在发布分支、发布标签或完整提交 SHA 上运行 `Full Release Validation` -4. 如果你明确只需要确定性的常规测试图,则改为在发布 ref 上运行手动 `CI` 工作流 +1. 运行 `OpenClaw NPM Release`,并设置 `preflight_only=true` + - 在标签尚不存在时,你可以使用当前工作流分支的完整提交 + SHA,对预检工作流进行仅验证的 dry run +2. 对常规的 beta 优先流程选择 `npm_dist_tag=beta`,只有在你有意直接发布 stable 时才选择 `latest` +3. 当你希望通过一个手动工作流获得常规 CI 加上 live prompt cache、Docker、QA Lab、Matrix 和 Telegram 覆盖时,对发布分支、发布标签或完整提交 SHA 运行 `Full Release Validation` +4. 如果你有意只需要确定性的常规测试图,则改为在发布 ref 上运行手动 `CI` 工作流 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` 工作流,将该 stable 版本从 `beta` 提升到 `latest` -8. 如果该发布是有意直接发布到 `latest`,并且 `beta` 应立即跟随同一个 stable 构建,请使用同一个私有工作流将两个 dist-tag 都指向该 stable 版本,或者让其定时自愈同步稍后再更新 `beta` +8. 如果该发布是有意直接发布到 `latest`,并且 `beta` + 应立即跟随同一个 stable 构建,则使用相同的私有工作流让两个 dist-tag 都指向该 stable 版本,或者让其定时自愈同步稍后再移动 `beta` -dist-tag 修改位于私有仓库中以确保安全,因为它仍然需要 `NPM_TOKEN`,而公开仓库保持仅使用 OIDC 发布。 +dist-tag 变更位于私有仓库中,出于安全原因,因为它仍然需要 +`NPM_TOKEN`,而公开仓库保持仅使用 OIDC 发布。 -这样既记录了直接发布路径,也记录了 beta 优先提升路径,并且两者都对运维人员可见。 +这使直接发布路径和 beta 优先提升路径都具备文档记录,并且对操作员可见。 -如果维护者必须退回到本地 npm 身份验证,只能在专用 tmux 会话中运行任何 1Password CLI(`op`)命令。不要直接从主智能体 shell 调用 `op`;将其限制在 tmux 中可以让提示、警报和 OTP 处理保持可观察,并防止重复的主机警报。 +如果维护者必须回退到本地 npm 身份验证,请仅在专用 tmux 会话中运行任何 1Password CLI(`op`)命令。不要直接从主 agent shell 调用 `op`;将其限制在 tmux 内可以让提示、告警和 OTP 处理可观察,并防止重复的主机告警。 ## 公开参考 @@ -325,10 +350,10 @@ dist-tag 修改位于私有仓库中以确保安全,因为它仍然需要 `NPM - [`scripts/package-mac-dist.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/package-mac-dist.sh) - [`scripts/make_appcast.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/make_appcast.sh) -维护者会使用私有发布文档 +维护者会使用 [`openclaw/maintainers/release/README.md`](https://github.com/openclaw/maintainers/blob/main/release/README.md) -作为实际运行手册。 +中的私有发布文档作为实际运行手册。 -## 相关内容 +## 相关 - [发布渠道](/zh-CN/install/development-channels) diff --git a/docs/zh-CN/tools/index.md b/docs/zh-CN/tools/index.md index 32a213b3c..eb88ad45e 100644 --- a/docs/zh-CN/tools/index.md +++ b/docs/zh-CN/tools/index.md @@ -2,47 +2,47 @@ read_when: - 你想了解 OpenClaw 提供了哪些工具 - 你需要配置、允许或拒绝工具 - - 你正在内置工具、Skills 和插件之间做选择 + - 你正在内置工具、Skills 和插件之间做出选择 summary: OpenClaw 工具和插件概览:智能体能做什么,以及如何扩展它 title: 工具和插件 x-i18n: - generated_at: "2026-04-26T04:12:02Z" + generated_at: "2026-04-27T22:50:25Z" model: gpt-5.4 provider: openai - source_hash: 47cc0e2de5688328f7c11fcf86c0a2262b488c277f48416f584f5c7913f750c4 + source_hash: 62cde740188c224af03b4425c7f6dfca9a12f95603066db5925724fc6a07dcf0 source_path: tools/index.md workflow: 15 --- -智能体除了生成文本之外所做的一切,都是通过**工具**完成的。 +智能体执行的所有超出生成文本范围的操作,都是通过**工具**完成的。 工具让智能体能够读取文件、运行命令、浏览网页、发送消息以及与设备交互。 ## 工具、Skills 和插件 -OpenClaw 有三层协同工作的结构: +OpenClaw 有三个协同工作的层级: - 工具是智能体可以调用的类型化函数(例如 `exec`、`browser`、 - `web_search`、`message`)。OpenClaw 内置了一组**内置工具**,插件也可以注册额外的工具。 + 工具是智能体可调用的类型化函数(例如 `exec`、`browser`、 + `web_search`、`message`)。OpenClaw 自带一组**内置工具**,插件也可以注册额外工具。 - 对智能体来说,工具是发送给模型 API 的结构化函数定义。 + 对智能体来说,工具就是发送给模型 API 的结构化函数定义。 - Skill 是注入到系统提示词中的 markdown 文件(`SKILL.md`)。 - Skills 为智能体提供上下文、约束以及如何高效使用工具的分步指导。Skills 可以存在于你的工作区、共享文件夹中,或由插件内置提供。 + Skill 是注入到系统提示词中的 Markdown 文件(`SKILL.md`)。 + Skills 为智能体提供上下文、约束和分步指导,帮助它更有效地使用工具。Skills 可以位于你的工作区、共享文件夹中,或由插件内置提供。 [Skills 参考](/zh-CN/tools/skills) | [创建 Skills](/zh-CN/tools/creating-skills) - 插件是可以注册任意能力组合的软件包: - 渠道、模型提供商、工具、Skills、语音、实时转录、 + 插件是一种软件包,可以注册任意组合的能力: + 渠道、模型提供商、工具、Skills、语音、实时转写、 实时语音、媒体理解、图像生成、视频生成、 - 网页抓取、网页搜索等。有些插件是**核心**插件(随 + 网页抓取、网页搜索等。部分插件属于**核心**插件(随 OpenClaw 一起提供),另一些则是**外部**插件(由社区发布到 npm)。 [安装和配置插件](/zh-CN/tools/plugin) | [构建你自己的插件](/zh-CN/plugins/building-plugins) @@ -54,53 +54,52 @@ OpenClaw 有三层协同工作的结构: 这些工具随 OpenClaw 一起提供,无需安装任何插件即可使用: -| 工具 | 功能 | 页面 | -| ------------------------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------------ | -| `exec` / `process` | 运行 shell 命令,管理后台进程 | [Exec](/zh-CN/tools/exec), [Exec 审批](/zh-CN/tools/exec-approvals) | -| `code_execution` | 运行沙箱隔离的远程 Python 分析 | [代码执行](/zh-CN/tools/code-execution) | -| `browser` | 控制 Chromium 浏览器(导航、点击、截图) | [浏览器](/zh-CN/tools/browser) | -| `web_search` / `x_search` / `web_fetch` | 搜索网页、搜索 X 帖子、抓取页面内容 | [Web](/zh-CN/tools/web), [网页抓取](/zh-CN/tools/web-fetch) | -| `read` / `write` / `edit` | 在工作区中进行文件 I/O | | -| `apply_patch` | 多段文件补丁 | [Apply Patch](/zh-CN/tools/apply-patch) | -| `message` | 跨所有渠道发送消息 | [智能体发送](/zh-CN/tools/agent-send) | -| `canvas` | 驱动节点 Canvas(展示、求值、快照) | | -| `nodes` | 发现并指定已配对设备 | | -| `cron` / `gateway` | 管理定时任务;检查、修补、重启或更新 Gateway 网关 | | -| `image` / `image_generate` | 分析或生成图像 | [图像生成](/zh-CN/tools/image-generation) | -| `music_generate` | 生成音乐轨道 | [音乐生成](/zh-CN/tools/music-generation) | -| `video_generate` | 生成视频 | [视频生成](/zh-CN/tools/video-generation) | -| `tts` | 一次性文本转语音转换 | [TTS](/zh-CN/tools/tts) | -| `sessions_*` / `subagents` / `agents_list` | 会话管理、状态查看和子智能体编排 | [子智能体](/zh-CN/tools/subagents) | -| `session_status` | 轻量级 `/status` 风格回读和按会话覆盖模型 | [会话工具](/zh-CN/concepts/session-tool) | +| 工具 | 作用 | 页面 | +| ------------------------------------------ | -------------------------------------------------------------------- | ------------------------------------------------------------ | +| `exec` / `process` | 运行 shell 命令,管理后台进程 | [Exec](/zh-CN/tools/exec), [Exec 审批](/zh-CN/tools/exec-approvals) | +| `code_execution` | 运行沙箱隔离的远程 Python 分析 | [代码执行](/zh-CN/tools/code-execution) | +| `browser` | 控制 Chromium 浏览器(导航、点击、截图) | [浏览器](/zh-CN/tools/browser) | +| `web_search` / `x_search` / `web_fetch` | 搜索网页、搜索 X 帖子、抓取页面内容 | [网页](/zh-CN/tools/web), [网页抓取](/zh-CN/tools/web-fetch) | +| `read` / `write` / `edit` | 在工作区中进行文件 I/O | | +| `apply_patch` | 多区块文件补丁 | [Apply Patch](/zh-CN/tools/apply-patch) | +| `message` | 在所有渠道中发送消息 | [智能体发送](/zh-CN/tools/agent-send) | +| `canvas` | 驱动节点 Canvas(present、eval、snapshot) | | +| `nodes` | 发现并定位已配对设备 | | +| `cron` / `gateway` | 管理定时任务;检查、修补、重启或更新 Gateway 网关 | | +| `image` / `image_generate` | 分析或生成图像 | [图像生成](/zh-CN/tools/image-generation) | +| `music_generate` | 生成音乐轨道 | [音乐生成](/zh-CN/tools/music-generation) | +| `video_generate` | 生成视频 | [视频生成](/zh-CN/tools/video-generation) | +| `tts` | 一次性文本转语音转换 | [TTS](/zh-CN/tools/tts) | +| `sessions_*` / `subagents` / `agents_list` | 会话管理、状态查看和子智能体编排 | [子智能体](/zh-CN/tools/subagents) | +| `session_status` | 轻量级 `/status` 风格回读和会话模型覆盖 | [会话工具](/zh-CN/concepts/session-tool) | -对于图像相关工作,使用 `image` 进行分析,使用 `image_generate` 进行生成或编辑。如果你要指定 `openai/*`、`google/*`、`fal/*` 或其他非默认图像提供商,请先配置该提供商的认证/API key。 +对于图像相关工作,使用 `image` 进行分析,使用 `image_generate` 进行生成或编辑。如果你要使用 `openai/*`、`google/*`、`fal/*` 或其他非默认图像提供商,请先配置该提供商的凭证 / API 密钥。 -对于音乐相关工作,使用 `music_generate`。如果你要指定 `google/*`、`minimax/*` 或其他非默认音乐提供商,请先配置该提供商的认证/API key。 +对于音乐相关工作,使用 `music_generate`。如果你要使用 `google/*`、`minimax/*` 或其他非默认音乐提供商,请先配置该提供商的凭证 / API 密钥。 -对于视频相关工作,使用 `video_generate`。如果你要指定 `qwen/*` 或其他非默认视频提供商,请先配置该提供商的认证/API key。 +对于视频相关工作,使用 `video_generate`。如果你要使用 `qwen/*` 或其他非默认视频提供商,请先配置该提供商的凭证 / API 密钥。 -对于由工作流驱动的音频生成,当某个插件(例如 +对于由工作流驱动的音频生成,当插件(例如 ComfyUI)注册了 `music_generate` 时,请使用 `music_generate`。这与 `tts` 不同,后者是文本转语音。 -`session_status` 是会话组中的轻量级状态/回读工具。 -它用于回答关于当前会话的 `/status` 风格问题,并且 -可选地设置按会话生效的模型覆盖;`model=default` 会清除该 -覆盖。与 `/status` 一样,它可以根据最新 transcript usage 条目回填稀疏的 token/cache 计数器以及当前运行时模型标签。 +`session_status` 是 sessions 分组中的轻量级状态 / 回读工具。 +它可以回答当前会话中类似 `/status` 的问题,并且可以 +选择设置按会话生效的模型覆盖;`model=default` 会清除该 +覆盖。与 `/status` 一样,它还可以从最新的转录用量条目中回填稀疏的 token / cache 计数器以及当前运行时模型标签。 -`gateway` 是仅限所有者使用、用于 Gateway 网关操作的运行时工具: +`gateway` 是仅限所有者使用的 Gateway 网关运行时工具,用于执行 Gateway 网关操作: -- `config.schema.lookup`:在编辑前查询单一路径范围内的配置子树 +- `config.schema.lookup`:在编辑前查看某一路径范围内的配置子树 - `config.get`:获取当前配置快照和 hash - `config.patch`:执行部分配置更新并重启 -- `config.apply`:仅用于完整替换整份配置 +- `config.apply`:仅用于完整配置替换 - `update.run`:执行显式自更新并重启 -对于部分变更,优先使用 `config.schema.lookup`,然后使用 `config.patch`。只有在你明确打算替换整个配置时才使用 -`config.apply`。 -有关更全面的配置文档,请参阅 [配置](/zh-CN/gateway/configuration) 和 -[配置参考](/zh-CN/gateway/configuration-reference)。 -该工具还会拒绝修改 `tools.exec.ask` 或 `tools.exec.security`; -旧版 `tools.bash.*` 别名会规范化到相同的受保护 exec 路径。 +对于部分修改,优先使用 `config.schema.lookup`,然后使用 `config.patch`。 +只有在你明确要替换整个配置时,才使用 +`config.apply`。关于更广泛的配置文档,请阅读 [配置](/zh-CN/gateway/configuration) 和 +[配置参考](/zh-CN/gateway/configuration-reference)。 +该工具还会拒绝修改 `tools.exec.ask` 或 `tools.exec.security`;旧版 `tools.bash.*` 别名会被规范化为相同的受保护 exec 路径。 ### 插件提供的工具 @@ -108,16 +107,16 @@ ComfyUI)注册了 `music_generate` 时,请使用 `music_generate`。这与 ` - [Diffs](/zh-CN/tools/diffs) — 差异查看器和渲染器 - [LLM Task](/zh-CN/tools/llm-task) — 仅输出 JSON 的 LLM 步骤,用于结构化输出 -- [Lobster](/zh-CN/tools/lobster) — 带可恢复审批的类型化工作流运行时 -- [音乐生成](/zh-CN/tools/music-generation) — 共享的 `music_generate` 工具,带有工作流驱动的提供商 -- [OpenProse](/zh-CN/prose) — markdown 优先的工作流编排 -- [Tokenjuice](/zh-CN/tools/tokenjuice) — 紧凑呈现噪声较多的 `exec` 和 `bash` 工具结果 +- [Lobster](/zh-CN/tools/lobster) — 带可恢复审批机制的类型化工作流运行时 +- [音乐生成](/zh-CN/tools/music-generation) — 由工作流驱动提供商支持的共享 `music_generate` 工具 +- [OpenProse](/zh-CN/prose) — 以 Markdown 为优先的工作流编排 +- [Tokenjuice](/zh-CN/tools/tokenjuice) — 紧凑化嘈杂的 `exec` 和 `bash` 工具结果 ## 工具配置 ### 允许列表和拒绝列表 -通过配置中的 `tools.allow` / `tools.deny` 控制智能体可以调用哪些工具。拒绝始终优先于允许。 +通过配置中的 `tools.allow` / `tools.deny` 控制智能体可以调用哪些工具。拒绝规则始终优先于允许规则。 ```json5 { @@ -128,56 +127,73 @@ ComfyUI)注册了 `music_generate` 时,请使用 `music_generate`。这与 ` } ``` -当显式允许列表解析后没有任何可调用工具时,OpenClaw 会默认拒绝继续运行。 -例如,`tools.allow: ["query_db"]` 只有在某个已加载插件实际 -注册了 `query_db` 时才会生效。 -如果没有任何内置工具、插件工具或内置 MCP 工具匹配该允许列表,运行会在调用模型之前停止,而不是继续进行纯文本运行并可能编造工具结果。 +当显式允许列表最终解析为没有任何可调用工具时,OpenClaw 会采用默认拒绝策略并直接失败。 +例如,`tools.allow: ["query_db"]` 只有在某个已加载插件确实 +注册了 `query_db` 时才会生效。 +如果没有任何内置工具、插件工具或内置 MCP 工具匹配该允许列表,运行会在模型调用之前停止,而不是继续作为纯文本运行,从而避免模型凭空编造工具结果。 -### 工具配置档 +### 工具配置档案 -`tools.profile` 会在应用 `allow`/`deny` 之前设置基础允许列表。 +`tools.profile` 会在应用 `allow` / `deny` 之前先设置一个基础允许列表。 按智能体覆盖:`agents.list[].tools.profile`。 -| 配置档 | 包含内容 | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| `full` | 无限制(与未设置相同) | -| `coding` | `group:fs`, `group:runtime`, `group:web`, `group:sessions`, `group:memory`, `cron`, `image`, `image_generate`, `music_generate`, `video_generate` | -| `messaging` | `group:messaging`, `sessions_list`, `sessions_history`, `sessions_send`, `session_status` | -| `minimal` | 仅 `session_status` | +| 配置档案 | 包含内容 | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `full` | 用于更广泛命令 / 控制访问的无限制基线;等同于不设置 `tools.profile` | +| `coding` | `group:fs`、`group:runtime`、`group:web`、`group:sessions`、`group:memory`、`cron`、`image`、`image_generate`、`music_generate`、`video_generate` | +| `messaging` | `group:messaging`、`sessions_list`、`sessions_history`、`sessions_send`、`session_status` | +| `minimal` | 仅 `session_status` | -`coding` 包含轻量级 Web 工具(`web_search`、`web_fetch`、 -`x_search`),但不包含完整的浏览器控制工具。浏览器自动化可以驱动真实 -会话和已登录配置档,因此需要通过 -`tools.alsoAllow: ["browser"]` 或按智能体设置的 -`agents.list[].tools.alsoAllow: ["browser"]` 显式添加。 + +`tools.profile: "messaging"` 是专门为聚焦渠道的 +智能体而有意设计的窄权限配置。 +它不包含更广泛的命令 / 控制工具,例如文件系统、运行时、 +浏览器、canvas、nodes、cron 和 Gateway 网关控制。请使用 `tools.profile: "full"` +作为更广泛命令 / 控制访问的无限制基线,并在需要时再通过 +`tools.allow` / `tools.deny` 缩减权限。 + -`coding` 和 `messaging` 配置档还会允许在插件键 `bundle-mcp` 下配置的内置 MCP 工具。如果你希望配置档保留其常规内置工具,但隐藏所有已配置的 MCP 工具,请添加 `tools.deny: ["bundle-mcp"]`。 -`minimal` 配置档不包含内置 MCP 工具。 +`coding` 包含轻量级网页工具(`web_search`、`web_fetch`、`x_search`),但不包含完整的浏览器控制工具。浏览器自动化可能会驱动真实会话和已登录配置,因此请通过 +`tools.alsoAllow: ["browser"]` 或按智能体配置的 +`agents.list[].tools.alsoAllow: ["browser"]` 显式添加它。 -### 工具组 +`coding` 和 `messaging` 配置档案还会允许在插件键 `bundle-mcp` 下配置的内置 MCP 工具。如果你希望某个配置档案保留其正常的内置工具,但隐藏所有已配置的 MCP 工具,请添加 `tools.deny: ["bundle-mcp"]`。 +`minimal` 配置档案不包含内置 MCP 工具。 -在允许/拒绝列表中使用 `group:*` 简写: +示例(默认提供最宽的工具范围): -| 组 | 工具 | +```json5 +{ + tools: { + profile: "full", + }, +} +``` + +### 工具分组 + +在允许 / 拒绝列表中使用 `group:*` 简写: + +| 分组 | 工具 | | ------------------ | --------------------------------------------------------------------------------------------------------- | -| `group:runtime` | exec, process, code_execution(`bash` 可作为 `exec` 的别名) | -| `group:fs` | read, write, edit, apply_patch | -| `group:sessions` | sessions_list, sessions_history, sessions_send, sessions_spawn, sessions_yield, subagents, session_status | -| `group:memory` | memory_search, memory_get | -| `group:web` | web_search, x_search, web_fetch | -| `group:ui` | browser, canvas | -| `group:automation` | cron, gateway | +| `group:runtime` | exec、process、code_execution(`bash` 可作为 `exec` 的别名使用) | +| `group:fs` | read、write、edit、apply_patch | +| `group:sessions` | sessions_list、sessions_history、sessions_send、sessions_spawn、sessions_yield、subagents、session_status | +| `group:memory` | memory_search、memory_get | +| `group:web` | web_search、x_search、web_fetch | +| `group:ui` | browser、canvas | +| `group:automation` | cron、gateway | | `group:messaging` | message | | `group:nodes` | nodes | | `group:agents` | agents_list | -| `group:media` | image, image_generate, music_generate, video_generate, tts | -| `group:openclaw` | 所有 OpenClaw 内置工具(不包括插件工具) | +| `group:media` | image、image_generate、music_generate、video_generate、tts | +| `group:openclaw` | 所有 OpenClaw 内置工具(不包含插件工具) | -`sessions_history` 会返回一个有边界、经过安全过滤的回忆视图。它会从助手文本中移除 thinking 标签、`` 脚手架、纯文本工具调用 XML 负载(包括 `...`、`...`、`...`、`...` 以及被截断的工具调用块)、降级后的工具调用脚手架、泄露的 ASCII/全角模型控制 token,以及格式错误的 MiniMax 工具调用 XML,然后再应用脱敏/截断,并在可能的情况下用超大行占位符代替原始 transcript 转储。 +`sessions_history` 返回一个有边界、经过安全过滤的回忆视图。它会从助手文本中剥离思维标签、`` 脚手架、纯文本工具调用 XML 载荷(包括 `...`、`...`、`...`、`...` 以及被截断的工具调用块)、降级后的工具调用脚手架、泄露的 ASCII / 全角模型控制标记,以及格式错误的 MiniMax 工具调用 XML,然后再应用脱敏 / 截断,并在必要时使用超大行占位符,而不是充当原始转录转储。 -### 提供商专属限制 +### 提供商特定限制 -使用 `tools.byProvider` 可为特定提供商限制工具,而无需更改全局默认值: +使用 `tools.byProvider` 为特定提供商限制工具,而不改变全局默认设置: ```json5 {