diff --git a/docs/zh-CN/ci.md b/docs/zh-CN/ci.md index c3aa10ad3..de569eb09 100644 --- a/docs/zh-CN/ci.md +++ b/docs/zh-CN/ci.md @@ -1,53 +1,53 @@ --- read_when: - - 你需要理解 CI 作业为何运行或未运行 + - 你需要了解为什么某个 CI 作业运行了或没有运行 - 你正在调试失败的 GitHub Actions 检查 summary: CI 作业图、范围门禁和本地命令等效项 -title: 持续集成流水线 +title: CI 流水线 x-i18n: - generated_at: "2026-04-29T02:52:23Z" + generated_at: "2026-04-29T03:28:34Z" model: gpt-5.5 provider: openai - source_hash: 5b66d2f7d1a02955f9e9ee94fa6431c0652f62babde8c502a4b104ea811ee450 + source_hash: ff6ec4095aa24350e7dcbb894b06dc5c0eef1441dca882d1c9941c22aedbe2e4 source_path: ci.md workflow: 16 --- -CI 会在每次推送到 `main` 和每个拉取请求时运行。它使用智能作用域,在只有无关区域发生变更时跳过昂贵作业。手动 `workflow_dispatch` 运行会有意绕过智能作用域,并为发布候选或广泛验证展开完整的常规 CI 图。 +CI 会在每次推送到 `main` 和每个拉取请求上运行。它使用智能范围划分,在只有无关区域发生变更时跳过昂贵的作业。手动 `workflow_dispatch` 运行会有意绕过智能范围划分,并展开完整的常规 CI 图,用于发布候选版本或大范围验证。 -`Full Release Validation` 是用于“发布前运行所有内容”的手动总括工作流。它接受分支、标签或完整提交 SHA,使用该目标分派手动 `CI` 工作流,并分派 `OpenClaw Release Checks`,用于安装冒烟、包验收、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram lane。提供已发布包规范时,它还可以运行发布后的 `NPM Telegram Beta E2E` 工作流。`release_profile=minimum|stable|full` 控制传递给发布检查的 live/provider 覆盖范围:`minimum` 保留最快的 OpenAI/core 发布关键 lane,`stable` 添加稳定的 provider/backend 集合,`full` 运行广泛的 advisory provider/media 矩阵。总括工作流会记录已分派的子运行 ID,最终的 `Verify full validation` 作业会重新检查当前子运行结论,并为每个子运行追加最慢作业表。如果重新运行子工作流后变为绿色,只需重新运行父验证器作业,即可刷新总括结果和耗时摘要。 +`Full Release Validation` 是用于“发布前运行所有内容”的手动总控工作流。它接受分支、标签或完整提交 SHA,使用该目标调度手动 `CI` 工作流,并调度 `OpenClaw Release Checks`,用于安装冒烟测试、包验收、Docker 发布路径套件、实时/E2E、OpenWebUI、QA Lab 对等性、Matrix 和 Telegram 通道。提供已发布包规格时,它还可以运行发布后的 `NPM Telegram Beta E2E` 工作流。`release_profile=minimum|stable|full` 控制传入发布检查的实时/提供商覆盖范围:`minimum` 保留最快的 OpenAI/核心发布关键通道,`stable` 添加稳定的提供商/后端集合,`full` 运行广泛的建议性提供商/媒体矩阵。总控工作流会记录已调度的子运行 ID,最终的 `Verify full validation` 作业会重新检查当前子运行结论,并为每个子运行追加最慢作业表。如果某个子工作流重新运行后变绿,只需重新运行父验证器作业即可刷新总控结果和耗时摘要。 -对于恢复,`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`。这样可以在聚焦修复后,将失败发布箱的重新运行范围保持有界。 +对于恢复,`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`。这样可以在做出针对性修复后,将失败发布箱的重新运行限制在有界范围内。 -发布 live/E2E 子项保留广泛的原生 `pnpm test:live` 覆盖,但它通过 `scripts/test-live-shard.mjs` 将其作为命名分片运行(`native-live-src-agents`、`native-live-src-gateway-core`、provider 过滤的 `native-live-src-gateway-profiles` 作业、`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-other`、`native-live-extensions-xai`、拆分的媒体音频/视频分片,以及 provider 过滤的音乐分片),而不是一个串行作业。这样在保持相同文件覆盖的同时,让缓慢的 live provider 失败更容易重新运行和诊断。聚合的 `native-live-extensions-o-z`、`native-live-extensions-media` 和 `native-live-extensions-media-music` 分片名称仍然可用于手动一次性重新运行。 +发布实时/E2E 子项保留广泛的原生 `pnpm test:live` 覆盖范围,但会通过 `scripts/test-live-shard.mjs` 将其作为命名分片运行(`native-live-src-agents`、`native-live-src-gateway-core`、按提供商过滤的 `native-live-src-gateway-profiles` 作业、`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-other`、`native-live-extensions-xai`、拆分后的媒体音频/视频分片,以及按提供商过滤的音乐分片),而不是一个串行作业。这样既保持相同的文件覆盖范围,又让缓慢的实时提供商失败更容易重新运行和诊断。聚合分片名称 `native-live-extensions-o-z`、`native-live-extensions-media` 和 `native-live-extensions-media-music` 仍可用于手动一次性重新运行。 -原生 live 媒体分片在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中运行,该镜像由 `Live Media Runner Image` 工作流构建。该镜像预装 `ffmpeg` 和 `ffprobe`;媒体作业只会在设置前验证这些二进制文件。将 Docker 支持的 live 套件保留在普通 Blacksmith runner 上,因为容器作业不适合启动嵌套 Docker 测试。 +原生实时媒体分片在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中运行,该镜像由 `Live Media Runner Image` 工作流构建。该镜像预装了 `ffmpeg` 和 `ffprobe`;媒体作业只会在设置前验证这些二进制文件。让 Docker 支撑的实时套件保留在常规 Blacksmith 运行器上,因为容器作业不适合启动嵌套 Docker 测试。 -`OpenClaw Release Checks` 使用受信任的工作流 ref 将选定 ref 一次性解析为 `release-package-under-test` tarball,然后将该 artifact 传递给 live/E2E 发布路径 Docker 工作流和包验收分片。这会让发布箱之间的包字节保持一致,并避免在多个子作业中重复打包同一个候选。 +`OpenClaw Release Checks` 使用受信任的工作流引用将所选引用解析一次为 `release-package-under-test` tarball,然后将该工件传递给实时/E2E 发布路径 Docker 工作流和包验收分片。这样可以让发布箱之间的包字节保持一致,并避免在多个子作业中重复打包同一个候选包。 -`Package Acceptance` 是用于在不阻塞发布工作流的情况下验证包 artifact 的旁路运行工作流。它会从已发布的 npm 规范、使用选定 `workflow_ref` harness 构建的受信任 `package_ref`、带 SHA-256 的 HTTPS tarball URL,或来自另一个 GitHub Actions 运行的 tarball artifact 中解析一个候选,将其上传为 `package-under-test`,然后复用 Docker release/E2E 调度器,并使用该 tarball,而不是重新打包工作流检出内容。Profile 覆盖 smoke、package、product、full 和自定义 Docker lane 选择。`package` profile 使用离线 plugin 覆盖,因此已发布包验证不会被 live ClawHub 可用性卡住。可选 Telegram lane 会在 `NPM Telegram Beta E2E` 工作流中复用 `package-under-test` artifact,同时保留已发布 npm 规范路径供独立分派使用。 +`Package Acceptance` 是用于验证包工件的旁路运行工作流,不会阻塞发布工作流。它会从已发布的 npm 规格、使用所选 `workflow_ref` harness 构建的受信任 `package_ref`、带 SHA-256 的 HTTPS tarball URL,或来自另一个 GitHub Actions 运行的 tarball 工件中解析一个候选包,将其作为 `package-under-test` 上传,然后复用 Docker 发布/E2E 调度器,并使用该 tarball,而不是重新打包工作流检出内容。配置文件覆盖冒烟测试、包、产品、完整和自定义 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 验证源代码树,而包验收会通过用户安装或更新后使用的同一 Docker E2E harness 验证单个 tarball。 该工作流有四个作业: -1. `resolve_package` 检出 `workflow_ref`,解析一个包候选,写入 `.artifacts/docker-e2e-package/openclaw-current.tgz`,写入 `.artifacts/docker-e2e-package/package-candidate.json`,将两者作为 `package-under-test` artifact 上传,并在 GitHub 步骤摘要中打印来源、工作流 ref、包 ref、版本、SHA-256 和 profile。 -2. `docker_acceptance` 使用 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 调用 `openclaw-live-and-e2e-checks-reusable.yml`。可复用工作流会下载该 artifact,验证 tarball 清单,在需要时准备 package-digest Docker 镜像,并针对该包运行选定的 Docker lane,而不是打包工作流检出内容。当某个 profile 选择多个定向 `docker_lanes` 时,可复用工作流会先准备一次包和共享镜像,然后将这些 lane 展开为并行的定向 Docker 作业,并使用唯一 artifact。 -3. `package_telegram` 可选调用 `NPM Telegram Beta E2E`。当 `telegram_mode` 不是 `none` 时运行,并在 Package Acceptance 已解析包时安装同一个 `package-under-test` artifact;独立 Telegram 分派仍可安装已发布的 npm 规范。 -4. `summary` 会在包解析、Docker 验收或可选 Telegram lane 失败时使工作流失败。 +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` 使用 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 调用 `openclaw-live-and-e2e-checks-reusable.yml`。可复用工作流会下载该工件,验证 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@2026.4.27-beta.2` 这样的精确 OpenClaw 发布版本。将它用于已发布 beta/stable 验收。 -- `source=ref`:打包受信任的 `package_ref` 分支、标签或完整提交 SHA。解析器会获取 OpenClaw 分支/标签,验证选定提交可从仓库分支历史或发布标签访问,在分离工作树中安装依赖,并使用 `scripts/package-openclaw-for-docker.mjs` 打包。 +- `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` 可选,但应为外部共享 artifact 提供。 +- `source=artifact`:从 `artifact_run_id` 和 `artifact_name` 下载一个 `.tgz`;`package_sha256` 可选,但对于外部共享工件应提供。 -保持 `workflow_ref` 和 `package_ref` 分离。`workflow_ref` 是运行测试的受信任 workflow/harness 代码。`package_ref` 是在 `source=ref` 时会被打包的源提交。这样当前测试 harness 可以验证较旧的受信任源提交,而不运行旧工作流逻辑。 +保持 `workflow_ref` 和 `package_ref` 分离。`workflow_ref` 是运行测试的受信任工作流/harness 代码。`package_ref` 是在 `source=ref` 时被打包的源提交。这让当前测试 harness 可以验证较旧的受信任源提交,而不运行旧的工作流逻辑。 -Profile 映射到 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` @@ -55,10 +55,9 @@ Profile 映射到 Docker 覆盖: - `full`:带 OpenWebUI 的完整 Docker 发布路径分块 - `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/update/plugin lane,而 Package Acceptance 保留针对同一个已解析包 tarball 的 artifact 原生 bundled-channel 兼容性、离线 plugin 和 Telegram 证明。 -跨 OS 发布检查仍覆盖特定于 OS 的新手引导、安装器和平台行为;package/update 产品验证应从 Package Acceptance 开始。Windows packaged 和 installer fresh lane 还会验证已安装包能否从原始绝对 Windows 路径导入 browser-control override。 +发布检查会使用 `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 的工件原生内置渠道兼容性、离线插件和 Telegram 证明。跨 OS 发布检查仍覆盖 OS 特定的新手引导、安装器和平台行为;包/更新产品验证应从 Package Acceptance 开始。Windows 打包和安装器全新通道还会验证已安装包可以从原始绝对 Windows 路径导入浏览器控制替代项。 -Package Acceptance 对已发布包设置了有界的旧版兼容窗口。到 `2026.4.25` 为止的包(包括 `2026.4.25-beta.*`)可以对 `dist/postinstall-inventory.json` 中指向 tarball 省略文件的已知私有 QA 条目使用兼容路径;当包未暴露该标志时,`doctor-switch` 可以跳过 `gateway install --wrapper` 持久化子用例;`update-channel-switch` 可以从 tarball 派生的 fake git fixture 中修剪缺失的 `pnpm.patchedDependencies`,并可以记录缺失的持久化 `update.channel`;plugin 冒烟可以读取旧版安装记录位置,或接受缺失的 marketplace 安装记录持久化;`plugin-update` 可以允许配置元数据迁移,同时仍要求安装记录和不重新安装行为保持不变。已发布的 `2026.4.26` 包也可以对已随包发布的本地构建元数据戳记文件发出警告。后续包必须满足现代契约;相同条件会失败,而不是警告或跳过。 +Package Acceptance 对已经发布的包有有界的旧版兼容窗口。直到 `2026.4.25` 的包,包括 `2026.4.25-beta.*`,可以对 `dist/postinstall-inventory.json` 中指向 tarball 省略文件的已知私有 QA 条目使用兼容路径;当包未暴露该标志时,`doctor-switch` 可以跳过 `gateway install --wrapper` 持久化子用例;`update-channel-switch` 可以从 tarball 派生的假 git fixture 中裁剪缺失的 `pnpm.patchedDependencies`,并可以记录缺失的持久化 `update.channel`;插件冒烟测试可以读取旧版安装记录位置,或接受缺失的 marketplace 安装记录持久化;`plugin-update` 可以允许配置元数据迁移,同时仍要求安装记录和不重新安装行为保持不变。已发布的 `2026.4.26` 包也可以对已经发布的本地构建元数据戳文件发出警告。后续包必须满足现代契约;相同条件会失败,而不是警告或跳过。 示例: @@ -101,24 +100,24 @@ gh workflow run package-acceptance.yml \ -f docker_lanes='install-e2e plugin-update' ``` -调试失败的包验收运行时,先从 `resolve_package` 摘要开始,确认包来源、版本和 SHA-256。然后检查 `docker_acceptance` 子运行及其 Docker artifact:`.artifacts/docker-tests/**/summary.json`、`failures.json`、lane 日志、阶段耗时和重新运行命令。优先重新运行失败的包 profile 或精确 Docker lane,而不是重新运行完整发布验证。 +调试失败的包验收运行时,从 `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 智能体包。`QA-Lab - All Lanes` 工作流每晚在 `main` 上运行,也可手动派发;它会将模拟一致性门、实时 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 通道;其 QA 一致性门会把候选包和基线包作为并行通道作业运行,然后把两个制品下载到一个小型报告作业中,用于最终一致性比较。 -除非变更确实触及 QA 运行时、模型包一致性,或一致性工作流负责的表面,否则不要把 PR 合并路径放在 `Parity gate` 后面。对于普通的渠道、配置、文档或单元测试修复,把它视为可选信号,并遵循作用域内的 CI/检查证据。 +QA Lab 在主智能作用域工作流之外有专用 CI 通道。`Parity gate` 工作流会在匹配的 PR 变更和手动调度时运行;它会构建私有 QA 运行时,并比较模拟 GPT-5.5 和 Opus 4.6 智能体包。`QA-Lab - All Lanes` 工作流每晚在 `main` 上运行,也可手动调度;它会将模拟 parity gate、实时 Matrix 通道,以及实时 Telegram 和 Discord 通道作为并行作业展开运行。实时作业使用 `qa-live-shared` 环境,Telegram/Discord 使用 Convex 租约。发布检查会使用确定性模拟提供商运行 Matrix 和 Telegram 实时传输通道,因此渠道契约与实时模型延迟隔离;提供商连通性由独立的实时模型、原生提供商和 Docker 提供商套件覆盖。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 parity gate 会将候选包和基线包作为并行通道作业运行,然后把两个工件下载到一个小型报告作业中,用于最终 parity 比较。 +除非变更确实触及 QA 运行时、模型包 parity,或 parity 工作流拥有的表面,否则不要把 PR 落地路径放在 `Parity gate` 后面。对于常规渠道、配置、文档或单元测试修复,请将它视为可选信号,并遵循作用域内的 CI/检查证据。 -`Duplicate PRs After Merge` 工作流是一个用于合并后重复项清理的手动维护者工作流。它默认 dry-run,并且仅在 `apply=true` 时关闭显式列出的 PR。在修改 GitHub 之前,它会验证已合并的 PR 确实已合并,并验证每个重复项要么有共享的引用 issue,要么有重叠的变更 hunk。 +`Duplicate PRs After Merge` 工作流是一个用于落地后重复项清理的手动维护者工作流。它默认以 dry-run 运行,并且仅在 `apply=true` 时关闭显式列出的 PR。在变更 GitHub 之前,它会验证已落地的 PR 已合并,并且每个重复项要么有共享的引用 issue,要么存在重叠的变更 hunk。 -`CodeQL` 工作流有意作为窄范围的第一轮安全扫描器,而不是完整仓库扫描。每日和手动运行会使用高精度安全查询扫描 Actions 工作流代码,以及风险最高的 JavaScript/TypeScript 凭证、密钥、沙箱、cron 和 Gateway 网关表面。channel-runtime-boundary 作业会单独扫描核心渠道实现契约,以及渠道插件运行时、Gateway 网关、插件 SDK、密钥和审计触点,类别为 `/codeql-critical-security/channel-runtime-boundary`,这样渠道安全信号就可以在不扩大基线 JS/TS 类别的情况下扩展。 +`CodeQL` 工作流有意作为窄范围的第一轮安全扫描器,而不是完整仓库扫描。每日和手动运行会扫描 Actions 工作流代码,以及风险最高的 JavaScript/TypeScript 凭证、机密、沙箱、cron 和 gateway 表面,并使用高精度安全查询。channel-runtime-boundary 作业会在 `/codeql-critical-security/channel-runtime-boundary` 类别下单独扫描核心渠道实现契约,以及渠道插件运行时、gateway、插件 SDK、机密和审计触点,这样渠道安全信号可以扩展,而无需扩大基线 JS/TS 类别。 -`CodeQL Android Critical Security` 工作流是计划执行的 Android 安全分片。它会在 workflow sanity 接受的最小 Blacksmith Linux runner 标签上,为 CodeQL 手动构建 Android 应用,并在 `/codeql-critical-security/android` 类别下上传结果。 +`CodeQL Android Critical Security` 工作流是定时 Android 安全分片。它会在 workflow sanity 接受的最小 Blacksmith Linux runner 标签上为 CodeQL 手动构建 Android 应用,并将结果上传到 `/codeql-critical-security/android` 类别。 -`CodeQL macOS Critical Security` 工作流是每周/手动的 macOS 安全分片。它会在 Blacksmith macOS 上为 CodeQL 手动构建 macOS 应用,从上传的 SARIF 中过滤掉依赖构建结果,并在 `/codeql-critical-security/macos` 类别下上传结果。将它保持在每日默认工作流之外,因为即使结果干净,macOS 构建也会主导运行时间。 +`CodeQL macOS Critical Security` 工作流是每周/手动 macOS 安全分片。它会在 Blacksmith macOS 上为 CodeQL 手动构建 macOS 应用,从上传的 SARIF 中过滤掉依赖构建结果,并将结果上传到 `/codeql-critical-security/macos` 类别。请将它保留在每日默认工作流之外,因为即使干净通过,macOS 构建也会主导运行时间。 -`CodeQL Critical Quality` 工作流是对应的非安全分片。它只在较小的 Blacksmith Linux runner 上,针对窄范围高价值表面运行错误严重级别的非安全 JavaScript/TypeScript 质量查询。它的基线作业会扫描与安全工作流相同的凭证、密钥、沙箱、cron 和 Gateway 网关表面。config-boundary 作业会在单独的 `/codeql-critical-quality/config-boundary` 类别下扫描配置 schema、迁移、规范化和 IO 契约。gateway-runtime-boundary 作业会在单独的 `/codeql-critical-quality/gateway-runtime-boundary` 类别下扫描 Gateway 网关协议 schema 和服务器方法契约。channel-runtime-boundary 作业会在单独的 `/codeql-critical-quality/channel-runtime-boundary` 类别下扫描核心渠道实现契约。agent-runtime-boundary 作业会在单独的 `/codeql-critical-quality/agent-runtime-boundary` 类别下扫描命令执行、模型/提供商分发、自动回复分发和队列,以及 ACP 控制平面运行时契约。plugin-boundary 作业会在单独的 `/codeql-critical-quality/plugin-boundary` 类别下扫描加载器、注册表、公开表面和插件 SDK 入口点契约。将该工作流与安全分开,以便质量发现可以在不掩盖安全信号的情况下被计划、度量、禁用或扩展。Swift、Python、UI 和内置插件的 CodeQL 扩展应仅在窄范围 profile 具备稳定运行时间和信号后,作为有作用域或分片的后续工作重新加入。 +`CodeQL Critical Quality` 工作流是对应的非安全分片。它只在较小的 Blacksmith Linux runner 上,对窄范围高价值表面运行错误严重级别的非安全 JavaScript/TypeScript 质量查询。其基线作业扫描与安全工作流相同的凭证、机密、沙箱、cron 和 gateway 表面。config-boundary 作业会在单独的 `/codeql-critical-quality/config-boundary` 类别下扫描配置 schema、迁移、规范化和 IO 契约。gateway-runtime-boundary 作业会在单独的 `/codeql-critical-quality/gateway-runtime-boundary` 类别下扫描 gateway 协议 schema 和服务器方法契约。channel-runtime-boundary 作业会在单独的 `/codeql-critical-quality/channel-runtime-boundary` 类别下扫描核心渠道实现契约。agent-runtime-boundary 作业会在单独的 `/codeql-critical-quality/agent-runtime-boundary` 类别下扫描命令执行、模型/提供商分发、自动回复分发和队列,以及 ACP 控制平面运行时契约。ui-control-plane 作业会在单独的 `/codeql-critical-quality/ui-control-plane` 类别下扫描 Control UI 引导、本地持久化、gateway 控制流和任务控制平面运行时契约。plugin-boundary 作业会在单独的 `/codeql-critical-quality/plugin-boundary` 类别下扫描 loader、registry、公共表面和插件 SDK 入口点契约。请将该工作流与安全工作流分开,以便质量发现可以在不遮蔽安全信号的情况下进行调度、度量、禁用或扩展。Swift、Python 和内置插件 CodeQL 扩展应仅在窄范围配置拥有稳定运行时间和信号之后,作为作用域化或分片的后续工作重新加入。 -`Docs Agent` 工作流是一个事件驱动的 Codex 维护通道,用于让现有文档与最近合并的变更保持一致。它没有纯计划任务:`main` 上成功的非 bot push CI 运行可以触发它,手动派发也可以直接运行它。当 `main` 已经前进,或过去一小时内已创建另一个未跳过的 Docs Agent 运行时,workflow-run 调用会跳过。运行时,它会审查从上一个未跳过的 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此每小时一次的运行可以覆盖自上次文档处理以来累积的所有 main 变更。 +`Docs Agent` 工作流是一个事件驱动的 Codex 维护通道,用于让现有文档与最近落地的变更保持一致。它没有纯定时计划:`main` 上一次成功的非 bot push CI 运行可以触发它,手动调度也可以直接运行它。当 `main` 已经前进,或者最近一小时内已创建另一个未跳过的 Docs Agent 运行时,workflow-run 调用会跳过。运行时,它会审查从上一个未跳过 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此一次每小时运行可以覆盖自上次文档处理以来累积的所有 main 变更。 -`Test Performance Agent` 工作流是一个用于慢测试的事件驱动 Codex 维护通道。它没有纯计划任务:`main` 上成功的非 bot push CI 运行可以触发它,但如果当天 UTC 已经有另一个 workflow-run 调用运行过或正在运行,它会跳过。手动派发会绕过这个每日活动门。该通道会构建全套分组 Vitest 性能报告,让 Codex 只做小型且保持覆盖率的测试性能修复,而不是大范围重构,然后重新运行全套报告,并拒绝会降低通过基线测试数量的变更。如果基线存在失败测试,Codex 只能修复明显失败,并且 agent 之后的全套报告必须通过后才会提交任何内容。当 `main` 在 bot push 落地前前进时,该通道会 rebase 已验证的补丁,重新运行 `pnpm check:changed`,并重试 push;存在冲突的过期补丁会被跳过。它使用 GitHub 托管的 Ubuntu,因此 Codex action 可以与 docs agent 保持相同的 drop-sudo 安全姿态。 +`Test Performance Agent` 工作流是一个事件驱动的 Codex 维护通道,用于处理慢测试。它没有纯定时计划:`main` 上一次成功的非 bot push CI 运行可以触发它,但如果当天 UTC 已经有另一个 workflow-run 调用运行过或正在运行,它会跳过。手动调度会绕过该每日活动门禁。该通道会构建全套分组 Vitest 性能报告,让 Codex 仅做小型、保留覆盖率的测试性能修复,而不是大范围重构,然后重新运行全套报告,并拒绝会降低通过基线测试数量的变更。如果基线存在失败测试,Codex 只能修复明显失败项,并且 after-agent 全套报告必须通过后才会提交任何内容。当 `main` 在 bot push 落地前前进时,该通道会 rebase 已验证的补丁,重新运行 `pnpm check:changed`,并重试 push;有冲突的过期补丁会被跳过。它使用 GitHub 托管 Ubuntu,因此 Codex action 可以保持与 docs agent 相同的 drop-sudo 安全姿态。 ```bash gh workflow run duplicate-after-merge.yml \ @@ -129,31 +128,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 正确性通道,例如内置/插件契约/协议检查 | Node 相关变更 | -| `checks-fast-contracts-channels` | 分片渠道契约检查,并提供稳定的聚合检查结果 | Node 相关变更 | -| `checks-node-extensions` | 覆盖插件套件的完整内置插件测试分片 | Node 相关变更 | -| `checks-node-core-test` | 核心 Node 测试分片,不包括渠道、内置、契约和插件通道 | Node 相关变更 | -| `check` | 分片的主本地门等价项:生产类型、lint、guard、测试类型和严格 smoke | Node 相关变更 | -| `check-additional` | 架构、边界、插件表面 guard、包边界和 gateway-watch 分片 | Node 相关变更 | -| `build-smoke` | 已构建 CLI smoke 测试和启动内存 smoke | Node 相关变更 | -| `checks` | 构建制品渠道测试的验证器 | Node 相关变更 | -| `checks-node-compat-node22` | Node 22 兼容性构建和 smoke 通道 | 发布的手动 CI 派发 | -| `check-docs` | 文档格式化、lint 和断链检查 | 文档变更 | -| `skills-python` | 面向 Python 支持的 Skills 的 Ruff + pytest | Python skill 相关变更 | -| `checks-windows` | Windows 特定进程/路径测试,以及共享运行时 import specifier 回归 | Windows 相关变更 | -| `macos-node` | 使用共享构建制品的 macOS TypeScript 测试通道 | macOS 相关变更 | -| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | macOS 相关变更 | -| `android` | 两种 flavor 的 Android 单元测试,以及一次 debug APK 构建 | Android 相关变更 | -| `test-performance-agent` | 受信活动后的每日 Codex 慢测试优化 | Main CI 成功或手动派发 | +| `preflight` | 检测仅文档变更、变更作用域、变更插件,并构建 CI manifest | 始终在非草稿 push 和 PR 上运行 | +| `security-scm-fast` | 通过 `zizmor` 进行私钥检测和工作流审计 | 始终在非草稿 push 和 PR 上运行 | +| `security-dependency-audit` | 针对 npm advisories 的无依赖生产 lockfile 审计 | 始终在非草稿 push 和 PR 上运行 | +| `security-fast` | 快速安全作业的必需聚合 | 始终在非草稿 push 和 PR 上运行 | +| `build-artifacts` | 构建 `dist/`、Control UI、构建工件检查和可复用下游工件 | Node 相关变更 | +| `checks-fast-core` | 快速 Linux 正确性通道,例如内置/插件契约/协议检查 | Node 相关变更 | +| `checks-fast-contracts-channels` | 分片渠道契约检查,带稳定的聚合检查结果 | Node 相关变更 | +| `checks-node-extensions` | 跨插件套件的完整内置插件测试分片 | Node 相关变更 | +| `checks-node-core-test` | 核心 Node 测试分片,不包括渠道、内置、契约和插件通道 | Node 相关变更 | +| `check` | 分片主本地门禁等价项:生产类型、lint、guard、测试类型和严格 smoke | Node 相关变更 | +| `check-additional` | 架构、边界、插件表面 guard、包边界和 gateway-watch 分片 | Node 相关变更 | +| `build-smoke` | 已构建 CLI smoke 测试和启动内存 smoke | Node 相关变更 | +| `checks` | 已构建工件渠道测试的验证器 | Node 相关变更 | +| `checks-node-compat-node22` | Node 22 兼容性构建和 smoke 通道 | 用于发布的手动 CI 调度 | +| `check-docs` | 文档格式化、lint 和断链检查 | 文档已变更 | +| `skills-python` | 用于 Python 支持 Skills 的 Ruff + pytest | Python Skills 相关变更 | +| `checks-windows` | Windows 特定的进程/路径测试,以及共享运行时 import specifier 回归 | Windows 相关变更 | +| `macos-node` | 使用共享构建工件的 macOS TypeScript 测试通道 | macOS 相关变更 | +| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | macOS 相关变更 | +| `android` | 两种 flavor 的 Android 单元测试,以及一次 debug APK 构建 | Android 相关变更 | +| `test-performance-agent` | 可信活动后的每日 Codex 慢测试优化 | Main CI 成功或手动调度 | -手动 CI 派发会运行与普通 CI 相同的作业图,但会强制开启每个作用域通道:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建 smoke、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。手动运行使用唯一的并发组,因此发布候选的全套运行不会被同一 ref 上的另一个 push 或 PR 运行取消。可选的 `target_ref` 输入允许受信调用方在使用所选派发 ref 的工作流文件时,针对分支、标签或完整提交 SHA 运行该作业图。 +手动 CI 调度会运行与普通 CI 相同的作业图,但会强制打开每个作用域通道:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建 smoke、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。手动运行使用唯一并发组,因此发布候选全套不会被同一 ref 上的另一个 push 或 PR 运行取消。可选的 `target_ref` 输入允许可信调用方针对分支、tag 或完整提交 SHA 运行该图,同时使用所选调度 ref 中的工作流文件。 ```bash gh workflow run ci.yml --ref release/YYYY.M.D @@ -163,54 +162,45 @@ 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 通道重叠运行,以便下游消费者能在共享构建就绪后立即开始。 +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` 中的单元测试覆盖。 -手动分发会跳过变更范围检测,并让预检清单 -表现得像每个受限范围都发生了变更。 -CI 工作流编辑会验证 Node CI 图以及工作流 lint,但本身不会强制运行 Windows、Android 或 macOS 原生构建;这些平台通道仍然只限于平台源代码变更。 -仅 CI 路由的编辑、选定的低成本核心测试夹具编辑,以及范围很窄的插件契约辅助工具/测试路由编辑,会使用快速的仅 Node 清单路径:预检、安全检查,以及一个 `checks-fast-core` 任务。该路径会在变更文件仅限于路由或辅助工具表面,且快速任务会直接覆盖这些表面时,避开构建产物、Node 22 兼容性、渠道契约、完整核心分片、内置插件分片,以及额外的保护矩阵。 -Windows Node 检查仅限于 Windows 专用的进程/路径包装器、npm/pnpm/UI 运行器辅助工具、包管理器配置,以及执行该通道的 CI 工作流表面;无关的源代码、插件、install-smoke 和仅测试变更会留在 Linux Node 通道上,因此不会为正常测试分片已经覆盖的内容占用 16-vCPU Windows 工作器。 -单独的 `install-smoke` 工作流会通过自己的 `preflight` 作业复用同一个范围脚本。它将冒烟覆盖拆分为 `run_fast_install_smoke` 和 `run_full_install_smoke`。拉取请求会针对 Docker/包表面、内置插件包/清单变更,以及 Docker 冒烟作业覆盖的核心插件/渠道/Gateway 网关/插件 SDK 表面运行快速路径。仅源代码的内置插件变更、仅测试编辑和仅文档编辑不会占用 Docker 工作器。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行智能体删除共享工作区 CLI 冒烟测试,运行容器 gateway-network e2e,验证内置扩展构建参数,并在 240 秒聚合命令超时内运行有界的内置插件 Docker 配置,同时分别限制每个场景的 Docker 运行时长。完整路径会为夜间计划运行、手动分发、workflow-call 发布检查,以及真正触及安装器/包/Docker 表面的拉取请求保留 QR 包安装和安装器 Docker/更新覆盖。`main` 推送(包括合并提交)不会强制走完整路径;当变更范围逻辑在推送上请求完整覆盖时,工作流会保留快速 Docker 冒烟测试,并把完整安装冒烟留给夜间或发布验证。较慢的 Bun 全局安装 image-provider 冒烟测试由 `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` 运行通道;用 `OPENCLAW_DOCKER_ALL_PARALLELISM` 调整默认值为 10 的主池槽位数,用 `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` 调整默认值为 10 的提供商敏感尾池槽位数。重型通道上限默认是 `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` 和 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`,这样 npm 安装和多服务通道不会让 Docker 过载,同时较轻的通道仍可填满可用槽位。单个比有效上限更重的通道仍可从空池启动,然后独占运行,直到释放容量。默认情况下通道启动会错开 2 秒,以避免本地 Docker 守护进程创建风暴;可用 `OPENCLAW_DOCKER_ALL_START_STAGGER_MS=0` 或其他毫秒值覆盖。本地聚合会预检 Docker,移除陈旧的 OpenClaw E2E 容器,输出活动通道 Status,持久化通道耗时以便按最长优先排序,并支持用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 检查调度器。默认情况下,它会在第一次失败后停止调度新的池化通道,并且每个通道都有 120 分钟的回退超时,可通过 `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` 覆盖;选定的实时/尾部通道使用更严格的单通道上限。`OPENCLAW_DOCKER_ALL_LANES=` 会运行精确的调度器通道,包括仅发布通道(如 `install-e2e`)和拆分后的内置更新通道(如 `bundled-channel-update-acpx`),同时跳过清理冒烟测试,以便智能体复现单个失败通道。可复用的实时/E2E 工作流会询问 `scripts/test-docker-all.mjs --plan-json` 需要哪些包、镜像类型、实时镜像、通道和凭证覆盖,然后 `scripts/docker-e2e.mjs` 会把该计划转换为 GitHub 输出和摘要。它会通过 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw,或下载当前运行的包产物,或从 `package_artifact_run_id` 下载包产物;验证 tarball 清单;当计划需要已安装包的通道时,通过 Blacksmith 的 Docker 层缓存构建并推送带有包摘要标签的裸/功能 GHCR Docker E2E 镜像;并复用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 输入或现有的包摘要镜像,而不是重新构建。`Package Acceptance` 工作流是高级包门禁:它会从 npm、受信任的 `package_ref`、HTTPS tarball 加 SHA-256,或先前工作流产物中解析候选项,然后把单个 `package-under-test` 产物传递给可复用 Docker E2E 工作流。它将 `workflow_ref` 与 `package_ref` 分开,使当前验收逻辑能够验证较旧的受信任提交,而无需检出旧工作流代码。发布检查会针对目标 ref 运行自定义 Package Acceptance 增量:内置渠道兼容性、离线插件夹具,以及针对已解析 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-plugins|plugins-runtime-services|plugins-runtime-install-a|plugins-runtime-install-b|plugins-runtime-install-c|plugins-runtime-install-d|bundled-channels`)。当完整发布路径覆盖请求 OpenWebUI 时,它会并入 `plugins-runtime-services`,并且只在仅 OpenWebUI 分发时保留独立的 `openwebui` 分块。旧版聚合分块名称 `package-update`、`plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 仍可用于手动重跑,但发布工作流使用拆分后的分块,因此安装器 E2E 和内置插件安装/卸载扫描不会主导关键路径。`install-e2e` 通道别名仍是两个提供商安装器通道的聚合手动重跑别名。`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 更新和 Doctor 修复轮次可以与其他内置检查分片运行。 +手动调度会跳过变更范围检测,并让预检清单表现得像每个限定范围都已变更。 +CI 工作流编辑会验证 Node CI 图以及工作流 lint,但本身不会强制运行 Windows、Android 或 macOS 原生构建;这些平台通道仍限定于平台源代码变更。 +仅 CI 路由的编辑、选定的廉价核心测试夹具编辑,以及窄范围的插件契约辅助程序/测试路由编辑,会使用快速的仅 Node 清单路径:预检、安全检查,以及单个 `checks-fast-core` 任务。当变更文件仅限于该快速任务直接覆盖的路由或辅助程序表面时,该路径会避开构建工件、Node 22 兼容性、渠道契约、完整核心分片、内置插件分片以及额外防护矩阵。 +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/包表面、内置插件包/清单变更,以及 Docker 冒烟作业会覆盖的核心插件/渠道/Gateway 网关/插件 SDK 表面运行快速路径。仅源代码的内置插件变更、仅测试编辑和仅文档编辑不会占用 Docker worker。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行 agents delete 共享工作区 CLI 冒烟,运行容器 Gateway 网关网络 e2e,验证内置插件构建参数,并在 240 秒的聚合命令超时内运行有界的内置插件 Docker profile,同时每个场景的 Docker run 都单独封顶。完整路径保留 QR 包安装和安装器 Docker/更新覆盖,用于夜间定时运行、手动调度、workflow-call 发布检查,以及真正触及安装器/包/Docker 表面的拉取请求。`main` 推送(包括合并提交)不会强制完整路径;当变更范围逻辑会在推送上请求完整覆盖时,工作流会保留快速 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` 运行通道;使用 `OPENCLAW_DOCKER_ALL_PARALLELISM` 调整默认主池槽位数 10,并使用 `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` 调整对提供商敏感的尾池槽位数 10。重型通道上限默认为 `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 容器,输出活动通道 Status,持久化通道耗时以便最长优先排序,并支持用 `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 层缓存构建并推送带有包摘要标签的裸/功能 GHCR Docker E2E 镜像;并复用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 输入或已有的包摘要镜像,而不是重新构建。`Package Acceptance` 工作流是高级包门禁:它会从 npm、受信任的 `package_ref`、HTTPS tarball 加 SHA-256,或先前的工作流工件解析候选项,然后将那个单一的 `package-under-test` 工件传入可复用 Docker E2E 工作流。它将 `workflow_ref` 与 `package_ref` 分开,因此当前验收逻辑可以验证较旧的受信任提交,而无需检出旧的工作流代码。发布检查会针对目标 ref 运行自定义 Package Acceptance delta:内置渠道兼容性、离线插件夹具,以及针对已解析 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-plugins|plugins-runtime-services|plugins-runtime-install-a|plugins-runtime-install-b|plugins-runtime-install-c|plugins-runtime-install-d|bundled-channels`)。当完整 release-path 覆盖请求 OpenWebUI 时,OpenWebUI 会并入 `plugins-runtime-services`,只有 OpenWebUI 专用调度才保留独立的 `openwebui` 分块。旧版聚合分块名称 `package-update`、`plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 仍可用于手动重跑,但发布工作流使用拆分分块,因此安装器 E2E 和内置插件安装/卸载扫查不会主导关键路径。`install-e2e` 通道别名仍是两个提供商安装器通道的聚合手动重跑别名。`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 工作流每天运行完整的 release-path Docker 套件。内置更新矩阵按更新目标拆分,因此重复的 npm update 和 Doctor 修复过程可以与其他内置检查分片运行。 -当前发布 Docker 分块是 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、`plugins-runtime-install-a`、`plugins-runtime-install-b`、`plugins-runtime-install-c`、`plugins-runtime-install-d`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`。聚合 `bundled-channels` 分块仍可用于手动一次性重跑,`plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 也仍保留为聚合插件/运行时别名,但发布工作流使用拆分后的分块,因此渠道冒烟、更新目标、插件运行时检查,以及内置插件安装/卸载扫描可以并行运行。目标 `docker_lanes` 分发也会在一个共享包/镜像准备步骤之后,将多个选定通道拆分为并行作业,并且内置渠道更新通道会针对临时 npm 网络故障重试一次。 +当前发布 Docker 分块为 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、`plugins-runtime-install-a`、`plugins-runtime-install-b`、`plugins-runtime-install-c`、`plugins-runtime-install-d`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`。聚合 `bundled-channels` 分块仍可用于手动一次性重跑,`plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 也仍保留为聚合插件/运行时别名,但发布工作流使用拆分分块,因此渠道冒烟、更新目标、插件运行时检查以及内置插件安装/卸载扫查可以并行运行。目标 `docker_lanes` 调度还会在一个共享包/镜像准备步骤后,将多个选定通道拆分为并行作业,并且内置渠道更新通道会针对临时 npm 网络失败重试一次。 -本地变更通道逻辑位于 `scripts/changed-lanes.mjs`,并由 `scripts/check-changed.mjs` 执行。该本地检查门禁对架构边界的要求比宽泛的 CI 平台范围更严格:核心生产变更会运行核心生产和核心测试类型检查以及核心 lint/保护检查,仅核心测试变更只运行核心测试类型检查和核心 lint,扩展生产变更会运行扩展生产和扩展测试类型检查以及扩展 lint,仅扩展测试变更会运行扩展测试类型检查和扩展 lint。公共插件 SDK 或插件契约变更会扩展到扩展类型检查,因为扩展依赖这些核心契约,但 Vitest 扩展扫描是显式测试工作。仅发布元数据的版本号变更会运行目标版本/配置/根依赖检查。未知的根/配置变更会保守地退回到所有检查通道。 -本地变更测试路由位于 `scripts/test-projects.test-support.mjs`,并且 -有意比 `check:changed` 更低成本:直接测试编辑会运行自身, -源代码编辑优先使用显式映射,然后是同级测试和导入图 -依赖项。共享 group-room 投递配置是显式映射之一: -对群组可见回复配置、源回复投递模式或 -message-tool 系统提示词的变更,会路由到核心回复测试以及 Discord 和 -Slack 投递回归测试,因此共享默认值变更会在第一次 PR -推送前失败。仅当变更足够覆盖整个 harness,低成本映射集合不能作为可信代理时, -才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 +本地变更车道逻辑位于 `scripts/changed-lanes.mjs`,并由 `scripts/check-changed.mjs` 执行。该本地检查门禁对架构边界的要求比宽泛的 CI 平台范围更严格:核心生产变更会运行核心生产和核心测试类型检查,以及核心 lint/guard;仅核心测试变更只运行核心测试类型检查以及核心 lint;插件生产变更会运行插件生产和插件测试类型检查,以及插件 lint;仅插件测试变更会运行插件测试类型检查以及插件 lint。公开的插件 SDK 或插件契约变更会扩展到插件类型检查,因为插件依赖这些核心契约,但 Vitest 插件扫描属于显式测试工作。仅发布元数据的版本升级会运行有针对性的版本/配置/根依赖检查。未知的根目录/配置变更会以安全失败方式进入所有检查车道。 +本地变更测试路由位于 `scripts/test-projects.test-support.mjs`,并且有意比 `check:changed` 更低成本:直接测试编辑会运行自身,源码编辑优先使用显式映射,然后是同级测试和导入图依赖项。共享群组房间投递配置是显式映射之一:对群组可见回复配置、源回复投递模式或消息工具系统提示词的变更,会通过核心回复测试以及 Discord 和 Slack 投递回归测试路由,因此共享默认值变更会在第一次 PR 推送前失败。只有当变更覆盖整个 harness,以至于低成本映射集合不再是可信代理时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 -进行 Testbox 验证时,请从仓库根目录运行;对于范围较广的证明,优先使用新预热的 box。在把缓慢的关卡耗在被复用、已过期,或刚报告了异常大规模同步的 box 之前,先在该 box 内运行 `pnpm testbox:sanity`。当必需的根文件(例如 `pnpm-lock.yaml`)消失,或 `git status --short` 显示至少 200 个已跟踪文件被删除时,完整性检查会快速失败。这通常表示远程同步状态不是该 PR 的可信副本。应停止该 box 并预热一个新的,而不是调试产品测试失败。对于有意进行大规模删除的 PR,请为该次完整性检查设置 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 +对于 Testbox 验证,请从仓库根目录运行,并优先为宽泛证明使用新预热的 box。在把慢速门禁花在已复用、已过期或刚报告异常大同步的 box 上之前,先在 box 内运行 `pnpm testbox:sanity`。当所需根文件(例如 `pnpm-lock.yaml`)消失,或 `git status --short` 显示至少 200 个已跟踪删除时,完整性检查会快速失败。这通常意味着远程同步状态不是 PR 的可信副本。停止该 box 并预热一个新的,而不是调试产品测试失败。对于有意的大规模删除 PR,请为该完整性运行设置 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 -手动 CI 调度会运行 `checks-node-compat-node22` 作为候选发布版本的兼容性覆盖。普通拉取请求和 `main` 推送会跳过该通道,让矩阵聚焦在 Node 24 测试/渠道通道上。 +手动 CI 派发会运行 `checks-node-compat-node22`,作为发布候选兼容性覆盖。普通拉取请求和 `main` 推送会跳过该车道,让矩阵专注于 Node 24 测试/渠道车道。 -最慢的 Node 测试族会被拆分或均衡,以便每个作业保持较小规模,同时不超额预留运行器:渠道契约会作为三个加权分片运行,内置插件测试会在六个 extension worker 间均衡,小型核心单元通道会成对运行,auto-reply 会作为四个均衡 worker 运行,并将 reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片,agentic Gateway 网关/插件配置会分散到现有仅源码 agentic Node 作业中,而不是等待构建产物。广泛的浏览器、QA、媒体和杂项插件测试使用各自专用的 Vitest 配置,而不是共享插件总括配置。Extension 分片作业一次最多运行两个插件配置组,每组一个 Vitest worker,并使用更大的 Node 堆,因此导入繁重的插件批次不会创建额外 CI 作业。广泛的 agents 通道使用共享的 Vitest 文件并行调度器,因为它主要受导入/调度影响,而不是由单个慢测试文件主导。`runtime-config` 会与 infra core-runtime 分片一起运行,避免共享 runtime 分片承担尾部耗时。包含模式分片会使用 CI 分片名称记录计时条目,因此 `.artifacts/vitest-shard-timings.json` 可以区分完整配置和经过筛选的分片。`check-additional` 会把 package-boundary 编译/canary 工作放在一起,并将运行时拓扑架构与 Gateway 网关 watch 覆盖分开;boundary guard 分片会在一个作业内并发运行其小型独立 guard。Gateway 网关 watch、渠道测试和核心 support-boundary 分片会在 `dist/` 和 `dist-runtime/` 已构建后,在 `build-artifacts` 内并发运行,保留它们旧有的检查名称作为轻量验证作业,同时避免两个额外 Blacksmith worker 和第二个产物消费者队列。 -Android CI 会同时运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play debug APK。第三方 flavor 没有单独的 source set 或 manifest;它的单元测试通道仍会使用 SMS/call-log BuildConfig 标志编译该 flavor,同时避免在每次 Android 相关推送中重复执行 debug APK 打包作业。 -当同一 PR 或 `main` ref 上有更新推送落地时,GitHub 可能会将被取代的作业标记为 `cancelled`。除非同一 ref 的最新运行也在失败,否则应将其视为 CI 噪声。聚合分片检查使用 `!cancelled() && always()`,因此它们仍会报告正常分片失败,但在整个 workflow 已被取代后不会继续排队。 -自动 CI 并发键带有版本号(`CI-v7-*`),因此 GitHub 侧旧队列组中的僵尸项无法无限期阻塞较新的 main 运行。手动全套件运行使用 `CI-manual-v1-*`,并且不会取消正在进行的运行。 +最慢的 Node 测试族会被拆分或均衡,以便每个作业保持较小规模且不过度预留 runner:渠道契约以三个加权分片运行,内置插件测试在六个插件 worker 间均衡,小型核心单元车道会成对运行,自动回复以四个均衡 worker 运行,并将回复子树拆分为 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` 将包边界编译/canary 工作放在一起,并将运行时拓扑架构与 Gateway 网关 watch 覆盖分离;边界 guard 分片会在一个作业内并发运行其小型独立 guard。Gateway 网关 watch、渠道测试和核心支持边界分片会在 `dist/` 与 `dist-runtime/` 已构建完成后,在 `build-artifacts` 内并发运行,保留它们旧有的检查名称作为轻量验证作业,同时避免两个额外的 Blacksmith worker 和第二个产物消费者队列。 +Android CI 会同时运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play debug APK。第三方 flavor 没有单独的 source set 或 manifest;其单元测试车道仍会使用 SMS/通话记录 BuildConfig 标志编译该 flavor,同时避免在每次 Android 相关推送时重复执行 debug APK 打包作业。 +当同一 PR 或 `main` ref 上有更新推送落地时,GitHub 可能会将被取代的作业标记为 `cancelled`。除非同一 ref 的最新运行也失败,否则将其视为 CI 噪声。聚合分片检查使用 `!cancelled() && always()`,因此它们仍会报告正常的分片失败,但不会在整个工作流已被取代后继续排队。 +自动 CI 并发键带有版本号(`CI-v7-*`),因此 GitHub 端旧队列组中的僵尸任务不会无限期阻塞较新的 main 运行。手动全套件运行使用 `CI-manual-v1-*`,且不会取消正在进行的运行。 -## 运行器 +## Runners -| 运行器 | 作业 | +| 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 矩阵可以更早排队 | -| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`、较低权重 extension 分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 和 `check-test-types` | +| `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-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`、较低权重的插件分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 和 `check-test-types` | | `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` | +| `blacksmith-6vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-node`;fork 回退到 `macos-latest` | +| `blacksmith-12vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-swift`;fork 回退到 `macos-latest` | ## 本地等价命令 diff --git a/docs/zh-CN/plugins/architecture-internals.md b/docs/zh-CN/plugins/architecture-internals.md index 415fcfbe0..4b944f5c9 100644 --- a/docs/zh-CN/plugins/architecture-internals.md +++ b/docs/zh-CN/plugins/architecture-internals.md @@ -3,25 +3,25 @@ read_when: - 实现提供商运行时钩子、渠道生命周期或包集合 - 调试插件加载顺序或注册表状态 - 添加新的插件能力或上下文引擎插件 -summary: 插件架构内部机制:加载流水线、注册表、运行时钩子、HTTP 路由和参考表 +summary: 插件架构内部机制:加载管线、注册表、运行时钩子、HTTP 路由和参考表 title: 插件架构内部机制 x-i18n: - generated_at: "2026-04-29T02:56:03Z" + generated_at: "2026-04-29T03:28:37Z" model: gpt-5.5 provider: openai - source_hash: 8bf4d19b962e92580d39b45f6171d937d2d23f3491a32a304bfd62510197ab3e + source_hash: 24f6b5d20bbd7f0f33e8e6bcbd9b0769e7e7c335530e19c4b85f60cb3b5b070e source_path: plugins/architecture-internals.md workflow: 16 --- -关于公开能力模型、插件形态以及所有权/执行契约,请参阅[插件架构](/zh-CN/plugins/architecture)。本页是内部机制的参考:加载管线、注册表、运行时钩子、Gateway 网关 HTTP 路由、导入路径和模式表。 +有关公共能力模型、插件形态以及所有权/执行契约,请参阅[插件架构](/zh-CN/plugins/architecture)。本页是内部机制的参考:加载流水线、注册表、运行时钩子、Gateway 网关 HTTP 路由、导入路径和 schema 表。 -## 加载管线 +## 加载流水线 启动时,OpenClaw 大致会执行以下操作: 1. 发现候选插件根目录 -2. 读取原生或兼容 bundle 清单和包元数据 +2. 读取原生或兼容 bundle manifest 以及 package 元数据 3. 拒绝不安全的候选项 4. 规范化插件配置(`plugins.enabled`、`allow`、`deny`、`entries`、 `slots`、`load.paths`) @@ -32,75 +32,68 @@ x-i18n: 8. 将注册表暴露给命令/运行时界面 -`activate` 是 `register` 的旧版别名 — 加载器会解析当前存在的那个(`def.register ?? def.activate`),并在同一时点调用它。所有内置插件都使用 `register`;新插件请优先使用 `register`。 +`activate` 是 `register` 的旧版别名 — 加载器会解析存在的那个(`def.register ?? def.activate`),并在同一时点调用它。所有内置插件都使用 `register`;新插件请优先使用 `register`。 -安全门禁发生在运行时执行**之前**。当入口逃逸出插件根目录、路径可被所有用户写入,或非内置插件的路径所有权看起来可疑时,候选项会被阻止。 +安全门控发生在运行时执行**之前**。当入口逃逸出插件根目录、路径可被全局写入,或非内置插件的路径所有权看起来可疑时,候选项会被阻止。 -### 清单优先行为 +### Manifest 优先行为 -清单是控制平面的事实来源。OpenClaw 使用它来: +Manifest 是控制平面的事实来源。OpenClaw 使用它来: - 识别插件 -- 发现声明的渠道/Skills/配置模式或 bundle 能力 +- 发现已声明的渠道/Skills/配置 schema 或 bundle 能力 - 验证 `plugins.entries..config` -- 增强控制 UI 标签/占位符 +- 补充 Control UI 标签/占位符 - 显示安装/目录元数据 -- 在不加载插件运行时的情况下保留低成本激活和设置描述符 +- 在不加载插件运行时的情况下保留轻量激活和设置描述符 -对于原生插件,运行时模块是数据平面部分。它注册钩子、工具、命令或提供商流程等实际行为。 +对于原生插件,运行时模块是数据平面部分。它注册实际行为,例如钩子、工具、命令或提供商流程。 -可选清单 `activation` 和 `setup` 块保留在控制平面上。它们是用于激活规划和设置发现的纯元数据描述符;它们不会替代运行时注册、`register(...)` 或 `setupEntry`。第一批实时激活消费者现在会使用清单命令、渠道和提供商提示,在更广泛的注册表物化之前缩小插件加载范围: +可选的 manifest `activation` 和 `setup` 块保留在控制平面上。它们是仅含元数据的描述符,用于激活规划和设置发现;它们不会取代运行时注册、`register(...)` 或 `setupEntry`。首批实时激活消费者现在使用 manifest 命令、渠道和提供商提示,在更广泛的注册表物化之前缩小插件加载范围: - CLI 加载会缩小到拥有所请求主命令的插件 -- 渠道设置/插件解析会缩小到拥有所请求 - 渠道 ID 的插件 -- 显式提供商设置/运行时解析会缩小到拥有所请求 - 提供商 ID 的插件 -- Gateway 网关启动规划使用 `activation.onStartup` 处理显式启动 - 导入和启动退出;随着 OpenClaw 从隐式启动导入迁移出去,每个插件都应声明它,而没有静态 - 能力元数据且没有 `activation.onStartup` 的插件仍会使用 - 已弃用的隐式启动 sidecar 回退以保持兼容性 +- 渠道设置/插件解析会缩小到拥有所请求渠道 id 的插件 +- 显式提供商设置/运行时解析会缩小到拥有所请求提供商 id 的插件 +- Gateway 网关启动规划会使用 `activation.onStartup` 处理显式启动导入和启动选择退出;随着 OpenClaw 摆脱隐式启动导入,每个插件都应声明它,而没有静态能力元数据且没有 `activation.onStartup` 的插件仍会使用已弃用的隐式启动 sidecar 回退以保持兼容 -激活规划器既为现有调用方暴露仅包含 ID 的 API,也为新诊断暴露规划 API。规划条目会报告插件被选中的原因,将显式 `activation.*` 规划器提示与清单所有权回退区分开来,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和钩子。这种原因拆分就是兼容性边界:现有插件元数据会继续工作,而新代码可以在不改变运行时加载语义的情况下检测宽泛提示或回退行为。 +激活规划器既为现有调用方暴露仅包含 id 的 API,也为新的诊断暴露计划 API。计划条目会报告插件被选中的原因,将显式 `activation.*` 规划器提示与 manifest 所有权回退区分开来,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和钩子。这个原因拆分就是兼容边界:现有插件元数据会继续工作,而新代码可以检测宽泛提示或回退行为,而无需改变运行时加载语义。 -设置发现现在优先使用描述符拥有的 ID,例如 `setup.providers` 和 `setup.cliBackends`,以便在回退到仍需要设置时运行时钩子的插件的 `setup-api` 之前缩小候选插件范围。提供商设置列表会使用清单 `providerAuthChoices`、从描述符派生的设置选项以及安装目录元数据,而不加载提供商运行时。显式 `setup.requiresRuntime: false` 是仅描述符的截止点;省略 `requiresRuntime` 会保留旧版 setup-api 回退以保持兼容性。如果多个已发现插件声明同一个规范化后的设置提供商或 CLI 后端 ID,设置查找会拒绝这个含糊的所有者,而不是依赖发现顺序。当设置运行时确实执行时,注册表诊断会报告 `setup.providers` / `setup.cliBackends` 与 setup-api 注册的提供商或 CLI 后端之间的漂移,但不会阻止旧版插件。 +设置发现现在优先使用描述符拥有的 id,例如 `setup.providers` 和 `setup.cliBackends`,在回退到 `setup-api` 之前缩小候选插件范围,供那些仍需要设置时运行时钩子的插件使用。提供商设置列表会使用 manifest `providerAuthChoices`、描述符派生的设置选项和安装目录元数据,而不加载提供商运行时。显式 `setup.requiresRuntime: false` 是仅描述符的截止点;省略 `requiresRuntime` 会保留旧版 setup-api 回退以保持兼容。如果多个发现到的插件声明了同一个规范化后的设置提供商或 CLI 后端 id,设置查找会拒绝这个模糊所有者,而不是依赖发现顺序。当设置运行时确实执行时,注册表诊断会报告 `setup.providers` / `setup.cliBackends` 与 setup-api 注册的提供商或 CLI 后端之间的漂移,但不会阻止旧版插件。 ### 插件缓存边界 -OpenClaw 不会在基于墙钟时间的窗口后面缓存插件发现结果或直接清单注册表数据。安装、清单编辑和加载路径变更必须在下一次显式元数据读取或快照重建时可见。 +OpenClaw 不会在基于挂钟时间的窗口后面缓存插件发现结果或直接 manifest 注册表数据。安装、manifest 编辑和加载路径更改必须在下一次显式元数据读取或快照重建时可见。 -安全的元数据快速路径是显式对象所有权,而不是隐藏缓存。Gateway 网关启动热路径应通过调用链传递当前的 `PluginMetadataSnapshot`、派生的 `PluginLookUpTable` 或显式清单注册表。配置验证、启动自动启用、插件引导、设置查找和提供商选择可以复用这些对象,只要它们表示的是当前配置和插件清单。当该输入变化时,应重建并替换快照,而不是修改它或保留历史副本。 -对活动插件注册表的视图和内置渠道引导辅助工具应从当前注册表/根目录重新计算。短生命周期映射可以在一次调用内部用于去重工作或防止重入;它们不得变成进程元数据缓存。 +安全的元数据快速路径是显式对象所有权,而不是隐藏缓存。Gateway 网关启动热路径应通过调用链传递当前的 `PluginMetadataSnapshot`、派生的 `PluginLookUpTable` 或显式 manifest 注册表。配置验证、启动自动启用、插件引导和提供商选择可以复用这些对象,只要它们代表当前配置和插件清单。设置查找仍会按需重建 manifest 元数据,除非特定设置路径收到显式 manifest 注册表;请将其保留为冷路径回退,而不是添加隐藏查找缓存。当输入发生变化时,重建并替换快照,而不是修改它或保留历史副本。 +活动插件注册表上的视图和内置渠道引导辅助函数应从当前注册表/根目录重新计算。短生命周期 map 可以在单次调用内用于去重工作或防止重入;它们不得变成进程元数据缓存。 -对于插件加载,持久缓存层是运行时加载。当代码或已安装产物确实被加载时,它可以复用加载器状态,例如: +对于插件加载,持久缓存层是运行时加载。当代码或已安装工件确实被加载时,它可以复用加载器状态,例如: - `PluginLoaderCacheState` 和兼容的活动运行时注册表 -- 用于避免反复导入同一运行时界面的 jiti/模块缓存和公共界面加载器缓存 -- 已安装插件产物的运行时依赖镜像和文件系统缓存 -- 用于路径规范化或重复解析的短生命周期逐调用映射 +- jiti/module 缓存和公共界面加载器缓存,用于避免重复导入同一个运行时界面 +- 已安装插件工件的运行时依赖镜像和文件系统缓存 +- 用于路径规范化或重复解析的短生命周期按调用 map -这些缓存是数据平面实现细节。它们不得回答控制平面问题,例如“哪个插件拥有此提供商?”,除非调用方有意请求了运行时加载。 +这些缓存是数据平面实现细节。它们不得回答诸如“哪个插件拥有这个提供商?”之类的控制平面问题,除非调用方有意请求了运行时加载。 -不要为以下内容添加持久缓存或基于墙钟时间的缓存: +不要为以下内容添加持久缓存或挂钟时间缓存: - 发现结果 -- 直接清单注册表 -- 从已安装插件索引重建的清单注册表 -- 提供商所有者查找、模型抑制、提供商策略或公共产物 - 元数据 -- 任何其他从清单派生的答案,其中变更后的清单、已安装索引 - 或加载路径应在下一次元数据读取时可见 +- 直接 manifest 注册表 +- 从已安装插件索引重建的 manifest 注册表 +- 提供商所有者查找、模型抑制、提供商策略或公共工件元数据 +- 任何其他 manifest 派生答案,其中已更改的 manifest、已安装索引或加载路径应在下一次元数据读取时可见 -从持久化已安装插件索引重建清单元数据的调用方会按需重建该注册表。已安装索引是持久的源平面状态;它不是隐藏的进程内元数据缓存。 +从持久化的已安装插件索引重建 manifest 元数据的调用方会按需重建该注册表。已安装索引是持久的源平面状态;它不是隐藏的进程内元数据缓存。 ## 注册表模型 -已加载的插件不会直接修改随机核心全局变量。它们会注册到一个中央插件注册表中。 +已加载的插件不会直接修改任意核心全局变量。它们会注册到中央插件注册表中。 注册表会跟踪: -- 插件记录(身份、来源、源头、Status、诊断) +- 插件记录(身份、来源、原点、Status、诊断) - 工具 - 旧版钩子和类型化钩子 - 渠道 @@ -111,16 +104,16 @@ OpenClaw 不会在基于墙钟时间的窗口后面缓存插件发现结果或 - 后台服务 - 插件拥有的命令 -随后,核心功能会从该注册表读取,而不是直接与插件模块通信。这使加载保持单向: +然后,核心功能会从该注册表读取,而不是直接与插件模块通信。这让加载保持单向: - 插件模块 -> 注册表注册 - 核心运行时 -> 注册表消费 -这种分离对可维护性很重要。它意味着大多数核心界面只需要一个集成点:“读取注册表”,而不是“为每个插件模块做特殊处理”。 +这种分离对可维护性很重要。这意味着大多数核心界面只需要一个集成点:“读取注册表”,而不是“为每个插件模块做特殊处理”。 ## 对话绑定回调 -绑定对话的插件可以在审批完成时作出反应。 +绑定对话的插件可以在审批被解析时作出响应。 使用 `api.onConversationBindingResolved(...)` 在绑定请求被批准或拒绝后接收回调: @@ -147,87 +140,86 @@ export default { - `status`:`"approved"` 或 `"denied"` - `decision`:`"allow-once"`、`"allow-always"` 或 `"deny"` - `binding`:已批准请求的已解析绑定 -- `request`:原始请求摘要、分离提示、发送方 ID 和 - 对话元数据 +- `request`:原始请求摘要、分离提示、发送方 id 和对话元数据 -此回调仅用于通知。它不会改变允许谁绑定对话,并且会在核心审批处理完成后运行。 +此回调仅用于通知。它不会改变谁被允许绑定对话,并且会在核心审批处理完成后运行。 ## 提供商运行时钩子 提供商插件有三层: -- 用于低成本运行时前查找的**清单元数据**: +- **Manifest 元数据**,用于轻量的运行时前查找: `setup.providers[].envVars`、已弃用的兼容性 `providerAuthEnvVars`、 `providerAuthAliases`、`providerAuthChoices` 和 `channelEnvVars`。 - **配置时钩子**:`catalog`(旧版 `discovery`)加上 `applyConfigDefaults`。 -- **运行时钩子**:40 多个可选钩子,覆盖认证、模型解析、 +- **运行时钩子**:40 多个可选钩子,覆盖凭证、模型解析、 流包装、思考等级、重放策略和用量端点。请参阅 [钩子顺序和用法](#hook-order-and-usage)下的完整列表。 -OpenClaw 仍拥有通用 Agent loop、故障转移、转录处理和工具策略。这些钩子是在不需要完整自定义推理传输的情况下支持提供商特定行为的扩展界面。 +OpenClaw 仍拥有通用 Agent loop、故障转移、转录处理和工具策略。这些钩子是提供商特定行为的扩展界面,不需要完整的自定义推理传输。 -当提供商具有基于环境的凭证,并且通用认证/Status/模型选择器路径应在不加载插件运行时的情况下看到这些凭证时,请使用清单 `setup.providers[].envVars`。已弃用的 `providerAuthEnvVars` 在弃用窗口期间仍会由兼容性适配器读取,使用它的非内置插件会收到清单诊断。当一个提供商 ID 应复用另一个提供商 ID 的环境变量、认证配置文件、配置支持的认证和 API 密钥新手引导选项时,请使用清单 `providerAuthAliases`。当新手引导/认证选择 CLI 界面应在不加载提供商运行时的情况下了解提供商的选择 ID、分组标签和简单的单标志认证接线时,请使用清单 `providerAuthChoices`。请将提供商运行时 `envVars` 保留用于面向操作员的提示,例如新手引导标签或 OAuth 客户端 ID/客户端密钥设置变量。 +当提供商具有基于环境变量的凭证,并且通用凭证/Status/模型选择器路径应在不加载插件运行时的情况下看到这些凭证时,请使用 manifest `setup.providers[].envVars`。已弃用的 `providerAuthEnvVars` 在弃用窗口期间仍会由兼容性适配器读取,使用它的非内置插件会收到 manifest 诊断。当一个提供商 id 应复用另一个提供商 id 的环境变量、凭证配置文件、配置支持的凭证和 API 密钥新手引导选项时,请使用 manifest `providerAuthAliases`。当新手引导/凭证选择 CLI 界面应在不加载提供商运行时的情况下了解提供商的选项 id、分组标签和简单的单标志凭证接线时,请使用 manifest `providerAuthChoices`。将提供商运行时 `envVars` 保留给面向操作者的提示,例如新手引导标签或 OAuth client-id/client-secret 设置变量。 -当渠道具有由环境驱动的认证或设置,并且通用 shell 环境回退、配置/Status 检查或设置提示应在不加载渠道运行时的情况下看到它们时,请使用清单 `channelEnvVars`。 +当渠道具有由环境变量驱动的凭证或设置,并且通用 shell 环境回退、配置/Status 检查或设置提示应在不加载渠道运行时的情况下看到它们时,请使用 manifest `channelEnvVars`。 ### 钩子顺序和用法 -对于模型/提供商插件,OpenClaw 会按以下大致顺序调用钩子。 -“When to use”列是快速决策指南。 +对于模型/提供商插件,OpenClaw 会按大致如下顺序调用钩子。 +“When to use” 列是快速决策指南。 -| # | 钩子 | 作用 | 使用场景 | +| # | 钩子 | 作用 | 何时使用 | | --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `catalog` | 在生成 `models.json` 期间,将提供商配置发布到 `models.providers` | 提供商拥有目录或基础 URL 默认值 | -| 2 | `applyConfigDefaults` | 在配置物化期间应用提供商拥有的全局配置默认值 | 默认值取决于认证模式、环境或提供商模型系列语义 | -| -- | _(内置模型查找)_ | OpenClaw 会先尝试普通注册表/目录路径 | _(不是插件钩子)_ | -| 3 | `normalizeModelId` | 在查找前规范化旧版或预览版模型 ID 别名 | 提供商负责在规范模型解析前清理别名 | -| 4 | `normalizeTransport` | 在通用模型组装前规范化提供商系列的 `api` / `baseUrl` | 提供商负责清理同一传输系列中自定义提供商 ID 的传输 | -| 5 | `normalizeConfig` | 在运行时/提供商解析前规范化 `models.providers.` | 提供商需要由插件负责的配置清理;内置 Google 系列助手也会兜底支持的 Google 配置条目 | -| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式用量兼容性重写 | 提供商需要由端点驱动的原生流式用量元数据修复 | -| 7 | `resolveConfigApiKey` | 在运行时认证加载前,为配置提供商解析环境标记认证 | 提供商拥有由提供商负责的环境标记 API 密钥解析;`amazon-bedrock` 也在这里有一个内置 AWS 环境标记解析器 | -| 8 | `resolveSyntheticAuth` | 暴露本地/自托管或配置支持的认证,而不持久化明文 | 提供商可以使用合成/本地凭证标记运行 | -| 9 | `resolveExternalAuthProfiles` | 叠加提供商拥有的外部认证配置文件;对于 CLI/应用拥有的凭证,默认 `persistence` 为 `runtime-only` | 提供商复用外部认证凭证,而不持久化复制的刷新令牌;在清单中声明 `contracts.externalAuthProviders` | -| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的合成配置文件占位符降级到环境/配置支持的认证之后 | 提供商存储的合成占位符配置文件不应获得优先级 | -| 11 | `resolveDynamicModel` | 针对尚不在本地注册表中的提供商自有模型 ID 进行同步回退 | 提供商接受任意上游模型 ID | +| 1 | `catalog` | 在生成 `models.json` 期间将提供商配置发布到 `models.providers` | 提供商拥有目录或基础 URL 默认值 | +| 2 | `applyConfigDefaults` | 在配置物化期间应用提供商自有的全局配置默认值 | 默认值取决于认证模式、环境或提供商模型族语义 | +| -- | _(内置模型查找)_ | OpenClaw 会先尝试正常的注册表/目录路径 | _(不是插件钩子)_ | +| 3 | `normalizeModelId` | 在查找前规范化旧版或预览版模型 ID 别名 | 提供商在规范模型解析前负责清理别名 | +| 4 | `normalizeTransport` | 在通用模型组装前规范化提供商族的 `api` / `baseUrl` | 提供商负责清理同一传输族中自定义提供商 ID 的传输设置 | +| 5 | `normalizeConfig` | 在运行时/提供商解析前规范化 `models.providers.` | 提供商需要与插件同处的配置清理;内置 Google 族助手也会兜底支持的 Google 配置条目 | +| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式用量兼容重写 | 提供商需要由端点驱动的原生流式用量元数据修复 | +| 7 | `resolveConfigApiKey` | 在运行时认证加载前为配置提供商解析环境标记认证 | 提供商拥有自有的环境标记 API-key 解析;`amazon-bedrock` 也在这里有一个内置的 AWS 环境标记解析器 | +| 8 | `resolveSyntheticAuth` | 暴露本地/自托管或配置支持的认证,且不持久化明文 | 提供商可以使用合成/本地凭证标记运行 | +| 9 | `resolveExternalAuthProfiles` | 叠加提供商自有的外部认证配置文件;CLI/应用自有凭证的默认 `persistence` 为 `runtime-only` | 提供商复用外部认证凭证,而不持久化复制的刷新令牌;在 manifest 中声明 `contracts.externalAuthProviders` | +| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的合成配置文件占位符降级到环境/配置支持的认证之后 | 提供商存储了不应优先胜出的合成占位符配置文件 | +| 11 | `resolveDynamicModel` | 为尚未进入本地注册表的提供商自有模型 ID 同步兜底 | 提供商接受任意上游模型 ID | | 12 | `prepareDynamicModel` | 异步预热,然后再次运行 `resolveDynamicModel` | 提供商在解析未知 ID 前需要网络元数据 | -| 13 | `normalizeResolvedModel` | 在嵌入式运行器使用已解析模型前进行最终重写 | 提供商需要传输重写,但仍使用核心传输 | -| 14 | `contributeResolvedModelCompat` | 为位于另一个兼容传输后的供应商模型贡献兼容性标志 | 提供商可在代理传输上识别自己的模型,而无需接管该提供商 | -| 15 | `capabilities` | 由共享核心逻辑使用的提供商自有 transcript/工具元数据 | 提供商需要 transcript/提供商系列特殊处理 | -| 16 | `normalizeToolSchemas` | 在嵌入式运行器看到工具 schema 前规范化它们 | 提供商需要传输系列的 schema 清理 | -| 17 | `inspectToolSchemas` | 在规范化后暴露提供商自有的 schema 诊断 | 提供商想要关键字警告,而不把提供商特定规则教给核心 | -| 18 | `resolveReasoningOutputMode` | 选择原生或带标签的推理输出契约 | 提供商需要带标签的推理/最终输出,而不是原生字段 | -| 19 | `prepareExtraParams` | 在通用流式选项包装器之前进行请求参数规范化 | 提供商需要默认请求参数或按提供商清理参数 | -| 20 | `createStreamFn` | 用自定义传输完全替换普通流式路径 | 提供商需要自定义线路协议,而不只是包装器 | -| 21 | `wrapStreamFn` | 在应用通用包装器后进行流式包装 | 提供商需要请求标头/正文/模型兼容性包装器,而不需要自定义传输 | -| 22 | `resolveTransportTurnState` | 附加原生的逐轮传输标头或元数据 | 提供商希望通用传输发送提供商原生的轮次身份 | -| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 标头或会话冷却策略 | 提供商希望通用 WS 传输调节会话标头或回退策略 | +| 13 | `normalizeResolvedModel` | 嵌入式运行器使用已解析模型前的最终重写 | 提供商需要传输重写,但仍使用核心传输 | +| 14 | `contributeResolvedModelCompat` | 为位于另一种兼容传输之后的厂商模型贡献兼容标志 | 提供商能在代理传输上识别自己的模型,而不接管该提供商 | +| 15 | `capabilities` | 共享核心逻辑使用的提供商自有转录/工具元数据 | 提供商需要转录/提供商族特性 | +| 16 | `normalizeToolSchemas` | 在嵌入式运行器看到工具 schema 前对其规范化 | 提供商需要传输族 schema 清理 | +| 17 | `inspectToolSchemas` | 在规范化后暴露提供商自有的 schema 诊断 | 提供商希望发出关键字警告,而不让核心学习提供商特定规则 | +| 18 | `resolveReasoningOutputMode` | 选择原生与带标签的推理输出契约 | 提供商需要带标签的推理/最终输出,而不是原生字段 | +| 19 | `prepareExtraParams` | 在通用流选项包装器前规范化请求参数 | 提供商需要默认请求参数或按提供商清理参数 | +| 20 | `createStreamFn` | 用自定义传输完全替换正常流路径 | 提供商需要自定义线协议,而不只是包装器 | +| 21 | `wrapStreamFn` | 应用通用包装器后的流包装器 | 提供商需要请求 header/body/模型兼容包装器,而不需要自定义传输 | +| 22 | `resolveTransportTurnState` | 附加原生的逐轮传输 header 或元数据 | 提供商希望通用传输发送提供商原生的轮次身份 | +| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket header 或会话冷却策略 | 提供商希望通用 WS 传输调整会话 header 或兜底策略 | | 24 | `formatApiKey` | 认证配置文件格式化器:已存储配置文件会变成运行时 `apiKey` 字符串 | 提供商存储额外认证元数据,并需要自定义运行时令牌形态 | -| 25 | `refreshOAuth` | 针对自定义刷新端点或刷新失败策略的 OAuth 刷新覆盖 | 提供商不适配共享的 `pi-ai` 刷新器 | -| 26 | `buildAuthDoctorHint` | OAuth 刷新失败时附加的修复提示 | 提供商需要在刷新失败后提供由提供商负责的认证修复指导 | +| 25 | `refreshOAuth` | 用于自定义刷新端点或刷新失败策略的 OAuth 刷新覆盖 | 提供商不适配共享的 `pi-ai` 刷新器 | +| 26 | `buildAuthDoctorHint` | OAuth 刷新失败时追加的修复提示 | 提供商在刷新失败后需要提供商自有的认证修复指引 | | 27 | `matchesContextOverflowError` | 提供商自有的上下文窗口溢出匹配器 | 提供商存在通用启发式会漏掉的原始溢出错误 | -| 28 | `classifyFailoverReason` | 提供商自有的故障转移原因分类 | 提供商可以将原始 API/传输错误映射为限流/过载等 | -| 29 | `isCacheTtlEligible` | 代理/回传提供商的提示缓存策略 | 提供商需要代理特定的缓存 TTL 门控 | -| 30 | `buildMissingAuthMessage` | 替换通用的缺失认证恢复消息 | 提供商需要提供商特定的缺失认证恢复提示 | -| 31 | `suppressBuiltInModel` | 已弃用。运行时钩子不再被调用;请使用清单 `modelCatalog.suppressions` | 用于隐藏过期上游行的历史钩子;将新的抑制数据保留在插件清单中 | +| 28 | `classifyFailoverReason` | 提供商自有的故障转移原因分类 | 提供商可以将原始 API/传输错误映射为限速/过载等 | +| 29 | `isCacheTtlEligible` | 代理/回程提供商的提示缓存策略 | 提供商需要特定于代理的缓存 TTL 门控 | +| 30 | `buildMissingAuthMessage` | 替换通用的缺失认证恢复消息 | 提供商需要特定于提供商的缺失认证恢复提示 | +| 31 | `suppressBuiltInModel` | 已弃用。运行时钩子不再被调用;请使用 manifest `modelCatalog.suppressions` | 用于隐藏过期上游行的历史钩子;新的抑制数据应保留在插件 manifest 中 | | 32 | `augmentModelCatalog` | 在设备发现后追加的合成/最终目录行 | 提供商需要在 `models list` 和选择器中提供合成的前向兼容行 | -| 33 | `resolveThinkingProfile` | 模型特定的 `/think` 级别集合、显示标签和默认值 | 提供商为所选模型暴露自定义思考档位或二元标签 | -| 34 | `isBinaryThinking` | 开/关推理切换兼容性钩子 | 提供商只暴露二元思考开/关 | -| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容性钩子 | 提供商只想在模型子集上启用 `xhigh` | -| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 级别兼容性钩子 | 提供商拥有某个模型系列的默认 `/think` 策略 | -| 37 | `isModernModelRef` | 用于实时 profile 过滤器和冒烟选择的现代模型匹配器 | 提供商负责实时/冒烟首选模型匹配 | -| 38 | `prepareRuntimeAuth` | 在推理前,将配置的凭据交换为实际的运行时令牌/密钥 | 提供商需要令牌交换或短期请求凭据 | -| 39 | `resolveUsageAuth` | 为 `/usage` 和相关 Status 界面解析用量/计费凭据 | 提供商需要自定义用量/配额令牌解析,或不同的用量凭据 | -| 40 | `fetchUsageSnapshot` | 在认证解析完成后,获取并规范化提供商特定的用量/配额快照 | 提供商需要提供商特定的用量端点或载荷解析器 | +| 33 | `resolveThinkingProfile` | 特定模型的 `/think` 等级集、显示标签和默认值 | 提供商为选定模型暴露自定义 thinking 阶梯或二元标签 | +| 34 | `isBinaryThinking` | 开/关推理切换兼容钩子 | 提供商只暴露二元 thinking 开/关 | +| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容钩子 | 提供商只希望部分模型支持 `xhigh` | +| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 等级兼容钩子 | 提供商拥有某个模型族的默认 `/think` 策略 | +| 37 | `isModernModelRef` | 用于实时配置文件筛选器和冒烟测试选择的现代模型匹配器 | 由提供商负责实时/冒烟测试首选模型匹配 | +| 38 | `prepareRuntimeAuth` | 在推理前,将已配置凭证交换为实际运行时令牌/密钥 | 提供商需要令牌交换或短期请求凭证 | +| 39 | `resolveUsageAuth` | 为 `/usage` 和相关 Status 表面解析使用量/计费凭证 | 提供商需要自定义使用量/配额令牌解析,或不同的使用量凭证 | +| 40 | `fetchUsageSnapshot` | 在凭证解析完成后,获取并规范化特定于提供商的使用量/配额快照 | 提供商需要特定于提供商的使用量端点或载荷解析器 | | 41 | `createEmbeddingProvider` | 为记忆/搜索构建由提供商负责的嵌入适配器 | 记忆嵌入行为归属提供商插件 | -| 42 | `buildReplayPolicy` | 返回用于控制该提供商转录处理的重放策略 | 提供商需要自定义转录策略(例如,剥离思考块) | -| 43 | `sanitizeReplayHistory` | 在通用转录清理后重写重放历史 | 提供商需要超出共享压缩辅助函数范围的提供商特定重放重写 | -| 44 | `validateReplayTurns` | 在嵌入式运行器之前进行最终重放回合验证或重塑 | 提供商传输协议在通用清理后需要更严格的回合验证 | +| 42 | `buildReplayPolicy` | 返回控制提供商转录处理的重放策略 | 提供商需要自定义转录策略(例如,移除思考块) | +| 43 | `sanitizeReplayHistory` | 在通用转录清理后重写重放历史 | 提供商需要超出共享压缩辅助函数的特定于提供商的重放重写 | +| 44 | `validateReplayTurns` | 在嵌入式运行器之前进行最终重放轮次验证或重塑 | 提供商传输协议需要在通用净化后进行更严格的轮次验证 | | 45 | `onModelSelected` | 运行由提供商负责的选择后副作用 | 当模型变为活动状态时,提供商需要遥测或由提供商负责的状态 | -`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配的提供商插件,然后继续落到其他具备钩子能力的提供商插件,直到某个插件实际更改了模型 ID 或传输/配置。这样可以让别名/兼容性提供商垫片继续工作,而不要求调用方知道哪个内置插件拥有这次重写。如果没有提供商钩子重写受支持的 Google 系列配置项,内置的 Google 配置规范化器仍会应用该兼容性清理。 +`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配的提供商插件,然后继续遍历其他支持钩子的提供商插件,直到某个插件实际改写了模型 ID 或传输/配置。这样可以保持别名/兼容提供商 shim 正常工作,而不要求调用方知道哪个内置插件负责改写。如果没有提供商钩子改写受支持的 Google 系列配置项,内置的 Google 配置规范化器仍会应用该兼容性清理。 -如果提供商需要完全自定义的线协议或自定义请求执行器,那属于另一类插件。这些钩子用于仍然运行在 OpenClaw 常规推理循环上的提供商行为。 +如果提供商需要完全自定义的线协议或自定义请求执行器,那属于另一类扩展。这些钩子用于仍运行在 OpenClaw 常规推理循环上的提供商行为。 ### 提供商示例 @@ -285,29 +277,39 @@ api.registerProvider({ ### 内置示例 -内置提供商插件会组合上面的钩子,以适配每个厂商的目录、认证、思考、重放和用量需求。权威的钩子集合与每个插件一起位于 `extensions/` 下;本页展示的是形态,而不是镜像完整列表。 +内置提供商插件会组合上面的钩子,以适配每个供应商的目录、认证、思考、回放和用量需求。权威的钩子集合随每个插件位于 `extensions/` 下;本页展示的是这些形态,而不是镜像完整列表。 - - OpenRouter、Kilocode、Z.AI、xAI 注册 `catalog` 加上 `resolveDynamicModel` / `prepareDynamicModel`,这样它们可以在 OpenClaw 的静态目录之前暴露上游模型 ID。 + + OpenRouter、Kilocode、Z.AI、xAI 注册 `catalog` 以及 + `resolveDynamicModel` / `prepareDynamicModel`,这样它们就能在 OpenClaw 的静态目录之前呈现上游模型 ID。 - - GitHub Copilot、Gemini CLI、ChatGPT Codex、MiniMax、Xiaomi、z.ai 将 `prepareRuntimeAuth` 或 `formatApiKey` 与 `resolveUsageAuth` + `fetchUsageSnapshot` 配对,用于拥有令牌交换和 `/usage` 集成。 + + GitHub Copilot、Gemini CLI、ChatGPT Codex、MiniMax、Xiaomi、z.ai 将 + `prepareRuntimeAuth` 或 `formatApiKey` 与 `resolveUsageAuth` + + `fetchUsageSnapshot` 配对,以拥有令牌交换和 `/usage` 集成。 - - 共享的具名系列(`google-gemini`、`passthrough-gemini`、`anthropic-by-model`、`hybrid-anthropic-openai`)让提供商可以通过 `buildReplayPolicy` 选择加入转录策略,而不必让每个插件重新实现清理逻辑。 + + 共享的命名族(`google-gemini`、`passthrough-gemini`、 + `anthropic-by-model`、`hybrid-anthropic-openai`)让提供商可以通过 + `buildReplayPolicy` 选择加入对话记录策略,而无需每个插件重新实现清理逻辑。 - - `byteplus`、`cloudflare-ai-gateway`、`huggingface`、`kimi-coding`、`nvidia`、`qianfan`、`synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine` 只注册 `catalog`,并使用共享推理循环。 + + `byteplus`、`cloudflare-ai-gateway`、`huggingface`、`kimi-coding`、`nvidia`、 + `qianfan`、`synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 + `volcengine` 只注册 `catalog`,并使用共享推理循环。 - - Beta 标头、`/fast` / `serviceTier` 和 `context1m` 位于 Anthropic 插件的公开 `api.ts` / `contract-api.ts` 接缝(`wrapAnthropicProviderStream`、`resolveAnthropicBetas`、`resolveAnthropicFastMode`、`resolveAnthropicServiceTier`)中,而不是位于通用 SDK 中。 + + Beta 头、`/fast` / `serviceTier` 和 `context1m` 位于 + Anthropic 插件的公共 `api.ts` / `contract-api.ts` 接缝内 + (`wrapAnthropicProviderStream`、`resolveAnthropicBetas`、 + `resolveAnthropicFastMode`、`resolveAnthropicServiceTier`),而不是通用 SDK 中。 -## 运行时辅助函数 +## 运行时辅助工具 -插件可以通过 `api.runtime` 访问选定的核心辅助函数。对于 TTS: +插件可以通过 `api.runtime` 访问选定的核心辅助工具。对于 TTS: ```ts const clip = await api.runtime.tts.textToSpeech({ @@ -328,14 +330,14 @@ const voices = await api.runtime.tts.listVoices({ 说明: -- `textToSpeech` 为文件/语音备注表面返回常规核心 TTS 输出载荷。 +- `textToSpeech` 返回用于文件/语音便笺表面的常规核心 TTS 输出载荷。 - 使用核心 `messages.tts` 配置和提供商选择。 - 返回 PCM 音频缓冲区 + 采样率。插件必须为提供商重新采样/编码。 -- `listVoices` 对每个提供商都是可选的。将它用于厂商拥有的语音选择器或设置流程。 -- 语音列表可以包含更丰富的元数据,例如区域设置、性别和个性标签,用于感知提供商的选择器。 -- OpenAI 和 ElevenLabs 目前支持电话语音。Microsoft 不支持。 +- `listVoices` 对每个提供商都是可选的。将它用于供应商拥有的语音选择器或设置流程。 +- 语音列表可以包含更丰富的元数据,例如区域设置、性别和人格标签,用于感知提供商的选择器。 +- OpenAI 和 ElevenLabs 目前支持电话音频。Microsoft 不支持。 -插件也可以通过 `api.registerSpeechProvider(...)` 注册语音提供商。 +插件还可以通过 `api.registerSpeechProvider(...)` 注册语音提供商。 ```ts api.registerSpeechProvider({ @@ -355,12 +357,12 @@ api.registerSpeechProvider({ 说明: -- 将 TTS 策略、回退和回复递送保留在核心中。 -- 使用语音提供商处理厂商拥有的合成行为。 +- 将 TTS 策略、回退和回复交付保留在核心中。 +- 将语音提供商用于供应商拥有的合成行为。 - 旧版 Microsoft `edge` 输入会规范化为 `microsoft` 提供商 ID。 -- 首选的所有权模型面向公司:随着 OpenClaw 添加这些能力契约,一个厂商插件可以拥有文本、语音、图像以及未来的媒体提供商。 +- 首选的所有权模型以公司为导向:随着 OpenClaw 添加这些能力合约,一个供应商插件可以拥有文本、语音、图像和未来媒体提供商。 -对于图像/音频/视频理解,插件会注册一个带类型的媒体理解提供商,而不是泛型键/值包: +对于图像/音频/视频理解,插件注册一个类型化的媒体理解提供商,而不是通用键/值包: ```ts api.registerMediaUnderstandingProvider({ @@ -375,14 +377,14 @@ api.registerMediaUnderstandingProvider({ 说明: - 将编排、回退、配置和渠道接线保留在核心中。 -- 将厂商行为保留在提供商插件中。 +- 将供应商行为保留在提供商插件中。 - 增量扩展应保持类型化:新的可选方法、新的可选结果字段、新的可选能力。 - 视频生成已经遵循相同模式: - - 核心拥有能力契约和运行时辅助函数 - - 厂商插件注册 `api.registerVideoGenerationProvider(...)` + - 核心拥有能力合约和运行时辅助工具 + - 供应商插件注册 `api.registerVideoGenerationProvider(...)` - 功能/渠道插件使用 `api.runtime.videoGeneration.*` -对于媒体理解运行时辅助函数,插件可以调用: +对于媒体理解运行时辅助工具,插件可以调用: ```ts const image = await api.runtime.mediaUnderstanding.describeImageFile({ @@ -412,10 +414,10 @@ const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ - `api.runtime.mediaUnderstanding.*` 是图像/音频/视频理解的首选共享表面。 - 使用核心媒体理解音频配置(`tools.media.audio`)和提供商回退顺序。 -- 当没有生成转录输出时(例如跳过/不受支持的输入),返回 `{ text: undefined }`。 +- 当没有生成转录输出时返回 `{ text: undefined }`(例如跳过/不支持的输入)。 - `api.runtime.stt.transcribeAudioFile(...)` 仍作为兼容性别名保留。 -插件也可以通过 `api.runtime.subagent` 启动后台子智能体运行: +插件还可以通过 `api.runtime.subagent` 启动后台子智能体运行: ```ts const result = await api.runtime.subagent.run({ @@ -429,14 +431,14 @@ const result = await api.runtime.subagent.run({ 说明: -- `provider` 和 `model` 是每次运行的可选覆盖项,而不是持久会话更改。 -- OpenClaw 只会为受信任调用方遵守这些覆盖字段。 +- `provider` 和 `model` 是每次运行的可选覆盖项,不是持久会话变更。 +- OpenClaw 仅为受信任调用方采用这些覆盖字段。 - 对于插件拥有的回退运行,操作员必须通过 `plugins.entries..subagent.allowModelOverride: true` 选择加入。 -- 使用 `plugins.entries..subagent.allowedModels` 将受信任插件限制到特定的规范 `provider/model` 目标,或使用 `"*"` 明确允许任意目标。 -- 不受信任的插件子智能体运行仍可工作,但覆盖请求会被拒绝,而不是静默回退。 -- 插件创建的子智能体会话会用创建它的插件 ID 打标签。回退 `api.runtime.subagent.deleteSession(...)` 只能删除这些归属会话;任意会话删除仍需要管理员作用域的 Gateway 网关请求。 +- 使用 `plugins.entries..subagent.allowedModels` 将受信任插件限制到特定规范 `provider/model` 目标,或使用 `"*"` 明确允许任意目标。 +- 不受信任的插件子智能体运行仍会工作,但覆盖请求会被拒绝,而不是静默回退。 +- 插件创建的子智能体会话会带有创建插件 ID 标签。回退 `api.runtime.subagent.deleteSession(...)` 只能删除这些归属会话;任意会话删除仍需要管理员范围的 Gateway 网关请求。 -对于 Web 搜索,插件可以使用共享运行时辅助函数,而不是进入智能体工具接线: +对于 Web 搜索,插件可以使用共享运行时辅助工具,而不是伸入智能体工具接线: ```ts const providers = api.runtime.webSearch.listProviders({ @@ -452,13 +454,13 @@ const result = await api.runtime.webSearch.search({ }); ``` -插件也可以通过 `api.registerWebSearchProvider(...)` 注册 Web 搜索提供商。 +插件还可以通过 `api.registerWebSearchProvider(...)` 注册 Web 搜索提供商。 说明: - 将提供商选择、凭证解析和共享请求语义保留在核心中。 -- 使用 Web 搜索提供商处理厂商特定的搜索传输。 -- `api.runtime.webSearch.*` 是需要搜索行为但不依赖智能体工具包装器的功能/渠道插件的首选共享表面。 +- 将 Web 搜索提供商用于供应商特定的搜索传输。 +- `api.runtime.webSearch.*` 是需要搜索行为、但不依赖智能体工具包装器的功能/渠道插件的首选共享表面。 ### `api.runtime.imageGeneration` @@ -478,7 +480,7 @@ const providers = api.runtime.imageGeneration.listProviders({ ## Gateway 网关 HTTP 路由 -插件可以通过 `api.registerHttpRoute(...)` 暴露 HTTP 端点。 +插件可以使用 `api.registerHttpRoute(...)` 暴露 HTTP 端点。 ```ts api.registerHttpRoute({ @@ -496,149 +498,149 @@ api.registerHttpRoute({ 路由字段: - `path`:Gateway 网关 HTTP 服务器下的路由路径。 -- `auth`:必需。使用 `"gateway"` 要求常规 Gateway 网关认证,或使用 `"plugin"` 进行插件管理的认证/webhook 验证。 +- `auth`:必填。使用 `"gateway"` 要求常规 Gateway 网关认证,或使用 `"plugin"` 进行插件管理的认证/webhook 验证。 - `match`:可选。`"exact"`(默认)或 `"prefix"`。 -- `replaceExisting`:可选。允许同一个插件替换其已有的路由注册。 +- `replaceExisting`:可选。允许同一插件替换其自己的现有路由注册。 - `handler`:当路由已处理请求时返回 `true`。 说明: - `api.registerHttpHandler(...)` 已移除,并会导致插件加载错误。请改用 `api.registerHttpRoute(...)`。 - 插件路由必须显式声明 `auth`。 -- 除非设置 `replaceExisting: true`,否则会拒绝完全相同的 `path + match` 冲突,并且一个插件不能替换另一个插件的路由。 -- 会拒绝具有不同 `auth` 级别的重叠路由。只应在相同鉴权级别上保留 `exact`/`prefix` 回退链。 -- `auth: "plugin"` 路由**不会**自动获得 operator 运行时作用域。它们用于插件管理的 webhook/签名验证,而不是特权 Gateway 网关辅助调用。 -- `auth: "gateway"` 路由在 Gateway 网关请求运行时作用域内运行,但该作用域刻意保持保守: - - shared-secret bearer 鉴权(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes` - - 携带可信身份的 HTTP 模式(例如 `trusted-proxy`,或私有入口上的 `gateway.auth.mode = "none"`)仅在显式存在 `x-openclaw-scopes` 标头时才会遵循它 - - 如果这些携带身份的插件路由请求中缺少 `x-openclaw-scopes`,运行时作用域会回退到 `operator.write` -- 实用规则:不要假设 Gateway 网关鉴权的插件路由是隐式管理员入口。如果你的路由需要仅限管理员的行为,请要求携带身份的鉴权模式,并记录显式的 `x-openclaw-scopes` 标头契约。 +- 精确的 `path + match` 冲突会被拒绝,除非设置 `replaceExisting: true`,并且一个插件不能替换另一个插件的路由。 +- 不同 `auth` 级别的重叠路由会被拒绝。仅在相同身份验证级别上保留 `exact`/`prefix` 回退链。 +- `auth: "plugin"` 路由**不会**自动接收操作员运行时作用域。它们用于插件管理的 webhook/签名验证,而不是特权 Gateway 网关辅助调用。 +- `auth: "gateway"` 路由在 Gateway 网关请求运行时作用域内运行,但该作用域有意保持保守: + - 共享密钥 bearer 身份验证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes` + - 带可信身份的 HTTP 模式(例如私有入口上的 `trusted-proxy` 或 `gateway.auth.mode = "none"`)仅在显式提供 `x-openclaw-scopes` 标头时才会采用它 + - 如果这些带身份的插件路由请求中缺少 `x-openclaw-scopes`,运行时作用域会回退到 `operator.write` +- 实用规则:不要假设经过 Gateway 网关身份验证的插件路由就是隐式管理员接口。如果你的路由需要仅限管理员的行为,请要求使用带身份的身份验证模式,并记录显式 `x-openclaw-scopes` 标头契约。 ## 插件 SDK 导入路径 -编写新插件时,请使用较窄的 SDK 子路径,而不是单体的 `openclaw/plugin-sdk` 根汇总入口。核心子路径: +编写新插件时,使用较窄的 SDK 子路径,而不是单体式 `openclaw/plugin-sdk` 根 barrel。核心子路径: | 子路径 | 用途 | | ----------------------------------- | -------------------------------------------------- | | `openclaw/plugin-sdk/plugin-entry` | 插件注册原语 | | `openclaw/plugin-sdk/channel-core` | 渠道入口/构建辅助工具 | -| `openclaw/plugin-sdk/core` | 通用共享辅助工具和伞形契约 | -| `openclaw/plugin-sdk/config-schema` | 根 `openclaw.json` Zod 模式(`OpenClawSchema`) | +| `openclaw/plugin-sdk/core` | 通用共享辅助工具和总括契约 | +| `openclaw/plugin-sdk/config-schema` | 根 `openclaw.json` Zod schema(`OpenClawSchema`) | -渠道插件从一组较窄的衔接面中选择:`channel-setup`、`setup-runtime`、`setup-adapter-runtime`、`setup-tools`、`channel-pairing`、`channel-contract`、`channel-feedback`、`channel-inbound`、`channel-lifecycle`、`channel-reply-pipeline`、`command-auth`、`secret-input`、`webhook-ingress`、`channel-targets` 和 `channel-actions`。审批行为应统一到一个 `approvalCapability` 契约,而不是混用不相关的插件字段。参见[渠道插件](/zh-CN/plugins/sdk-channel-plugins)。 +渠道插件可从一组较窄的边界中选择:`channel-setup`、`setup-runtime`、`setup-adapter-runtime`、`setup-tools`、`channel-pairing`、`channel-contract`、`channel-feedback`、`channel-inbound`、`channel-lifecycle`、`channel-reply-pipeline`、`command-auth`、`secret-input`、`webhook-ingress`、`channel-targets` 和 `channel-actions`。审批行为应整合到一个 `approvalCapability` 契约上,而不是混用无关的插件字段。请参阅[渠道插件](/zh-CN/plugins/sdk-channel-plugins)。 -运行时和配置辅助工具位于对应的聚焦型 `*-runtime` 子路径下(`approval-runtime`、`agent-runtime`、`lazy-runtime`、`directory-runtime`、`text-runtime`、`runtime-store`、`system-event-runtime`、`heartbeat-runtime`、`channel-activity-runtime` 等)。请优先使用 `config-types`、`plugin-config-runtime`、`runtime-config-snapshot` 和 `config-mutation`,而不是宽泛的 `config-runtime` 兼容汇总入口。 +运行时和配置辅助工具位于匹配的聚焦 `*-runtime` 子路径下(`approval-runtime`、`agent-runtime`、`lazy-runtime`、`directory-runtime`、`text-runtime`、`runtime-store`、`system-event-runtime`、`heartbeat-runtime`、`channel-activity-runtime` 等)。优先使用 `config-types`、`plugin-config-runtime`、`runtime-config-snapshot` 和 `config-mutation`,而不是宽泛的 `config-runtime` 兼容 barrel。 -`openclaw/plugin-sdk/channel-runtime`、`openclaw/plugin-sdk/config-runtime` 和 `openclaw/plugin-sdk/infra-runtime` 是面向旧插件的已弃用兼容垫片。新代码应改为导入更窄的通用原语。 +`openclaw/plugin-sdk/channel-runtime`、`openclaw/plugin-sdk/config-runtime` 和 `openclaw/plugin-sdk/infra-runtime` 是面向旧插件的已弃用兼容 shim。新代码应改为导入更窄的通用原语。 仓库内部入口点(按每个内置插件包根目录): - `index.js` — 内置插件入口 -- `api.js` — 辅助工具/类型汇总入口 -- `runtime-api.js` — 仅运行时汇总入口 +- `api.js` — 辅助工具/类型 barrel +- `runtime-api.js` — 仅运行时 barrel - `setup-entry.js` — 设置插件入口 -外部插件只应导入 `openclaw/plugin-sdk/*` 子路径。切勿从核心或另一个插件导入另一个插件包的 `src/*`。通过外观加载的入口点会在存在活动运行时配置快照时优先使用它,然后回退到磁盘上解析出的配置文件。 +外部插件应仅导入 `openclaw/plugin-sdk/*` 子路径。绝不要从 core 或另一个插件导入另一个插件包的 `src/*`。由 facade 加载的入口点在存在活动运行时配置快照时优先使用该快照,然后回退到磁盘上的已解析配置文件。 -存在 `image-generation`、`media-understanding` 和 `speech` 等特定能力子路径,是因为内置插件目前会使用它们。它们不会自动成为长期冻结的外部契约;依赖它们时请检查相关 SDK 参考页面。 +`image-generation`、`media-understanding` 和 `speech` 等能力专用子路径存在,是因为内置插件目前使用它们。它们不会自动成为长期冻结的外部契约;依赖它们时请查看相关 SDK 参考页面。 -## 消息工具模式 +## 消息工具 schema -插件应拥有渠道特定的 `describeMessageTool(...)` 模式贡献,用于 reaction、已读和投票等非消息原语。共享发送呈现应使用通用 `MessagePresentation` 契约,而不是提供商原生的按钮、组件、区块或卡片字段。请参见[消息呈现](/zh-CN/plugins/message-presentation),了解契约、回退规则、提供商映射和插件作者检查清单。 +插件应拥有渠道特定的 `describeMessageTool(...)` schema 贡献,用于 reaction、read 和 poll 等非消息原语。共享发送呈现应使用通用 `MessagePresentation` 契约,而不是 provider 原生按钮、组件、块或卡片字段。请参阅 [Message Presentation](/zh-CN/plugins/message-presentation) 了解契约、回退规则、provider 映射和插件作者检查清单。 具备发送能力的插件通过消息能力声明它们可以渲染的内容: -- `presentation` 用于语义呈现区块(`text`、`context`、`divider`、`buttons`、`select`) +- `presentation` 用于语义呈现块(`text`、`context`、`divider`、`buttons`、`select`) - `delivery-pin` 用于固定投递请求 -核心决定是原生渲染该呈现,还是降级为文本。不要从通用消息工具暴露提供商原生 UI 逃生口。面向旧版原生模式的已弃用 SDK 辅助工具仍会为现有第三方插件导出,但新插件不应使用它们。 +Core 决定是原生渲染该呈现,还是将其降级为文本。不要从通用消息工具暴露 provider 原生 UI 逃生口。旧版原生 schema 的已弃用 SDK 辅助工具仍会为现有第三方插件导出,但新插件不应使用它们。 ## 渠道目标解析 -渠道插件应拥有渠道特定的目标语义。保持共享出站主机通用,并使用消息适配器表面来处理提供商规则: +渠道插件应拥有渠道特定的目标语义。保持共享出站主机的通用性,并使用消息适配器接口处理 provider 规则: -- `messaging.inferTargetChatType({ to })` 在目录查找之前,决定是否应将规范化目标视为 `direct`、`group` 或 `channel`。 -- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉核心输入是否应跳过目录搜索,直接进入类似 id 的解析。 -- `messaging.targetResolver.resolveTarget(...)` 是核心在规范化后或目录未命中后,需要最终由提供商拥有的解析时的插件回退。 -- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后,拥有提供商特定的会话路由构造。 +- `messaging.inferTargetChatType({ to })` 在目录查找之前,决定规范化目标应被视为 `direct`、`group` 还是 `channel`。 +- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉 core 某个输入是否应跳过目录搜索,直接进入类似 id 的解析。 +- `messaging.targetResolver.resolveTarget(...)` 是插件回退路径,用于 core 在规范化后或目录未命中后需要最终由 provider 拥有的解析。 +- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后,负责构造 provider 特定的会话路由。 -建议拆分: +推荐拆分: - 使用 `inferTargetChatType` 处理应在搜索 peer/group 之前发生的类别决策。 -- 使用 `looksLikeId` 检查“将此视为显式/原生目标 id”。 -- 使用 `resolveTarget` 作为提供商特定的规范化回退,而不是用于宽泛目录搜索。 -- 将 chat id、thread id、JID、handle 和 room id 等提供商原生 id 保留在 `target` 值或提供商特定参数中,而不是通用 SDK 字段中。 +- 使用 `looksLikeId` 进行“将此视为显式/原生目标 id”的检查。 +- 使用 `resolveTarget` 作为 provider 特定的规范化回退,而不是用于宽泛的目录搜索。 +- 将 chat id、thread id、JID、handle 和 room id 等 provider 原生 id 保留在 `target` 值或 provider 特定参数中,不要放入通用 SDK 字段。 -## 配置支持的目录 +## 配置支撑的目录 从配置派生目录条目的插件应将该逻辑保留在插件中,并复用 `openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。 -当渠道需要配置支持的 peer/group 时使用它,例如: +当渠道需要由配置支撑的 peer/group 时使用它,例如: -- 由 allowlist 驱动的私信 peer +- allowlist 驱动的私信 peer - 已配置的渠道/group 映射 - 账号作用域的静态目录回退 `directory-runtime` 中的共享辅助工具仅处理通用操作: - 查询过滤 -- 限制应用 +- limit 应用 - 去重/规范化辅助工具 - 构建 `ChannelDirectoryEntry[]` -渠道特定的账号检查和 id 规范化应保留在插件实现中。 +渠道特定的账号检查和 id 规范化应留在插件实现中。 -## 提供商目录 +## Provider 目录 -提供商插件可以通过 `registerProvider({ catalog: { run(...) { ... } } })` 为推理定义模型目录。 +Provider 插件可以通过 `registerProvider({ catalog: { run(...) { ... } } })` 为推理定义模型目录。 -`catalog.run(...)` 返回的形状与 OpenClaw 写入 `models.providers` 的形状相同: +`catalog.run(...)` 返回与 OpenClaw 写入 `models.providers` 相同的形状: -- `{ provider }` 表示一个提供商条目 -- `{ providers }` 表示多个提供商条目 +- `{ provider }` 表示一个 provider 条目 +- `{ providers }` 表示多个 provider 条目 -当插件拥有提供商特定的模型 id、base URL 默认值或受鉴权保护的模型元数据时,请使用 `catalog`。 +当插件拥有 provider 特定的模型 id、base URL 默认值或受身份验证保护的模型元数据时,请使用 `catalog`。 -`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式提供商的合并时机: +`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式 provider 的合并时机: -- `simple`:普通 API key 或环境变量驱动的提供商 -- `profile`:存在鉴权配置文件时出现的提供商 -- `paired`:合成多个相关提供商条目的提供商 -- `late`:最后一轮,在其他隐式提供商之后 +- `simple`:普通 API key 或环境驱动的 provider +- `profile`:当身份验证 profile 存在时出现的 provider +- `paired`:合成多个相关 provider 条目的 provider +- `late`:最后一轮,在其他隐式 provider 之后 -发生键冲突时,后出现的提供商胜出,因此插件可以有意用相同提供商 id 覆盖内置提供商条目。 +发生键冲突时,较晚的 provider 胜出,因此插件可以有意使用相同 provider id 覆盖内置 provider 条目。 兼容性: -- `discovery` 仍可作为旧版别名使用 +- `discovery` 仍作为旧版别名可用 - 如果同时注册了 `catalog` 和 `discovery`,OpenClaw 会使用 `catalog` ## 只读渠道检查 -如果你的插件注册了渠道,请优先在 `resolveAccount(...)` 旁实现 `plugin.config.inspectAccount(cfg, accountId)`。 +如果你的插件注册了渠道,优先在 `resolveAccount(...)` 旁实现 `plugin.config.inspectAccount(cfg, accountId)`。 原因: -- `resolveAccount(...)` 是运行时路径。它可以假设凭证已完全实体化,并在缺少所需 secret 时快速失败。 -- `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve` 等只读命令路径,以及 Doctor/配置修复流程,不应只是为了描述配置就需要实体化运行时凭证。 +- `resolveAccount(...)` 是运行时路径。它允许假设凭证已完全物化,并且可以在缺少必需 secret 时快速失败。 +- `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve` 以及 doctor/config 修复流程等只读命令路径,不应仅为了描述配置就需要物化运行时凭证。 -建议的 `inspectAccount(...)` 行为: +推荐的 `inspectAccount(...)` 行为: -- 只返回描述性的账号状态。 +- 仅返回描述性账号状态。 - 保留 `enabled` 和 `configured`。 -- 相关时包含凭证来源/状态字段,例如: +- 在相关时包含凭证来源/状态字段,例如: - `tokenSource`、`tokenStatus` - `botTokenSource`、`botTokenStatus` - `appTokenSource`、`appTokenStatus` - `signingSecretSource`、`signingSecretStatus` -- 你不需要为了报告只读可用性而返回原始 token 值。返回 `tokenStatus: "available"`(以及匹配的来源字段)就足够用于 Status 风格的命令。 +- 你无需为了报告只读可用性而返回原始 token 值。返回 `tokenStatus: "available"`(以及匹配的 source 字段)就足以满足 status 风格的命令。 - 当凭证通过 SecretRef 配置但在当前命令路径中不可用时,使用 `configured_unavailable`。 -这样,只读命令可以报告“已配置但在此命令路径中不可用”,而不是崩溃或错误报告账号未配置。 +这让只读命令可以报告“已配置,但在此命令路径中不可用”,而不是崩溃或误报账号未配置。 -## 包集合 +## 包组合 插件目录可以包含带有 `openclaw.extensions` 的 `package.json`: @@ -652,37 +654,37 @@ api.registerHttpRoute({ } ``` -每个条目都会成为一个插件。如果该集合列出多个扩展,插件 id 会变为 `name/`。 +每个条目都会成为一个插件。如果包列出了多个插件,插件 id 会变为 `name/`。 如果你的插件导入 npm 依赖,请在该目录中安装它们,以便 `node_modules` 可用(`npm install` / `pnpm install`)。 -安全护栏:每个 `openclaw.extensions` 条目在 symlink 解析后都必须留在插件目录内。逃逸出包目录的条目会被拒绝。 +安全护栏:每个 `openclaw.extensions` 条目在 symlink 解析后都必须留在插件目录内。逃出包目录的条目会被拒绝。 -安全说明:`openclaw plugins install` 使用项目本地的 `npm install --omit=dev --ignore-scripts` 安装插件依赖(没有生命周期脚本,运行时没有 dev 依赖),并忽略继承的全局 npm 安装设置。保持插件依赖树为“纯 JS/TS”,并避免需要 `postinstall` 构建的包。 +安全说明:`openclaw plugins install` 会使用项目本地的 `npm install --omit=dev --ignore-scripts` 安装插件依赖(没有生命周期脚本,运行时没有 dev 依赖),并忽略继承的全局 npm install 设置。保持插件依赖树为“纯 JS/TS”,并避免需要 `postinstall` 构建的包。 -可选:`openclaw.setupEntry` 可以指向轻量的仅设置模块。当 OpenClaw 需要为已禁用的渠道插件提供设置表面,或者当渠道插件已启用但仍未配置时,它会加载 `setupEntry`,而不是完整插件入口。当你的主插件入口还会连接工具、钩子或其他仅运行时代码时,这可以让启动和设置更轻量。 +可选:`openclaw.setupEntry` 可以指向一个轻量的仅设置模块。当 OpenClaw 需要为已禁用的渠道插件提供设置接口,或渠道插件已启用但仍未配置时,它会加载 `setupEntry`,而不是完整插件入口。当你的主插件入口还会连接工具、钩子或其他仅运行时代码时,这会让启动和设置更轻量。 -可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` 可以让渠道插件在 Gateway 网关的监听前启动阶段选择使用相同的 `setupEntry` 路径,即使该渠道已经配置完成。 +可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` 可以让渠道插件在 Gateway 网关预监听启动阶段选择使用相同的 `setupEntry` 路径,即使该渠道已经配置完成。 -仅当 `setupEntry` 完全覆盖 Gateway 网关开始监听前必须存在的启动表面时,才使用此选项。实际中,这意味着设置入口必须注册启动依赖的每个渠道拥有的能力,例如: +仅当 `setupEntry` 完全覆盖 Gateway 网关开始监听前必须存在的启动接口时,才使用此项。实践中,这意味着设置入口必须注册启动所依赖的每个渠道自有能力,例如: - 渠道注册本身 -- Gateway 网关开始监听前必须可用的任何 HTTP 路由 -- 在同一窗口期内必须存在的任何 Gateway 网关方法、工具或服务 +- 任何必须在 Gateway 网关开始监听前可用的 HTTP 路由 +- 任何必须在同一时间窗口中存在的 gateway 方法、工具或服务 -如果你的完整入口仍拥有任何必需的启动能力,请不要启用此标志。保留插件的默认行为,让 OpenClaw 在启动期间加载完整入口。 +如果你的完整入口仍拥有任何必需的启动能力,请不要启用此标志。保持插件使用默认行为,并让 OpenClaw 在启动期间加载完整入口。 -内置渠道也可以发布仅设置的契约表面辅助工具,供核心在完整渠道运行时加载前查询。当前设置提升表面为: +内置渠道还可以发布仅设置的契约接口辅助工具,供 core 在完整渠道运行时加载前查询。当前设置提升接口是: - `singleAccountKeysToMove` - `namedAccountPromotionKeys` - `resolveSingleAccountPromotionTarget(...)` -核心在需要将旧版单账号渠道配置提升为 `channels..accounts.*`,但不加载完整插件入口时,会使用该接口。Matrix 是当前的内置示例:当已存在命名账号时,它只会把 auth/bootstrap 键移动到一个命名的提升账号中,并且它可以保留已配置的非规范默认账号键,而不是总是创建 `accounts.default`。 +当 Core 需要在不加载完整插件入口的情况下,将旧版单账号渠道配置提升到 `channels..accounts.*` 时,会使用这个表面。Matrix 是当前的内置示例:当命名账号已经存在时,它只会把身份验证/引导键移动到一个命名的已提升账号中,并且可以保留已配置的非规范默认账号键,而不是总是创建 `accounts.default`。 -这些设置补丁适配器会让内置契约接口发现保持惰性。导入时间保持轻量;提升接口只会在首次使用时加载,而不是在模块导入时重新进入内置渠道启动流程。 +这些设置补丁适配器会让内置合同表面的发现保持惰性。导入时间保持轻量;提升表面只会在首次使用时加载,而不是在模块导入时重新进入内置渠道启动流程。 -当这些启动接口包含 Gateway 网关 RPC 方法时,请把它们放在插件专用前缀下。核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)保持保留,并且始终解析为 `operator.admin`,即使某个插件请求了更窄的作用域也是如此。 +当这些启动表面包含 Gateway 网关 RPC 方法时,请把它们放在插件专用前缀下。Core 管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留命名空间,并且始终解析为 `operator.admin`,即使某个插件请求了更窄的作用域。 示例: @@ -701,7 +703,7 @@ api.registerHttpRoute({ ### 渠道目录元数据 -渠道插件可以通过 `openclaw.channel` 公告设置/发现元数据,并通过 `openclaw.install` 公告安装提示。这样核心目录就不需要携带数据。 +渠道插件可以通过 `openclaw.channel` 声明设置/设备发现元数据,并通过 `openclaw.install` 声明安装提示。这可以让 Core 目录不包含数据。 示例: @@ -729,17 +731,17 @@ api.registerHttpRoute({ } ``` -除最小示例外,常用的 `openclaw.channel` 字段: +除了最小示例之外,常用的 `openclaw.channel` 字段: -- `detailLabel`:用于更丰富目录/Status 界面的次级标签 +- `detailLabel`:用于更丰富的目录/Status 表面的次级标签 - `docsLabel`:覆盖文档链接的链接文本 -- `preferOver`:此目录条目应排在其前面的低优先级插件/渠道 ID -- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择界面文案控制项 -- `markdownCapable`:将该渠道标记为支持 Markdown,用于出站格式决策 -- `exposure.configured`:设置为 `false` 时,在已配置渠道列表界面中隐藏该渠道 +- `preferOver`:此目录条目应优先于的低优先级插件/渠道 ID +- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择表面的文案控制 +- `markdownCapable`:将该渠道标记为支持 markdown,用于出站格式化决策 +- `exposure.configured`:设置为 `false` 时,在已配置渠道列表表面隐藏该渠道 - `exposure.setup`:设置为 `false` 时,在交互式设置/配置选择器中隐藏该渠道 -- `exposure.docs`:将该渠道标记为内部/私有,用于文档导航界面 -- `showConfigured` / `showInSetup`:为兼容性仍接受的旧版别名;优先使用 `exposure` +- `exposure.docs`:在文档导航表面将该渠道标记为内部/私有 +- `showConfigured` / `showInSetup`:为了兼容仍然接受的旧版别名;优先使用 `exposure` - `quickstartAllowFrom`:让该渠道加入标准快速开始 `allowFrom` 流程 - `forceAccountBinding`:即使只存在一个账号,也要求显式账号绑定 - `preferSessionLookupForAnnounceTarget`:解析公告目标时优先使用会话查找 @@ -750,17 +752,17 @@ OpenClaw 也可以合并**外部渠道目录**(例如 MPM 注册表导出) - `~/.openclaw/mpm/catalog.json` - `~/.openclaw/plugins/catalog.json` -或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(以逗号/分号/`PATH` 分隔)。每个文件应包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的旧版别名。 +或者让 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(以逗号/分号/`PATH` 分隔)。每个文件都应包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器还接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的旧版别名。 -生成的渠道目录条目和提供商安装目录条目会在原始 `openclaw.install` 块旁公开规范化的安装来源事实。规范化事实会标识 npm 规格是精确版本还是浮动选择器,是否存在预期完整性元数据,以及是否也有本地来源路径可用。当目录/包身份已知时,如果解析出的 npm 包名偏离该身份,规范化事实会发出警告。当 `defaultChoice` 无效或指向不可用来源,以及存在 npm 完整性元数据但没有有效 npm 来源时,它们也会发出警告。消费者应将 `installSource` 视为可选的增量字段,这样手写条目和目录垫片就不必合成它。这样,新手引导和诊断就能解释来源平面状态,而无需导入插件运行时。 +生成的渠道目录条目和提供商安装目录条目会在原始 `openclaw.install` 块旁边暴露规范化的安装源事实。规范化事实会标识 npm spec 是精确版本还是浮动选择器、是否存在预期完整性元数据,以及本地源路径是否也可用。当目录/包身份已知时,如果解析出的 npm 包名偏离该身份,规范化事实会发出警告。它们还会在 `defaultChoice` 无效或指向不可用源时发出警告,并在存在 npm 完整性元数据但没有有效 npm 源时发出警告。消费者应将 `installSource` 视为一个附加的可选字段,这样手写条目和目录垫片就不必合成它。这让新手引导和诊断可以解释源平面状态,而无需导入插件运行时。 -官方外部 npm 条目应优先使用精确的 `npmSpec` 加 `expectedIntegrity`。裸包名和 dist-tag 仍可用于兼容性,但它们会显示来源平面警告,使目录可以在不破坏现有插件的情况下向固定版本、完整性检查安装迁移。当新手引导从本地目录路径安装时,它会记录一个托管插件索引条目,其中包含 `source: "path"`,并在可能时包含工作区相对的 `sourcePath`。绝对操作加载路径仍保留在 `plugins.load.paths` 中;安装记录避免把本地工作站路径复制到长期配置中。这样,本地开发安装对来源平面诊断保持可见,同时不会增加第二个原始文件系统路径披露界面。持久化的 `plugins/installs.json` 插件索引是安装来源事实来源,并且可以在不加载插件运行时模块的情况下刷新。即使插件清单缺失或无效,它的 `installRecords` 映射也会持久保留;它的 `plugins` 数组是可重建的清单视图。 +官方外部 npm 条目应优先使用精确的 `npmSpec` 加 `expectedIntegrity`。裸包名和 dist-tag 仍可用于兼容,但它们会显示源平面警告,以便目录可以逐步转向固定版本、带完整性检查的安装,而不会破坏现有插件。当新手引导从本地目录路径安装时,它会记录一个托管插件的插件索引条目,其中包含 `source: "path"`,并在可能时包含工作区相对的 `sourcePath`。绝对运行加载路径仍保留在 `plugins.load.paths` 中;安装记录会避免把本地工作站路径重复写入长期配置。这让本地开发安装对源平面诊断可见,同时不增加第二个原始文件系统路径披露表面。持久化的 `plugins/installs.json` 插件索引是安装事实来源,并且可以在不加载插件运行时模块的情况下刷新。即使插件清单缺失或无效,它的 `installRecords` map 也会持久保留;它的 `plugins` 数组是可重建的清单视图。 ## 上下文引擎插件 -上下文引擎插件拥有会话上下文编排,用于摄取、组装和压缩。通过 `api.registerContextEngine(id, factory)` 从你的插件注册它们,然后使用 `plugins.slots.contextEngine` 选择活跃引擎。 +上下文引擎插件拥有用于摄取、组装和压缩的会话上下文编排。使用 `api.registerContextEngine(id, factory)` 从你的插件注册它们,然后用 `plugins.slots.contextEngine` 选择活动引擎。 -当你的插件需要替换或扩展默认上下文流水线,而不只是添加记忆搜索或钩子时,请使用这个能力。 +当你的插件需要替换或扩展默认上下文管线,而不只是添加记忆搜索或钩子时,请使用这个能力。 ```ts import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core"; @@ -788,9 +790,9 @@ export default function (api) { } ``` -工厂 `ctx` 会公开可选的 `config`、`agentDir` 和 `workspaceDir` 值,用于构造时初始化。 +工厂的 `ctx` 会暴露可选的 `config`、`agentDir` 和 `workspaceDir` 值,用于构造时初始化。 -如果你的引擎**不**拥有压缩算法,请保留 `compact()` 实现并显式委托: +如果你的引擎**不**拥有压缩算法,请保留 `compact()` 实现并显式委托它: ```ts import { @@ -827,37 +829,37 @@ export default function (api) { ## 添加新能力 -当插件需要的行为不适合当前 API 时,不要用私有伸入方式绕过插件系统。请添加缺失的能力。 +当插件需要的行为不适合当前 API 时,不要通过私有内部访问绕过插件系统。请添加缺失的能力。 推荐顺序: -1. 定义核心契约 - 决定核心应拥有哪些共享行为:策略、回退、配置合并、生命周期、面向渠道的语义,以及运行时辅助工具形态。 -2. 添加类型化插件注册/运行时接口 - 使用最小有用的类型化能力接口扩展 `OpenClawPluginApi` 和/或 `api.runtime`。 -3. 接入核心 + 渠道/功能消费者 - 渠道和功能插件应通过核心消费新能力,而不是直接导入供应商实现。 +1. 定义 Core 合同 + 决定 Core 应该拥有哪些共享行为:策略、回退、配置合并、生命周期、面向渠道的语义,以及运行时 helper 形状。 +2. 添加类型化插件注册/运行时表面 + 用最小可用的类型化能力表面扩展 `OpenClawPluginApi` 和/或 `api.runtime`。 +3. 连接 Core + 渠道/功能消费者 + 渠道和功能插件应通过 Core 消费新能力,而不是直接导入某个供应商实现。 4. 注册供应商实现 - 然后供应商插件将其后端注册到该能力。 -5. 添加契约覆盖 - 添加测试,使所有权和注册形态随时间保持明确。 + 然后供应商插件将它们的后端注册到该能力。 +5. 添加合同覆盖 + 添加测试,让所有权和注册形状随着时间保持显式。 -这就是 OpenClaw 保持有主见,同时又不硬编码到某个提供商世界观中的方式。有关具体文件检查清单和完整示例,请参阅[能力扩展手册](/zh-CN/plugins/architecture)。 +这就是 OpenClaw 保持有主张但又不硬编码到某一个提供商世界观的方式。请参阅[能力扩展手册](/zh-CN/plugins/architecture),了解具体文件清单和完整示例。 ### 能力检查清单 -添加新能力时,通常应一起触及这些界面: +添加新能力时,实现通常应同时触及这些表面: -- `src//types.ts` 中的核心契约类型 -- `src//runtime.ts` 中的核心运行器/运行时辅助工具 -- `src/plugins/types.ts` 中的插件 API 注册接口 -- `src/plugins/registry.ts` 中的插件注册表接线 +- `src//types.ts` 中的 Core 合同类型 +- `src//runtime.ts` 中的 Core runner/运行时 helper +- `src/plugins/types.ts` 中的插件 API 注册表面 +- `src/plugins/registry.ts` 中的插件注册表连接 - 当功能/渠道插件需要消费它时,`src/plugins/runtime/*` 中的插件运行时暴露 -- `src/test-utils/plugin-registration.ts` 中的捕获/测试辅助工具 -- `src/plugins/contracts/registry.ts` 中的所有权/契约断言 +- `src/test-utils/plugin-registration.ts` 中的捕获/测试 helper +- `src/plugins/contracts/registry.ts` 中的所有权/合同断言 - `docs/` 中的操作员/插件文档 -如果缺少其中某个界面,通常说明该能力尚未完全集成。 +如果缺少其中某个表面,通常说明该能力尚未完全集成。 ### 能力模板 @@ -887,22 +889,22 @@ const clip = await api.runtime.videoGeneration.generate({ }); ``` -契约测试模式: +合同测试模式: ```ts expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]); ``` -这会让规则保持简单: +这让规则保持简单: -- 核心拥有能力契约 + 编排 +- Core 拥有能力合同 + 编排 - 供应商插件拥有供应商实现 -- 功能/渠道插件消费运行时辅助工具 -- 契约测试让所有权保持明确 +- 功能/渠道插件消费运行时 helper +- 合同测试让所有权保持显式 ## 相关内容 -- [插件架构](/zh-CN/plugins/architecture) — 公共能力模型和形态 +- [插件架构](/zh-CN/plugins/architecture) — 公共能力模型和形状 - [插件 SDK 子路径](/zh-CN/plugins/sdk-subpaths) - [插件 SDK 设置](/zh-CN/plugins/sdk-setup) - [构建插件](/zh-CN/plugins/building-plugins)