From f8f2d1ab010505b920b363437b06aa41d76bcbcb Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Thu, 23 Apr 2026 07:46:10 +0000 Subject: [PATCH] chore(i18n): refresh zh-CN translations --- docs/zh-CN/help/testing.md | 1056 ++++++++++++++++--------------- docs/zh-CN/plugins/manifest.md | 299 ++++----- docs/zh-CN/plugins/sdk-setup.md | 306 +++++---- 3 files changed, 873 insertions(+), 788 deletions(-) diff --git a/docs/zh-CN/help/testing.md b/docs/zh-CN/help/testing.md index 0ae2f841a..edf78816b 100644 --- a/docs/zh-CN/help/testing.md +++ b/docs/zh-CN/help/testing.md @@ -1,118 +1,158 @@ --- read_when: - 在本地或 CI 中运行测试 - - 为模型/提供商缺陷添加回归测试 + - 为模型/提供商 bug 添加回归测试 - 调试 Gateway 网关 + 智能体行为 -summary: 测试工具包:单元 / e2e / 实时测试套件、Docker 运行器,以及各项测试的覆盖范围 +summary: 测试工具包:unit/e2e/live 测试套件、Docker 运行器,以及每类测试覆盖的内容 title: 测试 x-i18n: - generated_at: "2026-04-23T06:40:48Z" + generated_at: "2026-04-23T07:42:10Z" model: gpt-5.4 provider: openai - source_hash: 6cb3c7e0644b66e5ca8bce51ec52e874ac8c1dfe02193afa3b34d5e6b5e8a355 + source_hash: a92e9d1cd0ff64aabfbc28b42045aa6c63159375ff41695805488b40280e1b43 source_path: help/testing.md workflow: 15 --- # 测试 -OpenClaw 有三个 Vitest 测试套件(单元/集成、e2e、实时)以及一小组 Docker 运行器。 +OpenClaw 有三个 Vitest 测试套件(unit/integration、e2e、live)以及一小组 Docker 运行器。 本文档是一份“我们如何测试”的指南: -- 每个测试套件覆盖什么(以及它刻意 _不_ 覆盖什么) -- 常见工作流应运行哪些命令(本地、推送前、调试) -- 实时测试如何发现凭证并选择模型/提供商 +- 每个测试套件覆盖什么(以及它明确 _不_ 覆盖什么) +- 常见工作流(本地、推送前、调试)应运行哪些命令 +- live 测试如何发现凭证,以及如何选择模型/提供商 - 如何为真实世界中的模型/提供商问题添加回归测试 ## 快速开始 大多数时候: -- 完整门禁(预期在推送前运行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test` -- 在配置较宽裕的机器上更快地运行本地全套测试:`pnpm test:max` -- 直接使用 Vitest 监视循环:`pnpm test:watch` -- 直接按文件定位现在也会路由扩展/渠道路径:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` -- 当你正在迭代处理单个失败问题时,优先进行有针对性的运行。 -- Docker 支持的 QA 站点:`pnpm qa:lab:up` -- Linux VM 支持的 QA 通道:`pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` +- 完整门禁(预期在 push 前运行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test` +- 在配置较高的机器上更快地运行本地全套测试:`pnpm test:max` +- 直接进入 Vitest watch 循环:`pnpm test:watch` +- 直接按文件定位现在也会路由 extension/channel 路径:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` +- 当你正在迭代处理单个失败时,优先先跑有针对性的测试。 +- 基于 Docker 的 QA 站点:`pnpm qa:lab:up` +- 基于 Linux VM 的 QA 通道:`pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` -当你修改了测试或希望获得更多信心时: +当你修改了测试,或想获得额外信心时: - 覆盖率门禁:`pnpm test:coverage` -- E2E 套件:`pnpm test:e2e` +- E2E 测试套件:`pnpm test:e2e` 当你在调试真实提供商/模型时(需要真实凭证): -- 实时套件(模型 + Gateway 网关工具/图像探测):`pnpm test:live` -- 静默定位单个实时文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts` -- Moonshot/Kimi 成本冒烟测试:设置 `MOONSHOT_API_KEY` 后,运行 - `openclaw models list --provider moonshot --json`,然后针对 `moonshot/kimi-k2.6` 运行隔离的 - `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json` - 。验证 JSON 报告的是 Moonshot/K2.6,并且助手转录存储了规范化的 `usage.cost`。 +- live 测试套件(模型 + Gateway 网关工具/图像探测):`pnpm test:live` +- 安静地只跑一个 live 文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts` +- Docker live 模型扫描:`pnpm test:docker:live-models` + - CI 覆盖:每日的 `OpenClaw Scheduled Live And E2E Checks` 和手动触发的 + `OpenClaw Release Checks` 都会调用可复用的 live/E2E workflow,并设置 + `include_live_suites: true`,其中包含按提供商分片的独立 Docker live 模型 + matrix 作业。 + - 将新的高信号提供商 secrets 添加到 `scripts/ci-hydrate-live-auth.sh`, + 以及 `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 和其 + scheduled/release 调用方中。 +- Moonshot/Kimi 成本冒烟测试:在设置了 `MOONSHOT_API_KEY` 的情况下,运行 + `openclaw models list --provider moonshot --json`,然后针对 `moonshot/kimi-k2.6` + 运行隔离的 + `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json`。 + 验证 JSON 报告的是 Moonshot/K2.6,并且 assistant transcript 存储了标准化后的 + `usage.cost`。 -提示:当你只需要一个失败用例时,优先使用下文描述的允许列表环境变量来缩小实时测试范围。 +提示:当你只需要一个失败用例时,优先使用下面描述的 allowlist 环境变量来收窄 live 测试范围。 ## QA 专用运行器 -当你需要 QA-lab 级别的真实环境时,这些命令与主测试套件并列使用: +当你需要 QA-lab 级别的真实性时,这些命令与主测试套件配套使用: -CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,也可通过手动触发配合模拟提供商运行。`QA-Lab - All Lanes` 会在 `main` 上夜间运行,也可通过手动触发并行运行模拟 parity gate、实时 Matrix 通道以及由 Convex 管理的实时 Telegram 通道。`OpenClaw Release Checks` 会在发布批准前运行同样的通道。 +CI 会在专用 workflow 中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行, +也可通过手动分发使用 mock 提供商运行。`QA-Lab - All Lanes` 会在 `main` 上 +每晚运行,也可手动分发,包含 mock parity gate、live Matrix 通道,以及由 +Convex 管理的 live Telegram 通道,作为并行作业运行。`OpenClaw Release Checks` +会在发布审批前运行相同的通道。 - `pnpm openclaw qa suite` - 直接在主机上运行基于仓库的 QA 场景。 - - 默认并行运行多个选定场景,并使用隔离的 Gateway 网关工作进程。`qa-channel` 默认并发数为 4(受所选场景数量限制)。使用 `--concurrency ` 调整工作进程数量,或使用 `--concurrency 1` 运行较旧的串行通道。 - - 任何场景失败时以非零状态退出。若你希望生成工件但不以失败退出,可使用 `--allow-failures`。 + - 默认会并行运行多个选定场景,并使用隔离的 Gateway 网关 worker。 + `qa-channel` 默认并发数为 4(受所选场景数量限制)。使用 `--concurrency ` + 调整 worker 数量,或使用 `--concurrency 1` 切换为旧的串行通道。 + - 当任一场景失败时,以非零状态退出。若你想保留产物而不让退出码失败,可使用 + `--allow-failures`。 - 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。 - `aimock` 会启动一个基于本地 AIMock 的提供商服务器,用于实验性的夹具和协议模拟覆盖,但不会替代场景感知的 `mock-openai` 通道。 + `aimock` 会启动一个基于本地 AIMock 的提供商服务器,用于实验性的 fixture + 和协议 mock 覆盖,而不是替代具备场景感知能力的 `mock-openai` 通道。 - `pnpm openclaw qa suite --runner multipass` - - 在一次性 Multipass Linux VM 中运行同样的 QA 套件。 - - 保持与主机上 `qa suite` 相同的场景选择行为。 + - 在一次性 Multipass Linux VM 内运行同一套 QA 测试。 + - 与主机上的 `qa suite` 保持相同的场景选择行为。 - 复用与 `qa suite` 相同的提供商/模型选择标志。 - - 实时运行会转发对来宾实用的受支持 QA 身份验证输入: - 基于环境变量的提供商密钥、QA 实时提供商配置路径,以及存在时的 `CODEX_HOME`。 - - 输出目录必须保持在仓库根目录下,以便来宾可以通过挂载的工作区回写。 - - 在 `.artifacts/qa-e2e/...` 下写入常规 QA 报告 + 摘要以及 Multipass 日志。 + - live 运行会转发来宾环境中可行的受支持 QA 认证输入: + 基于环境变量的提供商 keys、QA live 提供商配置路径,以及存在时的 `CODEX_HOME`。 + - 输出目录必须保持在仓库根目录下,这样来宾才能通过挂载的工作区回写内容。 + - 将常规 QA 报告 + 摘要以及 Multipass 日志写入 + `.artifacts/qa-e2e/...`。 - `pnpm qa:lab:up` - - 启动 Docker 支持的 QA 站点,用于运维风格的 QA 工作。 + - 启动基于 Docker 的 QA 站点,用于偏运维风格的 QA 工作。 - `pnpm test:docker:npm-onboard-channel-agent` - - 从当前检出构建一个 npm tarball,在 Docker 中全局安装,运行非交互式 OpenAI API 密钥新手引导,默认配置 Telegram,验证启用插件会按需安装运行时依赖,运行 doctor,并针对模拟的 OpenAI 端点运行一次本地智能体回合。 - - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可用 Discord 运行同样的打包安装通道。 + - 从当前 checkout 构建 npm tarball,在 Docker 中全局安装,运行非交互式 + OpenAI API-key 新手引导,默认配置 Telegram,验证启用插件时会按需安装运行时依赖, + 运行 doctor,并针对一个 mocked OpenAI endpoint 运行一次本地智能体轮次。 + - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可用 Discord 运行相同的 + 打包安装通道。 - `pnpm test:docker:bundled-channel-deps` - - 在 Docker 中打包并安装当前 OpenClaw 构建,在已配置 OpenAI 的情况下启动 Gateway 网关,然后通过编辑配置启用内置渠道/插件。 - - 验证设置发现过程会使未配置的插件运行时依赖保持缺失状态,首次配置后的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖,而第二次重启不会重新安装已经激活的依赖。 - - 还会安装一个已知的较旧 npm 基线,在运行 `openclaw update --tag ` 之前启用 Telegram,并验证候选版本的更新后 doctor 会修复内置渠道运行时依赖,而无需由测试框架侧执行 postinstall 修复。 + - 在 Docker 中打包并安装当前 OpenClaw 构建产物,使用已配置的 OpenAI 启动 + Gateway 网关,然后通过配置编辑启用内置 channel/plugin。 + - 验证设置发现阶段会让未配置插件的运行时依赖保持缺失状态,首次配置好的 + Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖, + 而第二次重启不会重新安装已激活的依赖。 + - 还会安装一个已知的旧 npm 基线,在运行 `openclaw update --tag ` + 前启用 Telegram,并验证候选版本的更新后 doctor 会修复内置 channel + 运行时依赖,而不依赖测试框架侧的 postinstall 修复。 - `pnpm openclaw qa aimock` - 仅启动本地 AIMock 提供商服务器,用于直接协议冒烟测试。 - `pnpm openclaw qa matrix` - - 针对一次性的 Docker 支持 Tuwunel homeserver 运行 Matrix 实时 QA 通道。 - - 该 QA 主机目前仅供仓库/开发使用。打包后的 OpenClaw 安装不包含 `qa-lab`,因此不会暴露 `openclaw qa`。 - - 仓库检出会直接加载内置运行器;不需要单独的插件安装步骤。 - - 预配三个临时 Matrix 用户(`driver`、`sut`、`observer`)以及一个私有房间,然后以真实 Matrix 插件作为 SUT 传输启动一个 QA Gateway 网关子进程。 - - 默认使用固定稳定版 Tuwunel 镜像 `ghcr.io/matrix-construct/tuwunel:v1.5.1`。如需测试其他镜像,可使用 `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` 覆盖。 - - Matrix 不暴露共享凭证源标志,因为该通道会在本地预配一次性用户。 - - 在 `.artifacts/qa-e2e/...` 下写入 Matrix QA 报告、摘要、观察到的事件工件,以及合并的 stdout/stderr 输出日志。 + - 针对一次性的基于 Docker 的 Tuwunel homeserver 运行 Matrix live QA 通道。 + - 这个 QA 主机目前仅用于 repo/dev。打包后的 OpenClaw 安装包不包含 + `qa-lab`,因此也不会暴露 `openclaw qa`。 + - 仓库 checkout 会直接加载内置运行器;无需单独安装插件步骤。 + - 配置三个临时 Matrix 用户(`driver`、`sut`、`observer`)以及一个私有房间, + 然后启动一个 QA gateway 子进程,并将真实 Matrix 插件作为 SUT 传输层。 + - 默认使用固定稳定版 Tuwunel 镜像 `ghcr.io/matrix-construct/tuwunel:v1.5.1`。 + 当你需要测试不同镜像时,可通过 `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` 覆盖。 + - Matrix 不暴露共享凭证源标志,因为该通道会在本地配置一次性用户。 + - 将 Matrix QA 报告、摘要、observed-events 产物,以及合并后的 stdout/stderr + 输出日志写入 `.artifacts/qa-e2e/...`。 - `pnpm openclaw qa telegram` - - 使用环境变量中的 driver 和 SUT 机器人令牌,针对真实私有群组运行 Telegram 实时 QA 通道。 - - 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。group id 必须是 Telegram 数字 chat id。 - - 支持 `--credential-source convex` 用于共享池化凭证。默认使用 env 模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以启用池化租约。 - - 任一场景失败时以非零状态退出。若你希望生成工件但不以失败退出,可使用 `--allow-failures`。 - - 需要两个不同的机器人位于同一个私有群组中,并且 SUT 机器人需要公开 Telegram 用户名。 - - 为了实现稳定的机器人到机器人观测,请在 `@BotFather` 中为两个机器人启用 Bot-to-Bot Communication Mode,并确保 driver 机器人可以观察群组中的机器人流量。 - - 在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和已观察消息工件。 + - 使用来自环境变量的 driver 和 SUT bot token,针对真实私有群组运行 + Telegram live QA 通道。 + - 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` + 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。group id 必须是数字格式的 Telegram chat id。 + - 支持 `--credential-source convex` 以使用共享池化凭证。默认使用 env 模式, + 或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以启用池化租约。 + - 当任一场景失败时,以非零状态退出。若你想保留产物而不让退出码失败,可使用 + `--allow-failures`。 + - 需要两个不同的 bot 位于同一个私有群组中,并且 SUT bot 需要暴露 Telegram 用户名。 + - 为了稳定地观察 bot 到 bot 通信,请在 `@BotFather` 中为两个 bot 都启用 + Bot-to-Bot Communication Mode,并确保 driver bot 能观察到群组中的 bot 流量。 + - 将 Telegram QA 报告、摘要和 observed-messages 产物写入 + `.artifacts/qa-e2e/...`。 -实时传输通道共享一个标准契约,以避免新传输发生漂移: +live 传输通道共享一份标准契约,以避免新增传输方式时发生漂移: -`qa-channel` 仍然是范围广泛的合成 QA 套件,不属于实时传输覆盖矩阵的一部分。 +`qa-channel` 仍然是广义的合成 QA 测试套件,不属于 live +传输覆盖 matrix 的一部分。 -| Lane | Canary | Mention gating | Allowlist block | Top-level reply | Restart resume | Thread follow-up | Thread isolation | Reaction observation | Help command | -| -------- | ------ | -------------- | --------------- | --------------- | -------------- | ---------------- | ---------------- | -------------------- | ------------ | -| Matrix | x | x | x | x | x | x | x | x | | -| Telegram | x | | | | | | | | x | +| 通道 | Canary | 提及门控 | Allowlist block | 顶层回复 | 重启恢复 | 线程后续跟进 | 线程隔离 | Reaction 观察 | 帮助命令 | +| -------- | ------ | -------- | --------------- | -------- | -------- | ------------ | -------- | ------------- | -------- | +| Matrix | x | x | x | x | x | x | x | x | | +| Telegram | x | | | | | | | | x | ### 通过 Convex 共享 Telegram 凭证(v1) -当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从一个基于 Convex 的凭证池中获取独占租约,在通道运行期间为该租约发送心跳,并在关闭时释放该租约。 +当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时, +QA lab 会从基于 Convex 的池中获取独占租约,在该通道运行期间对租约进行 heartbeat, +并在关闭时释放租约。 参考 Convex 项目脚手架: @@ -121,12 +161,12 @@ CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上 必需的环境变量: - `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`) -- 为所选角色提供一个密钥: - - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` 用于 `maintainer` - - `OPENCLAW_QA_CONVEX_SECRET_CI` 用于 `ci` +- 所选角色对应的一个 secret: + - `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`) 可选环境变量: @@ -135,14 +175,15 @@ CI 会在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上 - `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS`(默认 `90000`) - `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS`(默认 `15000`) - `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX`(默认 `/qa-credentials/v1`) -- `OPENCLAW_QA_CREDENTIAL_OWNER_ID`(可选跟踪 id) -- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许仅用于本地开发的 loopback `http://` Convex URL。 +- `OPENCLAW_QA_CREDENTIAL_OWNER_ID`(可选 trace id) +- `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 add --kind telegram --payload-file qa/telegram-credential.json @@ -150,87 +191,87 @@ pnpm openclaw qa credentials list --kind telegram pnpm openclaw qa credentials remove --credential-id ``` -在脚本和 CI 工具中使用 `--json` 可获得机器可读输出。 +在脚本和 CI 工具中,如需机器可读输出,请使用 `--json`。 默认端点契约(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): - `POST /acquire` - 请求:`{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }` - 成功:`{ status: "ok", credentialId, leaseToken, payload, leaseTtlMs?, heartbeatIntervalMs? }` - - 资源耗尽/可重试:`{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }` + - 耗尽/可重试:`{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }` - `POST /heartbeat` - 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs }` - - 成功:`{ status: "ok" }`(或空的 `2xx`) + - 成功:`{ status: "ok" }`(或空 `2xx`) - `POST /release` - 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken }` - - 成功:`{ status: "ok" }`(或空的 `2xx`) -- `POST /admin/add`(仅限 maintainer 密钥) + - 成功:`{ status: "ok" }`(或空 `2xx`) +- `POST /admin/add`(仅限 maintainer secret) - 请求:`{ kind, actorId, payload, note?, status? }` - 成功:`{ status: "ok", credential }` -- `POST /admin/remove`(仅限 maintainer 密钥) +- `POST /admin/remove`(仅限 maintainer secret) - 请求:`{ credentialId, actorId }` - 成功:`{ status: "ok", changed, credential }` - 活跃租约保护:`{ status: "error", code: "LEASE_ACTIVE", ... }` -- `POST /admin/list`(仅限 maintainer 密钥) +- `POST /admin/list`(仅限 maintainer secret) - 请求:`{ kind?, status?, includePayload?, limit? }` - 成功:`{ status: "ok", credentials, count }` -Telegram 类型的负载结构: +Telegram 类型的 payload 结构: - `{ groupId: string, driverToken: string, sutToken: string }` -- `groupId` 必须是数字形式的 Telegram chat id 字符串。 -- `admin/add` 会针对 `kind: "telegram"` 验证此结构,并拒绝格式错误的负载。 +- `groupId` 必须是数字格式的 Telegram chat id 字符串。 +- 对于 `kind: "telegram"`,`admin/add` 会验证该结构,并拒绝格式错误的 payload。 -### 向 QA 添加一个渠道 +### 向 QA 添加一个 channel -向 Markdown QA 系统添加一个渠道需要且仅需要两样东西: +向 markdown QA 系统添加一个 channel,严格来说只需要两样东西: -1. 一个用于该渠道的传输适配器。 -2. 一个用于验证该渠道契约的场景包。 +1. 该 channel 的传输适配器。 +2. 一个用于验证该 channel 契约的场景包。 当共享的 `qa-lab` 主机可以承载整个流程时,不要新增顶层 QA 命令根。 `qa-lab` 负责共享主机机制: - `openclaw qa` 命令根 -- 套件启动与清理 -- 工作进程并发 -- 工件写入 +- 测试套件启动与清理 +- worker 并发 +- 产物写入 - 报告生成 - 场景执行 - 对旧版 `qa-channel` 场景的兼容别名 运行器插件负责传输契约: -- `openclaw qa ` 如何挂载在共享 `qa` 根命令之下 -- 如何为该传输配置 Gateway 网关 +- 如何将 `openclaw qa ` 挂载到共享的 `qa` 根命令下 +- 如何为该传输方式配置 Gateway 网关 - 如何检查就绪状态 - 如何注入入站事件 -- 如何观测出站消息 -- 如何暴露转录和规范化的传输状态 -- 如何执行由传输支持的操作 +- 如何观察出站消息 +- 如何暴露 transcript 和标准化后的传输状态 +- 如何执行基于传输的操作 - 如何处理传输特定的重置或清理 -新渠道的最低接入门槛是: +新 channel 的最低接入门槛是: -1. 保持 `qa-lab` 作为共享 `qa` 根命令的所有者。 +1. 保持 `qa-lab` 作为共享 `qa` 根命令的拥有者。 2. 在共享的 `qa-lab` 主机接缝上实现传输运行器。 -3. 将传输特定机制保留在运行器插件或渠道测试框架内部。 -4. 将运行器挂载为 `openclaw qa `,而不是注册一个相互竞争的根命令。 +3. 将传输特定机制保留在运行器插件或 channel harness 内部。 +4. 将运行器挂载为 `openclaw qa `,而不是注册一个竞争性的根命令。 运行器插件应在 `openclaw.plugin.json` 中声明 `qaRunners`,并从 `runtime-api.ts` 导出匹配的 `qaRunnerCliRegistrations` 数组。 - 保持 `runtime-api.ts` 足够轻量;惰性 CLI 和运行器执行应放在独立入口点之后。 -5. 在按主题组织的 `qa/scenarios/` 目录下编写或调整 Markdown 场景。 + 保持 `runtime-api.ts` 足够轻量;延迟 CLI 和运行器执行应放在独立入口点之后。 +5. 在主题化的 `qa/scenarios/` 目录下编写或改造 markdown 场景。 6. 为新场景使用通用场景辅助工具。 -7. 除非仓库正在进行有意迁移,否则保持现有兼容别名继续可用。 +7. 除非仓库正在进行有意迁移,否则保持现有兼容别名可用。 决策规则是严格的: - 如果某个行为可以在 `qa-lab` 中统一表达一次,就把它放在 `qa-lab` 中。 -- 如果某个行为依赖于某一个渠道传输,就把它保留在该运行器插件或插件测试框架中。 -- 如果一个场景需要多个渠道都能使用的新能力,应添加一个通用辅助工具,而不是在 `suite.ts` 中添加渠道特定分支。 -- 如果某个行为只对一种传输有意义,就让该场景保持传输特定,并在场景契约中明确说明。 +- 如果某个行为依赖单一 channel 传输方式,就将其保留在该运行器插件或插件 harness 中。 +- 如果某个场景需要超过一个 channel 都能使用的新能力,就添加通用 helper,而不是在 `suite.ts` 中添加 channel 特定分支。 +- 如果某个行为只对单一传输方式有意义,就让该场景保持传输特定性,并在场景契约中明确说明。 -新场景推荐使用的通用辅助工具名称是: +新场景推荐使用的通用 helper 名称是: - `waitForTransportReady` - `waitForChannelReady` @@ -253,100 +294,101 @@ Telegram 类型的负载结构: - `formatConversationTranscript` - `resetBus` -新的渠道工作应使用这些通用辅助工具名称。 -兼容别名的存在是为了避免一次性迁移日,而不是作为新场景编写的范式。 +新的 channel 工作应使用通用 helper 名称。 +兼容别名的存在是为了避免一次性迁移,不应作为 +新场景编写的范式。 -## 测试套件(各自运行位置) +## 测试套件(哪些测试在哪里运行) -可以把这些套件理解为“真实度逐步提高”(同时波动性/成本也会提高): +可以把这些测试套件理解为“真实性逐步提高”(以及不稳定性/成本也逐步提高): -### 单元 / 集成(默认) +### Unit / integration(默认) - 命令:`pnpm test` -- 配置:针对现有按范围划分的 Vitest projects 运行十个顺序分片(`vitest.full-*.config.ts`) -- 文件:`src/**/*.test.ts`、`packages/**/*.test.ts`、`test/**/*.test.ts` 下的 core/unit 清单,以及 `vitest.unit.config.ts` 涵盖的白名单 `ui` node 测试 +- 配置:在现有按范围划分的 Vitest projects 上执行十个顺序分片运行(`vitest.full-*.config.ts`) +- 文件:`vitest.unit.config.ts` 覆盖的 `src/**/*.test.ts`、`packages/**/*.test.ts`、`test/**/*.test.ts` 下的 core/unit 清单,以及白名单中的 `ui` node 测试 - 范围: - - 纯单元测试 - - 进程内集成测试(Gateway 网关认证、路由、工具、解析、配置) - - 针对已知缺陷的确定性回归测试 + - 纯 unit 测试 + - 进程内 integration 测试(Gateway 网关认证、路由、工具、解析、配置) + - 针对已知 bug 的确定性回归测试 - 预期: - 在 CI 中运行 - - 不需要真实密钥 - - 应当快速且稳定 + - 不需要真实 keys + - 应该快速且稳定 - Projects 说明: - - 未指定目标的 `pnpm test` 现在会运行 11 个更小的分片配置(`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`),而不是运行一个巨大的原生 root-project 进程。这样可以降低高负载机器上的峰值 RSS,并避免 auto-reply/extension 工作拖累无关套件。 - - `pnpm test --watch` 仍然使用原生根 `vitest.config.ts` project graph,因为多分片 watch 循环并不现实。 - - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 会先通过按范围划分的通道来路由显式文件/目录目标,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 不必承担完整 root project 启动成本。 - - 当变更 diff 仅触及可路由的源文件/测试文件时,`pnpm test:changed` 会将变更后的 git 路径展开到相同的按范围划分通道;配置/设置编辑仍会回退到更广泛的 root-project 重跑。 - - `pnpm check:changed` 是窄范围工作的常规智能本地门禁。它会将 diff 分类到 core、core tests、extensions、extension tests、apps、docs、发布元数据和工具中,然后运行匹配的 typecheck/lint/test 通道。公开的插件 SDK 和插件契约变更会包含 extension 验证,因为 extensions 依赖这些 core 契约。仅包含发布元数据的版本升级会运行针对性的版本/配置/根依赖检查,而不是完整套件,同时带有一个保护措施,拒绝顶层 version 字段以外的 package 变更。 - - 来自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 以及类似纯工具区域的轻导入单元测试会通过 `unit-fast` 通道路由,该通道会跳过 `test/setup-openclaw-runtime.ts`;有状态/运行时较重的文件则保留在现有通道中。 - - 选定的 `plugin-sdk` 和 `commands` 辅助源文件也会在 changed 模式运行时映射到这些轻量通道中的显式同级测试,因此辅助工具编辑无需为该目录重跑完整的重型套件。 - - `auto-reply` 现在有三个专用分桶:顶层 core helpers、顶层 `reply.*` 集成测试,以及 `src/auto-reply/reply/**` 子树。这样可以让最重的 reply 测试框架工作远离那些便宜的 status/chunk/token 测试。 -- 嵌入式运行器说明: + - 不带目标的 `pnpm test` 现在会运行十一个更小的分片配置(`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`),而不是单个庞大的原生 root-project 进程。这样可以降低高负载机器上的峰值 RSS,并避免 auto-reply/extension 工作拖慢无关测试套件。 + - `pnpm test --watch` 仍然使用原生根级 `vitest.config.ts` project graph,因为多分片 watch 循环并不现实。 + - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 现在会优先将显式文件/目录目标路由到按范围划分的通道,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 无需承担完整 root project 启动成本。 + - `pnpm test:changed` 会在 diff 仅触及可路由的源码/测试文件时,将变更的 git 路径扩展到同样的按范围通道;配置/设置类改动仍会回退到更广泛的 root-project 重跑。 + - `pnpm check:changed` 是面向窄范围工作的常规智能本地门禁。它会将 diff 分类为 core、core tests、extensions、extension tests、apps、docs、release metadata 和 tooling,然后运行匹配的 typecheck/lint/test 通道。公开的 插件 SDK 和插件契约变更会包含 extension 验证,因为 extensions 依赖这些 core 契约。仅包含发布元数据的版本变更会运行有针对性的 version/config/root-dependency 检查,而不是完整测试套件,并带有一项保护措施:若改动超出顶层版本字段,则会被拒绝。 + - 来自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 及类似纯工具区域的轻导入 unit 测试会路由到 `unit-fast` 通道,该通道会跳过 `test/setup-openclaw-runtime.ts`;有状态/运行时较重的文件则仍保留在现有通道中。 + - 选定的 `plugin-sdk` 和 `commands` helper 源文件还会在 changed 模式运行时映射到这些轻量通道中的显式同级测试,因此 helper 改动无需为该目录重跑完整的重型测试套件。 + - `auto-reply` 现在有三个专用分桶:顶层 core helpers、顶层 `reply.*` integration 测试,以及 `src/auto-reply/reply/**` 子树。这让最重的 reply harness 工作不再拖累轻量的 status/chunk/token 测试。 +- Embedded runner 说明: - 当你修改消息工具发现输入或压缩运行时上下文时, - 要保持两个层级的覆盖。 - - 为纯路由/规范化边界添加聚焦的辅助工具回归测试。 - - 同时也要保持嵌入式运行器集成套件健康: + 请同时保留两个层级的覆盖。 + - 为纯路由/标准化边界添加聚焦的 helper 回归测试。 + - 同时也要保证 embedded runner integration 测试套件保持健康: `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.test.ts` 和 `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`。 - - 这些套件会验证作用域 id 和压缩行为仍然会流经真实的 `run.ts` / `compact.ts` 路径;仅有辅助工具测试不能充分替代这些集成路径。 -- 池说明: + - 这些测试套件验证带作用域的 id 和压缩行为仍会流经真实的 `run.ts` / `compact.ts` 路径;仅有 helper 测试并不能充分替代这些 integration 路径。 +- Pool 说明: - 基础 Vitest 配置现在默认使用 `threads`。 - - 共享 Vitest 配置还固定了 `isolate: false`,并在根 projects、e2e 和实时配置中使用非隔离运行器。 - - 根 UI 通道保留其 `jsdom` 设置和优化器,但现在也在共享的非隔离运行器上运行。 - - 每个 `pnpm test` 分片都继承了共享 Vitest 配置中的相同 `threads` + `isolate: false` 默认值。 - - 共享的 `scripts/run-vitest.mjs` 启动器现在还会默认给 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。如果你需要与原生 V8 行为对比,可设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1`。 + - 共享 Vitest 配置还固定了 `isolate: false`,并在 root projects、e2e 和 live 配置中使用非隔离运行器。 + - 根级 UI 通道保留其 `jsdom` 设置和优化器,但现在也运行在共享的非隔离运行器上。 + - 每个 `pnpm test` 分片都从共享 Vitest 配置继承相同的 `threads` + `isolate: false` 默认值。 + - 共享的 `scripts/run-vitest.mjs` 启动器现在默认还会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。如果你需要对比原生 V8 行为,可设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1`。 - 快速本地迭代说明: - - `pnpm changed:lanes` 会显示某个 diff 会触发哪些架构通道。 - - pre-commit hook 会在对暂存内容完成格式化/lint 后运行 `pnpm check:changed --staged`,因此纯 core 提交不会承担 extension 测试成本,除非它们触及面向 extension 的公开契约。仅发布元数据提交会保留在针对性的版本/配置/根依赖通道。 - - 如果完全相同的暂存变更集已经通过同等或更强门禁验证,可以使用 `scripts/committer --fast "" ` 仅跳过 changed-scope hook 的重跑。暂存格式化/lint 仍会运行。请在交接中说明已完成的门禁。在孤立的 hook 偶发失败被重跑并通过、且有范围化证据时,这样做也是可以接受的。 - - 当变更路径可以清晰映射到较小套件时,`pnpm test:changed` 会通过按范围划分的通道进行路由。 + - `pnpm changed:lanes` 会显示某个 diff 触发了哪些架构通道。 + - pre-commit hook 会在已暂存内容完成格式化/lint 后运行 `pnpm check:changed --staged`,因此仅 core 的提交不会承担 extension 测试成本,除非它们触及面向 extension 的公共契约。仅发布元数据提交会保留在有针对性的 version/config/root-dependency 通道中。 + - 如果完全相同的 staged 变更集已经通过了同等或更强的门禁验证,可使用 `scripts/committer --fast "" ` 只跳过 changed-scope hook 的重复运行。staged format/lint 仍会运行。请在交接中说明已完成的门禁。这同样适用于隔离的 flaky hook 失败在重跑后通过并有范围化证明的情况。 + - 当变更路径能够清晰映射到较小测试套件时,`pnpm test:changed` 会通过按范围通道进行路由。 - `pnpm test:max` 和 `pnpm test:changed:max` 保持相同的路由行为,只是使用更高的 worker 上限。 - - 本地 worker 自动扩缩现在刻意更保守,并且当主机负载平均值已经很高时也会回退,因此多个并发 Vitest 运行默认造成的影响会更小。 - - 基础 Vitest 配置将 projects/config 文件标记为 `forceRerunTriggers`,从而在测试接线变更时保持 changed 模式重跑正确。 + - 本地 worker 自动缩放现在刻意更保守;当主机 load average 已经较高时也会回退,因此默认情况下多个并发 Vitest 运行对系统的影响更小。 + - 基础 Vitest 配置将 projects/config 文件标记为 `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:changed:bench -- --ref ` 会针对该提交 diff,比对经路由的 `test:changed` 与原生 root-project 路径,并输出墙钟时间以及 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。 + - `pnpm test:perf:imports` 会启用 Vitest 导入耗时报告以及导入拆解输出。 + - `pnpm test:perf:imports:changed` 会将同样的性能分析视图限定在自 `origin/main` 以来发生变更的文件上。 +- `pnpm test:perf:changed:bench -- --ref ` 会将路由后的 `test:changed` 与该提交 diff 的原生 root-project 路径进行比较,并打印 wall time 以及 macOS 最大 RSS。 +- `pnpm test:perf:changed:bench -- --worktree` 会通过 `scripts/test-projects.mjs` 和根 Vitest 配置,将当前脏工作树中的变更文件列表进行路由,并据此做基准测试。 + - `pnpm test:perf:profile:main` 会为 Vitest/Vite 启动和 transform 开销写出主线程 CPU profile。 + - `pnpm test:perf:profile:runner` 会在禁用文件并行的情况下,为 unit 测试套件写出 runner CPU+heap profile。 ### 稳定性(Gateway 网关) - 命令:`pnpm test:stability:gateway` -- 配置:`vitest.gateway.config.ts`,强制使用一个 worker +- 配置:`vitest.gateway.config.ts`,强制为单 worker - 范围: - - 启动一个真实的 loopback Gateway 网关,默认启用诊断 - - 通过诊断事件路径驱动合成的 Gateway 网关消息、内存和大负载抖动 + - 启动一个默认启用诊断的真实 local loopback Gateway 网关 + - 通过诊断事件路径驱动合成的 gateway 消息、memory 和大负载 churn - 通过 Gateway 网关 WS RPC 查询 `diagnostics.stability` - - 覆盖诊断稳定性包持久化辅助工具 - - 断言记录器保持有界、合成 RSS 采样低于压力预算,并且每个会话的队列深度会回落为零 + - 覆盖诊断稳定性 bundle 持久化 helper + - 断言 recorder 保持有界、合成 RSS 样本低于压力预算,并且每个会话的队列深度都能回落到零 - 预期: - - 对 CI 安全且无需密钥 - - 这是用于稳定性回归跟进的窄范围通道,不是完整 Gateway 网关套件的替代品 + - 对 CI 安全且无需 keys + - 这是用于稳定性回归跟进的窄通道,不可替代完整的 Gateway 网关测试套件 ### E2E(Gateway 网关冒烟) - 命令:`pnpm test:e2e` - 配置:`vitest.e2e.config.ts` -- 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的内置插件 E2E 测试 +- 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及位于 `extensions/` 下的内置插件 E2E 测试 - 运行时默认值: - 使用 Vitest `threads` 和 `isolate: false`,与仓库其余部分保持一致。 - - 使用自适应 workers(CI:最多 2 个,本地:默认 1 个)。 - - 默认以静默模式运行,以减少控制台 I/O 开销。 -- 常用覆盖选项: - - `OPENCLAW_E2E_WORKERS=` 强制指定 worker 数量(上限为 16)。 - - `OPENCLAW_E2E_VERBOSE=1` 重新启用详细控制台输出。 + - 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。 + - 默认以 silent 模式运行,以减少控制台 I/O 开销。 +- 常用覆盖项: + - `OPENCLAW_E2E_WORKERS=`:强制指定 worker 数量(上限为 16)。 + - `OPENCLAW_E2E_VERBOSE=1`:重新启用详细控制台输出。 - 范围: - 多实例 Gateway 网关端到端行为 - - WebSocket/HTTP 表面、节点配对以及更重的网络行为 + - WebSocket/HTTP 接口、节点配对以及更重的网络交互 - 预期: - - 在 CI 中运行(当流水线中启用时) - - 不需要真实密钥 - - 比单元测试包含更多可变部件(可能更慢) + - 在 CI 中运行(当流水线启用时) + - 不需要真实 keys + - 比 unit 测试有更多活动部件(可能更慢) ### E2E:OpenShell 后端冒烟 @@ -354,159 +396,159 @@ Telegram 类型的负载结构: - 文件:`extensions/openshell/src/backend.e2e.test.ts` - 范围: - 通过 Docker 在主机上启动一个隔离的 OpenShell Gateway 网关 - - 从临时本地 Dockerfile 创建一个沙箱 - - 通过真实的 `sandbox ssh-config` + SSH exec 练习 OpenClaw 的 OpenShell 后端 - - 通过沙箱 fs bridge 验证远程规范化文件系统行为 + - 从一个临时本地 Dockerfile 创建沙箱 + - 通过真实的 `sandbox ssh-config` + SSH exec 执行 OpenClaw 的 OpenShell 后端 + - 通过沙箱 fs bridge 验证远端规范化文件系统行为 - 预期: - - 仅按需启用;不属于默认 `pnpm test:e2e` 运行的一部分 + - 仅按需启用;不属于默认的 `pnpm test:e2e` 运行 - 需要本地 `openshell` CLI 和可用的 Docker daemon - - 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 Gateway 网关和沙箱 -- 常用覆盖选项: - - `OPENCLAW_E2E_OPENSHELL=1` 可在手动运行更广泛 e2e 套件时启用该测试 - - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` 可指向非默认 CLI 二进制或包装脚本 + - 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,随后销毁测试 Gateway 网关和沙箱 +- 常用覆盖项: + - `OPENCLAW_E2E_OPENSHELL=1`:在手动运行更广泛 e2e 测试套件时启用此测试 + - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`:指向非默认的 CLI 二进制文件或包装脚本 -### 实时(真实提供商 + 真实模型) +### Live(真实提供商 + 真实模型) - 命令:`pnpm test:live` - 配置:`vitest.live.config.ts` -- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件实时测试 +- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件 live 测试 - 默认:由 `pnpm test:live` **启用**(会设置 `OPENCLAW_LIVE_TEST=1`) - 范围: - - “这个提供商/模型在 _今天_ 配合真实凭证是否真的可用?” - - 捕获提供商格式变更、工具调用怪癖、认证问题和速率限制行为 + - “这个提供商/模型在 _今天_ 搭配真实凭证时是否真的可用?” + - 捕捉提供商格式变化、工具调用怪癖、认证问题以及限流行为 - 预期: - - 按设计并不具备 CI 稳定性(真实网络、真实提供商策略、配额、故障) - - 会花费金钱 / 消耗速率限制 - - 优先运行收窄后的子集,而不是“全部” -- 实时运行会加载 `~/.profile` 以获取缺失的 API 密钥。 -- 默认情况下,实时运行仍会隔离 `HOME`,并将配置/认证材料复制到临时测试 home 中,这样单元测试夹具就不会修改你真实的 `~/.openclaw`。 -- 仅当你明确需要让实时测试使用真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。 -- `pnpm test:live` 现在默认使用更安静的模式:它会保留 `[live] ...` 进度输出,但会抑制额外的 `~/.profile` 提示,并静音 Gateway 网关启动日志/Bonjour 噪声。如果你想恢复完整启动日志,请设置 `OPENCLAW_LIVE_TEST_QUIET=0`。 -- API 密钥轮换(提供商特定):设置 `*_API_KEYS`,使用逗号/分号格式,或设置 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),或者通过 `OPENCLAW_LIVE_*_KEY` 为实时测试单独覆盖;测试会在收到速率限制响应时重试。 -- 进度/心跳输出: - - 实时套件现在会将进度行输出到 stderr,因此即使 Vitest 控制台捕获较安静,长时间的提供商调用也能明显显示为正在活动。 - - `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,因此提供商/Gateway 网关进度行会在实时运行期间立即流式输出。 - - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整直连模型心跳。 - - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关/探针心跳。 + - 按设计不具备 CI 稳定性(真实网络、真实提供商策略、配额、故障) + - 会花钱 / 占用限流额度 + - 优先运行收窄后的子集,而不是“全部都跑” +- live 运行会读取 `~/.profile`,以补齐缺失的 API keys。 +- 默认情况下,live 运行仍会隔离 `HOME`,并将配置/认证材料复制到一个临时测试 home 中,这样 unit fixtures 就不会修改你真实的 `~/.openclaw`。 +- 仅当你明确需要 live 测试使用真实 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` 为 live 测试单独覆盖;测试会在收到限流响应时重试。 +- 进度/heartbeat 输出: + - live 测试套件现在会将进度行输出到 stderr,这样即使 Vitest 控制台捕获处于安静模式,长时间的提供商调用也能明显显示仍在执行。 + - `vitest.live.config.ts` 会禁用 Vitest 的控制台拦截,因此提供商/gateway 进度行会在 live 运行期间立即流出。 + - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整 direct-model heartbeat。 + - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 gateway/probe heartbeat。 ## 我应该运行哪个测试套件? -使用这个决策表: +使用下面这个决策表: -- 编辑逻辑/测试:运行 `pnpm test`(如果你改动很多,再加上 `pnpm test:coverage`) -- 触及 Gateway 网关网络 / WS 协议 / 配对:加跑 `pnpm test:e2e` -- 调试“我的机器人宕了”/ 提供商特定失败 / 工具调用:运行收窄后的 `pnpm test:live` +- 编辑逻辑/测试:运行 `pnpm test`(如果改动较多,再加上 `pnpm test:coverage`) +- 修改 Gateway 网关网络 / WS 协议 / 配对:额外运行 `pnpm test:e2e` +- 调试“我的 bot 挂了”/ 提供商特定失败 / 工具调用:运行收窄后的 `pnpm test:live` -## 实时:Android 节点能力扫描 +## Live:Android 节点能力扫描 - 测试:`src/gateway/android-node.capabilities.live.test.ts` - 脚本:`pnpm android:test:integration` -- 目标:调用已连接 Android 节点当前声明的**每一个命令**,并断言命令契约行为。 +- 目标:调用一个已连接 Android 节点当前**宣告的每个命令**,并断言命令契约行为。 - 范围: - - 有前置条件/需要手动设置(该套件不会安装/运行/配对应用)。 - - 针对所选 Android 节点逐条验证 Gateway 网关 `node.invoke`。 -- 所需前置设置: - - Android 应用已连接并已与 Gateway 网关配对。 - - 应用保持在前台。 - - 已为你期望通过的能力授予权限/捕获同意。 + - 预先准备/手动设置(该测试套件不会安装/运行/配对 app)。 + - 针对所选 Android 节点逐命令验证 gateway `node.invoke`。 +- 必需的预设准备: + - Android app 已连接并与 gateway 完成配对。 + - app 保持前台运行。 + - 对你期望通过的能力授予了权限/捕获同意。 - 可选目标覆盖: - `OPENCLAW_ANDROID_NODE_ID` 或 `OPENCLAW_ANDROID_NODE_NAME`。 - `OPENCLAW_ANDROID_GATEWAY_URL` / `OPENCLAW_ANDROID_GATEWAY_TOKEN` / `OPENCLAW_ANDROID_GATEWAY_PASSWORD`。 - 完整 Android 设置详情:[Android App](/zh-CN/platforms/android) -## 实时:模型冒烟测试(profile keys) +## Live:模型冒烟(profile keys) -实时测试分为两层,以便我们隔离故障: +live 测试分成两层,以便我们隔离故障: -- “直连模型”告诉我们,给定密钥时该提供商/模型是否至少能响应。 -- “Gateway 网关冒烟”告诉我们,完整的 Gateway 网关 + 智能体流水线是否适用于该模型(会话、历史、工具、沙箱策略等)。 +- “Direct model” 告诉我们,提供商/模型在给定 key 下是否至少能正常响应。 +- “Gateway smoke” 告诉我们,针对该模型的完整 gateway + 智能体链路是否正常工作(会话、历史、工具、沙箱策略等)。 -### 第 1 层:直连模型补全(无 Gateway 网关) +### 第 1 层:Direct model completion(无 gateway) - 测试:`src/agents/models.profiles.live.test.ts` - 目标: - - 枚举已发现的模型 + - 枚举发现到的模型 - 使用 `getApiKeyForModel` 选择你拥有凭证的模型 - - 为每个模型运行一个小型补全(并在需要时运行有针对性的回归) + - 为每个模型运行一个小型 completion(并在需要时运行有针对性的回归测试) - 启用方式: - - `pnpm test:live`(如果直接调用 Vitest,则设置 `OPENCLAW_LIVE_TEST=1`) -- 设置 `OPENCLAW_LIVE_MODELS=modern`(或 `all`,即 modern 的别名)后,才会实际运行此套件;否则它会跳过,以便让 `pnpm test:live` 聚焦于 Gateway 网关冒烟测试 -- 选择模型的方法: - - `OPENCLAW_LIVE_MODELS=modern` 运行 modern 允许列表(Opus/Sonnet 4.6+、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4) - - `OPENCLAW_LIVE_MODELS=all` 是 modern 允许列表的别名 - - 或设置 `OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,..."`(逗号分隔的允许列表) - - modern/all 扫描默认使用精心挑选的高信号上限;设置 `OPENCLAW_LIVE_MAX_MODELS=0` 可执行穷尽的 modern 扫描,或设置为正数以指定更小的上限。 -- 选择提供商的方法: - - `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"`(逗号分隔的允许列表) -- 密钥来源: - - 默认:profile 存储和环境变量回退 - - 设置 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 以强制**仅使用 profile 存储** -- 存在原因: - - 将“提供商 API 坏了 / 密钥无效”和“Gateway 网关智能体流水线坏了”区分开来 - - 包含小型、隔离的回归测试(例如:OpenAI Responses/Codex Responses 推理回放 + 工具调用流程) + - `pnpm test:live`(或在直接调用 Vitest 时设置 `OPENCLAW_LIVE_TEST=1`) +- 设置 `OPENCLAW_LIVE_MODELS=modern`(或 `all`,它是 modern 的别名)后才会真正运行该测试套件;否则它会跳过,以让 `pnpm test:live` 聚焦于 gateway smoke +- 模型选择方式: + - `OPENCLAW_LIVE_MODELS=modern`:运行现代 allowlist(Opus/Sonnet 4.6+、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4) + - `OPENCLAW_LIVE_MODELS=all` 是现代 allowlist 的别名 + - 或 `OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,..."`(逗号分隔的 allowlist) + - modern/all 扫描默认有一个精心挑选的高信号数量上限;设置 `OPENCLAW_LIVE_MAX_MODELS=0` 可进行穷尽式 modern 扫描,或设置正数以使用更小的上限。 +- 提供商选择方式: + - `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"`(逗号分隔的 allowlist) +- keys 来源: + - 默认:profile store 和环境变量回退 + - 设置 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 可强制 **仅** 使用 profile store +- 这个测试存在的原因: + - 将“提供商 API 坏了 / key 无效”和“gateway 智能体链路坏了”区分开 + - 承载小而隔离的回归测试(示例:OpenAI Responses/Codex Responses 的推理重放 + 工具调用流程) -### 第 2 层:Gateway 网关 + dev 智能体冒烟测试(即 “@openclaw” 实际执行的内容) +### 第 2 层:Gateway + dev 智能体冒烟(也就是 “@openclaw” 实际做的事) - 测试:`src/gateway/gateway-models.profiles.live.test.ts` - 目标: - - 启动一个进程内 Gateway 网关 + - 启动一个进程内 gateway - 创建/修补一个 `agent:dev:*` 会话(每次运行按模型覆盖) - - 遍历带密钥的模型并断言: - - “有意义”的响应(无工具) - - 一个真实工具调用可用(读取探针) - - 可选的额外工具探针(exec+read 探针) - - OpenAI 回归路径(仅工具调用 → 后续跟进)持续可用 -- 探针细节(这样你可以快速解释故障): - - `read` 探针:测试会在工作区中写入一个 nonce 文件,并要求智能体 `read` 该文件并回显 nonce。 - - `exec+read` 探针:测试会要求智能体通过 `exec` 将 nonce 写入一个临时文件,然后再将其 `read` 回来。 - - 图像探针:测试会附加一个生成的 PNG(猫 + 随机代码),并期望模型返回 `cat `。 + - 遍历带 keys 的模型并断言: + - “有意义的”响应(不使用工具) + - 一个真实的工具调用可用(read probe) + - 可选的额外工具探测(exec+read probe) + - OpenAI 回归路径(仅工具调用 → 后续跟进)保持可用 +- Probe 细节(这样你可以快速解释失败原因): + - `read` probe:测试会在工作区写入一个 nonce 文件,并要求智能体 `read` 该文件并回显 nonce。 + - `exec+read` probe:测试会要求智能体用 `exec` 将 nonce 写入一个临时文件,然后再用 `read` 读回来。 + - image probe:测试会附加一个生成的 PNG(猫 + 随机代码),并期望模型返回 `cat `。 - 实现参考:`src/gateway/gateway-models.profiles.live.test.ts` 和 `src/gateway/live-image-probe.ts`。 - 启用方式: - - `pnpm test:live`(如果直接调用 Vitest,则设置 `OPENCLAW_LIVE_TEST=1`) -- 选择模型的方法: - - 默认:modern 允许列表(Opus/Sonnet 4.6+、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4) - - `OPENCLAW_LIVE_GATEWAY_MODELS=all` 是 modern 允许列表的别名 - - 或设置 `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"`(或逗号列表)来收窄范围 - - modern/all Gateway 网关扫描默认使用精心挑选的高信号上限;设置 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` 可执行穷尽的 modern 扫描,或设置为正数以指定更小的上限。 -- 选择提供商的方法(避免“OpenRouter 全家桶”): - - `OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"`(逗号分隔的允许列表) -- 工具 + 图像探针在此实时测试中始终启用: - - `read` 探针 + `exec+read` 探针(工具压力测试) - - 当模型声明支持图像输入时,会运行图像探针 - - 流程(高层级): - - 测试生成一个带有 “CAT” + 随机代码的小型 PNG(`src/gateway/live-image-probe.ts`) - - 通过 `agent` `attachments: [{ mimeType: "image/png", content: "" }]` 发送它 - - Gateway 网关将附件解析为 `images[]`(`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`) - - 嵌入式智能体将多模态用户消息转发给模型 + - `pnpm test:live`(或在直接调用 Vitest 时设置 `OPENCLAW_LIVE_TEST=1`) +- 模型选择方式: + - 默认:现代 allowlist(Opus/Sonnet 4.6+、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4) + - `OPENCLAW_LIVE_GATEWAY_MODELS=all` 是现代 allowlist 的别名 + - 或设置 `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"`(或逗号列表)以收窄范围 + - modern/all gateway 扫描默认有一个精心挑选的高信号数量上限;设置 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` 可进行穷尽式 modern 扫描,或设置正数以使用更小的上限。 +- 提供商选择方式(避免“OpenRouter 全家桶”): + - `OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"`(逗号分隔的 allowlist) +- 工具 + 图像 probes 在这个 live 测试中始终启用: + - `read` probe + `exec+read` probe(工具压力测试) + - 当模型宣告支持图像输入时,会运行 image probe + - 流程(高层概览): + - 测试生成一个带有 “CAT” + 随机代码 的小 PNG(`src/gateway/live-image-probe.ts`) + - 通过 `agent` 的 `attachments: [{ mimeType: "image/png", content: "" }]` 发送 + - Gateway 网关将附件解析到 `images[]` 中(`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`) + - Embedded 智能体将多模态用户消息转发给模型 - 断言:回复包含 `cat` + 该代码(OCR 容错:允许轻微错误) -提示:如果想查看你的机器上可以测试什么(以及精确的 `provider/model` id),请运行: +提示:如果你想查看你的机器上可以测试什么(以及精确的 `provider/model` id),运行: ```bash openclaw models list openclaw models list --json ``` -## 实时:CLI 后端冒烟测试(Claude、Codex、Gemini 或其他本地 CLI) +## Live:CLI 后端冒烟(Claude、Codex、Gemini 或其他本地 CLI) - 测试:`src/gateway/gateway-cli-backend.live.test.ts` -- 目标:使用本地 CLI 后端验证 Gateway 网关 + 智能体流水线,而不触碰你的默认配置。 -- 后端特定的默认冒烟测试配置位于对应扩展的 `cli-backend.ts` 定义中。 -- 启用: - - `pnpm test:live`(如果直接调用 Vitest,则设置 `OPENCLAW_LIVE_TEST=1`) +- 目标:使用本地 CLI 后端验证 Gateway 网关 + 智能体链路,同时不触碰你的默认配置。 +- 后端特定的冒烟默认值位于所属 extension 的 `cli-backend.ts` 定义中。 +- 启用方式: + - `pnpm test:live`(或在直接调用 Vitest 时设置 `OPENCLAW_LIVE_TEST=1`) - `OPENCLAW_LIVE_CLI_BACKEND=1` - 默认值: - - 默认提供商/模型:`claude-cli/claude-sonnet-4-6` - - 命令/参数/图像行为来自所属 CLI 后端插件元数据。 + - 默认 provider/model:`claude-cli/claude-sonnet-4-6` + - command/args/image 行为来自所属 CLI 后端插件元数据。 - 覆盖项(可选): - `OPENCLAW_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.4"` - `OPENCLAW_LIVE_CLI_BACKEND_COMMAND="/full/path/to/codex"` - `OPENCLAW_LIVE_CLI_BACKEND_ARGS='["exec","--json","--color","never","--sandbox","read-only","--skip-git-repo-check"]'` - - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1` 发送真实图像附件(路径会注入到提示中)。 - - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` 通过 CLI 参数而不是提示注入来传递图像文件路径。 - - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"`(或 `"list"`)控制在设置 `IMAGE_ARG` 时如何传递图像参数。 - - `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1` 发送第二轮消息并验证恢复流程。 - - `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0` 禁用默认的 Claude Sonnet -> Opus 同会话连续性探针(当所选模型支持切换目标时,可设置为 `1` 强制启用)。 + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1`:发送真实图像附件(路径会注入到提示词中)。 + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"`:将图像文件路径作为 CLI 参数传递,而不是通过提示词注入。 + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"`(或 `"list"`):当设置了 `IMAGE_ARG` 时,控制图像参数的传递方式。 + - `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1`:发送第二轮并验证恢复流程。 + - `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`:禁用默认的 Claude Sonnet -> Opus 同会话连续性 probe(当所选模型支持切换目标时,设置为 `1` 可强制启用)。 示例: @@ -534,26 +576,26 @@ pnpm test:docker:live-cli-backend:gemini 说明: - Docker 运行器位于 `scripts/test-live-cli-backend-docker.sh`。 -- 它会在仓库 Docker 镜像内,以非 root 的 `node` 用户身份运行实时 CLI 后端冒烟测试。 -- 它会从所属扩展中解析 CLI 冒烟测试元数据,然后将匹配的 Linux CLI 包(`@anthropic-ai/claude-code`、`@openai/codex` 或 `@google/gemini-cli`)安装到位于 `OPENCLAW_DOCKER_CLI_TOOLS_DIR` 的可写缓存前缀中(默认:`~/.cache/openclaw/docker-cli-tools`)。 -- `pnpm test:docker:live-cli-backend:claude-subscription` 需要通过 `~/.claude/.credentials.json` 中带有 `claudeAiOauth.subscriptionType` 的可移植 Claude Code 订阅 OAuth,或使用来自 `claude setup-token` 的 `CLAUDE_CODE_OAUTH_TOKEN`。它会先证明 Docker 中直接 `claude -p` 可用,然后在不保留 Anthropic API 密钥环境变量的情况下运行两轮 Gateway 网关 CLI 后端测试。该订阅通道默认禁用 Claude MCP/工具和图像探针,因为 Claude 目前会通过额外用量计费来路由第三方应用使用,而不是走普通订阅套餐限制。 -- 实时 CLI 后端冒烟测试现在会为 Claude、Codex 和 Gemini 演练相同的端到端流程:文本轮次、图像分类轮次,然后通过 Gateway 网关 CLI 验证 MCP `cron` 工具调用。 -- Claude 的默认冒烟测试还会将会话从 Sonnet 修补为 Opus,并验证恢复后的会话仍记得更早的笔记。 +- 它会在仓库 Docker 镜像中,以非 root 的 `node` 用户身份运行 live CLI 后端冒烟测试。 +- 它会从所属 extension 中解析 CLI 冒烟元数据,然后将匹配的 Linux CLI 包(`@anthropic-ai/claude-code`、`@openai/codex` 或 `@google/gemini-cli`)安装到可缓存、可写的前缀目录 `OPENCLAW_DOCKER_CLI_TOOLS_DIR`(默认:`~/.cache/openclaw/docker-cli-tools`)。 +- `pnpm test:docker:live-cli-backend:claude-subscription` 需要可移植的 Claude Code 订阅 OAuth,可通过 `~/.claude/.credentials.json` 中的 `claudeAiOauth.subscriptionType`,或来自 `claude setup-token` 的 `CLAUDE_CODE_OAUTH_TOKEN` 提供。它会先在 Docker 中直接验证 `claude -p`,然后在不保留 Anthropic API-key 环境变量的情况下运行两轮 Gateway 网关 CLI 后端交互。由于 Claude 当前会将第三方 app 使用量路由到额外用量计费,而不是普通订阅套餐额度,因此这个订阅通道默认禁用了 Claude MCP/tool 和 image probes。 +- live CLI 后端冒烟测试现在会对 Claude、Codex 和 Gemini 执行相同的端到端流程:文本轮次、图像分类轮次,然后通过 gateway CLI 验证 MCP `cron` 工具调用。 +- Claude 的默认冒烟测试还会将会话从 Sonnet 切换到 Opus,并验证恢复后的会话仍然记得之前的笔记。 -## 实时:ACP 绑定冒烟测试(`/acp spawn ... --bind here`) +## Live:ACP 绑定冒烟(`/acp spawn ... --bind here`) - 测试:`src/gateway/gateway-acp-bind.live.test.ts` -- 目标:使用实时 ACP 智能体验证真实 ACP 会话绑定流程: +- 目标:使用一个 live ACP 智能体验证真实的 ACP 会话绑定流程: - 发送 `/acp spawn --bind here` - - 原地绑定一个合成的消息渠道会话 - - 在同一个会话上发送一条普通后续消息 - - 验证该后续消息落入已绑定 ACP 会话的转录中 -- 启用: + - 就地绑定一个合成的 message-channel 会话 + - 在同一个会话上发送一次普通后续消息 + - 验证该后续消息会落入已绑定的 ACP 会话 transcript 中 +- 启用方式: - `pnpm test:live src/gateway/gateway-acp-bind.live.test.ts` - `OPENCLAW_LIVE_ACP_BIND=1` - 默认值: - Docker 中的 ACP 智能体:`claude,codex,gemini` - - 直接 `pnpm test:live ...` 使用的 ACP 智能体:`claude` + - 直接执行 `pnpm test:live ...` 时的 ACP 智能体:`claude` - 合成渠道:Slack 私信风格的会话上下文 - ACP 后端:`acpx` - 覆盖项: @@ -564,8 +606,8 @@ pnpm test:docker:live-cli-backend:gemini - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND='npx -y @agentclientprotocol/claude-agent-acp@'` - `OPENCLAW_LIVE_ACP_BIND_CODEX_MODEL=gpt-5.4` - 说明: - - 此通道使用 Gateway 网关 `chat.send` 接口,并带有仅管理员可用的合成来源路由字段,因此测试可以附加消息渠道上下文,而无需假装进行外部投递。 - - 当未设置 `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` 时,测试会使用嵌入式 `acpx` 插件内置的智能体注册表来处理所选 ACP 测试智能体。 + - 这个通道使用 gateway 的 `chat.send` 接口,并带有仅限管理员使用的合成 originating-route 字段,因此测试可以附加 message-channel 上下文,而无需假装执行外部投递。 + - 当未设置 `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` 时,测试会使用内置 `acpx` 插件的内建智能体注册表来选择所需的 ACP harness 智能体。 示例: @@ -592,33 +634,32 @@ pnpm test:docker:live-acp-bind:gemini Docker 说明: - Docker 运行器位于 `scripts/test-live-acp-bind-docker.sh`。 -- 默认情况下,它会按顺序对所有受支持的实时 CLI 智能体运行 ACP 绑定冒烟测试:`claude`、`codex`,然后是 `gemini`。 -- 使用 `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude`、`OPENCLAW_LIVE_ACP_BIND_AGENTS=codex` 或 `OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini` 可缩小矩阵范围。 -- 它会加载 `~/.profile`,将匹配的 CLI 认证材料暂存到容器中,把 `acpx` 安装到可写 npm 前缀中,然后在缺失时安装所请求的实时 CLI(`@anthropic-ai/claude-code`、`@openai/codex` 或 `@google/gemini-cli`)。 -- 在 Docker 内部,运行器会设置 `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`,以便 acpx 保持从已加载 profile 获取的提供商环境变量对其子测试 CLI 可用。 +- 默认情况下,它会按顺序对所有受支持的 live CLI 智能体运行 ACP 绑定冒烟测试:`claude`、`codex`,然后是 `gemini`。 +- 使用 `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude`、`OPENCLAW_LIVE_ACP_BIND_AGENTS=codex` 或 `OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini` 可收窄 matrix。 +- 它会读取 `~/.profile`,将匹配的 CLI 认证材料暂存到容器中,在可写的 npm 前缀中安装 `acpx`,然后在缺失时安装所请求的 live CLI(`@anthropic-ai/claude-code`、`@openai/codex` 或 `@google/gemini-cli`)。 +- 在 Docker 内部,运行器会设置 `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`,这样 acpx 就能让来自已读取 profile 的提供商环境变量继续对其子 harness CLI 可见。 -## 实时:Codex app-server 测试框架冒烟测试 +## Live:Codex app-server harness 冒烟测试 -- 目标:通过常规 Gateway 网关 - `agent` 方法验证由插件拥有的 Codex 测试框架: +- 目标:通过常规 gateway + `agent` 方法验证由插件拥有的 Codex harness: - 加载内置的 `codex` 插件 - 选择 `OPENCLAW_AGENT_RUNTIME=codex` - - 向 `codex/gpt-5.4` 发送第一轮 Gateway 网关智能体消息 - - 向同一个 OpenClaw 会话发送第二轮消息,并验证 app-server + - 向 `codex/gpt-5.4` 发送第一轮 gateway 智能体请求 + - 向同一个 OpenClaw 会话发送第二轮请求,并验证 app-server 线程可以恢复 - - 通过相同的 Gateway 网关命令 + - 通过同一条 gateway 命令 路径运行 `/codex status` 和 `/codex models` - - 可选运行两个经 Guardian 审查的提权 shell 探针:一个应被批准的良性 - 命令,以及一个应被拒绝的伪造密钥上传命令, - 这样智能体会反问确认 + - 可选地运行两个经过 Guardian 审查的提权 shell probe:一个应被批准的无害命令, + 以及一个应被拒绝的伪造 secret 上传命令,从而让智能体反问确认 - 测试:`src/gateway/gateway-codex-harness.live.test.ts` - 启用:`OPENCLAW_LIVE_CODEX_HARNESS=1` - 默认模型:`codex/gpt-5.4` -- 可选图像探针:`OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1` -- 可选 MCP/工具探针:`OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1` -- 可选 Guardian 探针:`OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1` +- 可选图像 probe:`OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1` +- 可选 MCP/tool probe:`OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1` +- 可选 Guardian probe:`OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1` - 该冒烟测试会设置 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`,因此损坏的 Codex - 测试框架不能通过静默回退到 PI 来蒙混过关。 + harness 不能通过悄悄回退到 Pi 而蒙混过关。 - 认证:来自 shell/profile 的 `OPENAI_API_KEY`,以及可选复制的 `~/.codex/auth.json` 和 `~/.codex/config.toml` @@ -644,51 +685,49 @@ pnpm test:docker:live-codex-harness Docker 说明: - Docker 运行器位于 `scripts/test-live-codex-harness-docker.sh`。 -- 它会加载挂载的 `~/.profile`,传递 `OPENAI_API_KEY`,在存在时复制 Codex CLI - 认证文件,将 `@openai/codex` 安装到可写挂载 npm - 前缀中,暂存源代码树,然后只运行 Codex 测试框架实时测试。 -- Docker 默认启用图像、MCP/工具和 Guardian 探针。设置 +- 它会读取挂载的 `~/.profile`,传递 `OPENAI_API_KEY`,在存在时复制 Codex CLI + 认证文件,将 `@openai/codex` 安装到可写的挂载 npm 前缀中,暂存源代码树,然后只运行 Codex-harness live 测试。 +- Docker 默认启用 image、MCP/tool 和 Guardian probes。需要更窄的调试运行时,可设置 `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0` 或 `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0` 或 - `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0`,当你需要更窄范围的调试 - 运行时使用。 -- Docker 还会导出 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`,与实时 - 测试配置保持一致,因此 `openai-codex/*` 或 PI 回退都无法掩盖 Codex 测试框架 + `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0`。 +- Docker 还会导出 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`,与 live + 测试配置保持一致,因此 `openai-codex/*` 或 Pi 回退都无法掩盖 Codex harness 回归问题。 -### 推荐的实时测试配方 +### 推荐的 live 配方 -范围窄、显式的允许列表最快,也最不容易波动: +范围窄且明确的 allowlist 最快,也最不容易波动: -- 单模型,直连(无 Gateway 网关): +- 单模型,direct(无 gateway): - `OPENCLAW_LIVE_MODELS="openai/gpt-5.4" pnpm test:live src/agents/models.profiles.live.test.ts` -- 单模型,Gateway 网关冒烟测试: +- 单模型,gateway 冒烟: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -- 多个提供商的工具调用: +- 跨多个提供商的工具调用: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -- Google 聚焦(Gemini API key + Antigravity): +- Google 重点场景(Gemini API key + Antigravity): - Gemini(API key):`OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` - Antigravity(OAuth):`OPENCLAW_LIVE_GATEWAY_MODELS="google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-pro-high" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` 说明: - `google/...` 使用 Gemini API(API key)。 -- `google-antigravity/...` 使用 Antigravity OAuth bridge(Cloud Code Assist 风格的智能体端点)。 -- `google-gemini-cli/...` 使用你机器上的本地 Gemini CLI(单独的认证 + 工具行为差异)。 +- `google-antigravity/...` 使用 Antigravity OAuth bridge(Cloud Code Assist 风格的智能体 endpoint)。 +- `google-gemini-cli/...` 使用你机器上的本地 Gemini CLI(独立的认证 + 工具行为差异)。 - Gemini API 与 Gemini CLI: - - API:OpenClaw 通过 HTTP 调用 Google 托管的 Gemini API(API key / profile 认证);这是大多数用户提到 “Gemini” 时的含义。 - - CLI:OpenClaw 会调用本地 `gemini` 二进制;它有自己的认证,并且行为可能不同(流式传输/工具支持/版本偏差)。 + - API:OpenClaw 通过 HTTP 调用 Google 托管的 Gemini API(API key / profile 认证);这通常就是大多数用户所说的 “Gemini”。 + - CLI:OpenClaw 会调用本地 `gemini` 二进制文件;它有自己的认证方式,并且行为可能不同(流式传输/工具支持/版本偏差)。 -## 实时:模型矩阵(我们覆盖什么) +## Live:模型矩阵(我们覆盖什么) -没有固定的 “CI 模型列表”(实时测试是按需启用的),但这些是建议在有密钥的开发机上定期覆盖的**推荐**模型。 +没有固定的“CI 模型列表”(live 是按需启用的),但以下是**推荐**在拥有 keys 的开发机器上定期覆盖的模型。 -### 现代冒烟测试集(工具调用 + 图像) +### 现代冒烟集(工具调用 + 图像) -这是我们预期要持续保持可用的 “常用模型” 运行集合: +这是我们期望始终保持可用的“常用模型”运行集: - OpenAI(非 Codex):`openai/gpt-5.4`(可选:`openai/gpt-5.4-mini`) - OpenAI Codex:`openai-codex/gpt-5.4` @@ -698,12 +737,12 @@ Docker 说明: - Z.AI(GLM):`zai/glm-4.7` - MiniMax:`minimax/MiniMax-M2.7` -运行带工具 + 图像的 Gateway 网关冒烟测试: +运行带工具 + 图像的 gateway 冒烟测试: `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,openai-codex/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3.1-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` ### 基线:工具调用(Read + 可选 Exec) -每个提供商家族至少选择一个: +每个提供商家族至少选一个: - OpenAI:`openai/gpt-5.4`(或 `openai/gpt-5.4-mini`) - Anthropic:`anthropic/claude-opus-4-6`(或 `anthropic/claude-sonnet-4-6`) @@ -714,72 +753,72 @@ Docker 说明: 可选的额外覆盖(有更好,没有也行): - xAI:`xai/grok-4`(或最新可用版本) -- Mistral:`mistral/`…(选择一个你已启用、具备工具能力的模型) +- Mistral:`mistral/`…(选择一个你已启用的支持工具调用的模型) - Cerebras:`cerebras/`…(如果你有访问权限) - LM Studio:`lmstudio/`…(本地;工具调用取决于 API 模式) -### 视觉:图像发送(附件 → 多模态消息) +### Vision:发送图像(附件 → 多模态消息) -在 `OPENCLAW_LIVE_GATEWAY_MODELS` 中至少包含一个具备图像能力的模型(Claude/Gemini/OpenAI 具备视觉能力的变体等),以覆盖图像探针。 +在 `OPENCLAW_LIVE_GATEWAY_MODELS` 中至少包含一个支持图像的模型(Claude/Gemini/OpenAI 的支持视觉的变体等),以覆盖 image probe。 ### 聚合器 / 替代 Gateway 网关 -如果你启用了相关密钥,我们也支持通过以下方式测试: +如果你已启用相关 keys,我们也支持通过以下方式测试: -- OpenRouter:`openrouter/...`(数百个模型;使用 `openclaw models scan` 查找具备工具 + 图像能力的候选模型) +- OpenRouter:`openrouter/...`(数百个模型;使用 `openclaw models scan` 查找支持工具 + 图像的候选模型) - OpenCode:Zen 使用 `opencode/...`,Go 使用 `opencode-go/...`(通过 `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY` 认证) -如果你有凭证/配置,还可以将更多提供商纳入实时矩阵: +如果你有 creds/config,还可以把以下更多提供商加入 live matrix: - 内置:`openai`、`openai-codex`、`anthropic`、`google`、`google-vertex`、`google-antigravity`、`google-gemini-cli`、`zai`、`openrouter`、`opencode`、`opencode-go`、`xai`、`groq`、`cerebras`、`mistral`、`github-copilot` -- 通过 `models.providers`(自定义端点):`minimax`(云/API),以及任何兼容 OpenAI/Anthropic 的代理(LM Studio、vLLM、LiteLLM 等) +- 通过 `models.providers`(自定义 endpoints):`minimax`(云/API),以及任何兼容 OpenAI/Anthropic 的代理(LM Studio、vLLM、LiteLLM 等) -提示:不要试图在文档中硬编码 “所有模型”。权威列表是你机器上 `discoverModels(...)` 返回的内容 + 当前可用的密钥。 +提示:不要试图在文档中硬编码“所有模型”。权威列表始终是你的机器上 `discoverModels(...)` 返回的内容,以及当前可用的 keys。 -## 凭证(绝不要提交) +## 凭证(切勿提交) -实时测试发现凭证的方式与 CLI 相同。实际含义如下: +live 测试发现凭证的方式与 CLI 相同。实际含义如下: -- 如果 CLI 可用,实时测试也应该能找到相同的密钥。 -- 如果实时测试提示 “no creds”,请按调试 `openclaw models list` / 模型选择的同样方式来排查。 +- 如果 CLI 可用,live 测试通常也应找到相同的 keys。 +- 如果 live 测试提示“没有凭证”,就按照你调试 `openclaw models list` / 模型选择时的方式去排查。 -- 按智能体划分的认证 profiles:`~/.openclaw/agents//agent/auth-profiles.json`(这就是实时测试中 “profile keys” 的含义) +- 每个智能体的认证 profile:`~/.openclaw/agents//agent/auth-profiles.json`(这就是 live 测试中 “profile keys” 的含义) - 配置:`~/.openclaw/openclaw.json`(或 `OPENCLAW_CONFIG_PATH`) -- 旧版状态目录:`~/.openclaw/credentials/`(存在时会复制到暂存的实时 home 中,但它不是主 profile-key 存储) -- 本地实时运行默认会将活动配置、按智能体划分的 `auth-profiles.json` 文件、旧版 `credentials/` 以及受支持的外部 CLI 认证目录复制到临时测试 home 中;暂存的实时 home 会跳过 `workspace/` 和 `sandboxes/`,并移除 `agents.*.workspace` / `agentDir` 路径覆盖,以便探针不会落到你真实的主机工作区上。 +- 旧版状态目录:`~/.openclaw/credentials/`(如果存在,会复制到 staged live home 中,但它不是主 profile-key store) +- 默认情况下,live 本地运行会将当前活动配置、每个智能体的 `auth-profiles.json` 文件、旧版 `credentials/` 以及受支持的外部 CLI 认证目录复制到一个临时测试 home 中;staged live homes 会跳过 `workspace/` 和 `sandboxes/`,并移除 `agents.*.workspace` / `agentDir` 路径覆盖,这样 probes 就不会落到你真实主机的工作区中。 -如果你想依赖环境变量密钥(例如在你的 `~/.profile` 中导出),请在运行本地测试前先执行 `source ~/.profile`,或者使用下面的 Docker 运行器(它们可以将 `~/.profile` 挂载到容器中)。 +如果你想依赖环境变量 keys(例如在 `~/.profile` 中导出的那些),请在本地测试前运行 `source ~/.profile`,或者使用下面的 Docker 运行器(它们可以把 `~/.profile` 挂载进容器)。 -## Deepgram 实时测试(音频转写) +## Deepgram live(音频转写) - 测试:`extensions/deepgram/audio.live.test.ts` - 启用:`DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live extensions/deepgram/audio.live.test.ts` -## BytePlus 编码计划实时测试 +## BytePlus coding plan live - 测试:`extensions/byteplus/live.test.ts` - 启用:`BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live extensions/byteplus/live.test.ts` - 可选模型覆盖:`BYTEPLUS_CODING_MODEL=ark-code-latest` -## ComfyUI 工作流媒体实时测试 +## ComfyUI workflow media live - 测试:`extensions/comfy/comfy.live.test.ts` - 启用:`OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test:live -- extensions/comfy/comfy.live.test.ts` - 范围: - - 演练内置 comfy 图像、视频和 `music_generate` 路径 - - 除非配置了 `models.providers.comfy.`,否则会跳过各项能力 - - 在修改 comfy 工作流提交、轮询、下载或插件注册后非常有用 + - 覆盖内置 comfy 的图像、视频和 `music_generate` 路径 + - 若未配置 `models.providers.comfy.`,则会跳过对应能力 + - 在修改 comfy workflow 提交、轮询、下载或插件注册后很有用 -## 图像生成实时测试 +## 图像生成 live - 测试:`test/image-generation.runtime.live.test.ts` - 命令:`pnpm test:live test/image-generation.runtime.live.test.ts` -- 测试框架:`pnpm test:live:media image` +- Harness:`pnpm test:live:media image` - 范围: - 枚举每个已注册的图像生成提供商插件 - - 在探测前从你的登录 shell(`~/.profile`)加载缺失的提供商环境变量 - - 默认优先使用实时/env API 密钥,而不是已存储的认证 profiles,这样 `auth-profiles.json` 中陈旧的测试密钥就不会掩盖真实 shell 凭证 - - 跳过没有可用认证/profile/模型的提供商 + - 在探测前,从你的登录 shell(`~/.profile`)加载缺失的提供商环境变量 + - 默认优先使用 live/env API keys,而不是已存储的 auth profiles,因此 `auth-profiles.json` 中陈旧的测试 keys 不会掩盖真实的 shell 凭证 + - 跳过没有可用认证/profile/model 的提供商 - 通过共享运行时能力运行标准图像生成变体: - `google:flash-generate` - `google:pro-generate` @@ -792,80 +831,80 @@ Docker 说明: - `openai` - `vydra` - `xai` -- 可选收窄: +- 可选收窄方式: - `OPENCLAW_LIVE_IMAGE_GENERATION_PROVIDERS="openai,google,xai"` - `OPENCLAW_LIVE_IMAGE_GENERATION_MODELS="openai/gpt-image-2,google/gemini-3.1-flash-image-preview,xai/grok-imagine-image"` - `OPENCLAW_LIVE_IMAGE_GENERATION_CASES="google:flash-generate,google:pro-edit,xai:default-generate,xai:default-edit"` - 可选认证行为: - - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 可强制使用 profile 存储认证,并忽略仅 env 的覆盖 + - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`:强制使用 profile-store 认证并忽略仅环境变量的覆盖 -## 音乐生成实时测试 +## 音乐生成 live - 测试:`extensions/music-generation-providers.live.test.ts` - 启用:`OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts` -- 测试框架:`pnpm test:live:media music` +- Harness:`pnpm test:live:media music` - 范围: - - 演练共享的内置音乐生成提供商路径 + - 覆盖共享的内置音乐生成提供商路径 - 当前覆盖 Google 和 MiniMax - - 在探测前从你的登录 shell(`~/.profile`)加载提供商环境变量 - - 默认优先使用实时/env API 密钥,而不是已存储的认证 profiles,这样 `auth-profiles.json` 中陈旧的测试密钥就不会掩盖真实 shell 凭证 - - 跳过没有可用认证/profile/模型的提供商 - - 在可用时运行两种已声明的运行时模式: - - 使用仅提示词输入的 `generate` + - 在探测前,从你的登录 shell(`~/.profile`)加载提供商环境变量 + - 默认优先使用 live/env API keys,而不是已存储的 auth profiles,因此 `auth-profiles.json` 中陈旧的测试 keys 不会掩盖真实的 shell 凭证 + - 跳过没有可用认证/profile/model 的提供商 + - 在可用时运行两个已声明的运行时模式: + - 使用纯 prompt 输入的 `generate` - 当提供商声明 `capabilities.edit.enabled` 时运行 `edit` - 当前共享通道覆盖: - `google`:`generate`、`edit` - `minimax`:`generate` - - `comfy`:使用单独的 Comfy 实时测试文件,不在此共享扫描中 -- 可选收窄: + - `comfy`:使用单独的 Comfy live 文件,不在这个共享扫描中 +- 可选收窄方式: - `OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS="google,minimax"` - `OPENCLAW_LIVE_MUSIC_GENERATION_MODELS="google/lyria-3-clip-preview,minimax/music-2.5+"` - 可选认证行为: - - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 可强制使用 profile 存储认证,并忽略仅 env 的覆盖 + - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`:强制使用 profile-store 认证并忽略仅环境变量的覆盖 -## 视频生成实时测试 +## 视频生成 live - 测试:`extensions/video-generation-providers.live.test.ts` - 启用:`OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts` -- 测试框架:`pnpm test:live:media video` +- Harness:`pnpm test:live:media video` - 范围: - - 演练共享的内置视频生成提供商路径 - - 默认使用发布安全的冒烟测试路径:非 FAL 提供商、每个提供商一个 text-to-video 请求、一秒钟的龙虾提示词,以及来自 `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` 的每提供商操作上限(默认 `180000`) + - 覆盖共享的内置视频生成提供商路径 + - 默认使用对发布安全的冒烟路径:非 FAL 提供商、每个提供商一个 text-to-video 请求、一个一秒钟的龙虾 prompt,以及来自 `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` 的每提供商操作上限(默认 `180000`) - 默认跳过 FAL,因为提供商侧队列延迟可能主导发布时间;传入 `--video-providers fal` 或 `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"` 可显式运行它 - - 在探测前从你的登录 shell(`~/.profile`)加载提供商环境变量 - - 默认优先使用实时/env API 密钥,而不是已存储的认证 profiles,这样 `auth-profiles.json` 中陈旧的测试密钥就不会掩盖真实 shell 凭证 - - 跳过没有可用认证/profile/模型的提供商 - - 默认仅运行 `generate` - - 设置 `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1` 后,还会在可用时运行已声明的转换模式: - - 当提供商声明 `capabilities.imageToVideo.enabled`,且所选提供商/模型在共享扫描中接受基于 buffer 的本地图像输入时,运行 `imageToVideo` - - 当提供商声明 `capabilities.videoToVideo.enabled`,且所选提供商/模型在共享扫描中接受基于 buffer 的本地视频输入时,运行 `videoToVideo` - - 当前在共享扫描中已声明但跳过的 `imageToVideo` 提供商: + - 在探测前,从你的登录 shell(`~/.profile`)加载提供商环境变量 + - 默认优先使用 live/env API keys,而不是已存储的 auth profiles,因此 `auth-profiles.json` 中陈旧的测试 keys 不会掩盖真实的 shell 凭证 + - 跳过没有可用认证/profile/model 的提供商 + - 默认只运行 `generate` + - 设置 `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1`,可在可用时额外运行已声明的转换模式: + - 当提供商声明 `capabilities.imageToVideo.enabled` 且所选提供商/模型在共享扫描中接受基于 buffer 的本地图像输入时,运行 `imageToVideo` + - 当提供商声明 `capabilities.videoToVideo.enabled` 且所选提供商/模型在共享扫描中接受基于 buffer 的本地视频输入时,运行 `videoToVideo` + - 当前在共享扫描中已声明但被跳过的 `imageToVideo` 提供商: - `vydra`,因为内置的 `veo3` 仅支持文本,而内置的 `kling` 需要远程图像 URL - 提供商特定的 Vydra 覆盖: - `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_VYDRA_VIDEO=1 pnpm test:live -- extensions/vydra/vydra.live.test.ts` - - 该文件会运行 `veo3` text-to-video,以及一个默认使用远程图像 URL 夹具的 `kling` 通道 - - 当前 `videoToVideo` 实时覆盖: - - 仅 `runway`,当所选模型为 `runway/gen4_aleph` 时 - - 当前在共享扫描中已声明但跳过的 `videoToVideo` 提供商: - - `alibaba`、`qwen`、`xai`,因为这些路径当前需要远程 `http(s)` / MP4 参考 URL - - `google`,因为当前共享 Gemini/Veo 通道使用的是基于本地 buffer 的输入,而该路径在共享扫描中不被接受 - - `openai`,因为当前共享通道缺少对特定组织的视频修补/混剪访问保证 -- 可选收窄: + - 该文件会运行 `veo3` text-to-video,以及一个默认使用远程图像 URL fixture 的 `kling` 通道 + - 当前 `videoToVideo` live 覆盖: + - 仅 `runway`,且所选模型为 `runway/gen4_aleph` 时 + - 当前在共享扫描中已声明但被跳过的 `videoToVideo` 提供商: + - `alibaba`、`qwen`、`xai`,因为这些路径目前要求远程 `http(s)` / MP4 参考 URL + - `google`,因为当前共享 Gemini/Veo 通道使用的是本地 buffer 支持输入,而该路径在共享扫描中不被接受 + - `openai`,因为当前共享通道缺少针对特定组织的视频 inpaint/remix 访问保证 +- 可选收窄方式: - `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="google,openai,runway"` - `OPENCLAW_LIVE_VIDEO_GENERATION_MODELS="google/veo-3.1-fast-generate-preview,openai/sora-2,runway/gen4_aleph"` - - `OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS=""` 可将每个提供商都纳入默认扫描,包括 FAL - - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000` 可在激进的冒烟测试运行中降低每个提供商的操作上限 + - `OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS=""`:在默认扫描中包含所有提供商,包括 FAL + - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000`:将每个提供商的操作上限降低,用于激进的冒烟运行 - 可选认证行为: - - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 可强制使用 profile 存储认证,并忽略仅 env 的覆盖 + - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`:强制使用 profile-store 认证并忽略仅环境变量的覆盖 -## 媒体实时测试框架 +## 媒体 live harness - 命令:`pnpm test:live:media` - 用途: - - 通过一个仓库原生命令入口运行共享的图像、音乐和视频实时测试套件 + - 通过一个仓库原生入口点运行共享的图像、音乐和视频 live 测试套件 - 自动从 `~/.profile` 加载缺失的提供商环境变量 - - 默认自动将每个套件收窄到当前具有可用认证的提供商 - - 复用 `scripts/test-live.mjs`,因此心跳和静默模式行为保持一致 + - 默认自动将每个测试套件收窄到当前具备可用认证的提供商 + - 复用 `scripts/test-live.mjs`,因此 heartbeat 和安静模式行为保持一致 - 示例: - `pnpm test:live:media` - `pnpm test:live:media image video --providers openai,google,minimax` @@ -876,211 +915,210 @@ 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 扫描保持可行: +- live-model 运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只会在仓库 Docker 镜像内运行与之匹配的 profile-key live 文件(`src/agents/models.profiles.live.test.ts` 和 `src/gateway/gateway-models.profiles.live.test.ts`),并挂载你的本地配置目录和工作区(如果挂载了 `~/.profile`,还会先读取它)。相应的本地入口点是 `test:live:models-profiles` 和 `test:live:gateway-profiles`。 +- Docker live 运行器默认使用较小的冒烟上限,以便完整 Docker 扫描仍然可行: `test:docker:live-models` 默认设置 `OPENCLAW_LIVE_MAX_MODELS=12`,并且 `test:docker:live-gateway` 默认设置 `OPENCLAW_LIVE_GATEWAY_SMOKE=1`、 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`、 - `OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000`,以及 + `OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000` 以及 `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。当你 - 明确想要更大、更穷尽的扫描时,可覆盖这些环境变量。 -- `test:docker:all` 会先通过 `test:docker:live-build` 构建一次实时 Docker 镜像,然后将其复用于两个实时 Docker 通道。它还会通过 `test:docker:e2e-build` 构建一个共享的 `scripts/e2e/Dockerfile` 镜像,并将其复用于演练已构建应用的 E2E 容器冒烟测试运行器。 -- 容器冒烟测试运行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:gateway-network`、`test:docker:mcp-channels`、`test:docker:pi-bundle-mcp-tools`、`test:docker:cron-mcp-cleanup`、`test:docker:plugins`、`test:docker:plugin-update` 和 `test:docker:config-reload` 会启动一个或多个真实容器,并验证更高层级的集成路径。 + 明确想要更大范围的穷尽式扫描时,可覆盖这些环境变量。 +- `test:docker:all` 会先通过 `test:docker:live-build` 构建一次 live Docker 镜像,然后在两个 live Docker 通道中复用它。它还会通过 `test:docker:e2e-build` 构建一个共享的 `scripts/e2e/Dockerfile` 镜像,并在执行已构建 app 的 E2E 容器冒烟运行器中复用它。 +- 容器冒烟运行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:gateway-network`、`test:docker:mcp-channels`、`test:docker:pi-bundle-mcp-tools`、`test:docker:cron-mcp-cleanup`、`test:docker:plugins`、`test:docker:plugin-update` 和 `test:docker:config-reload` 会启动一个或多个真实容器,并验证更高层级的集成路径。 -实时模型 Docker 运行器还会仅绑定挂载所需的 CLI 认证 home(如果运行范围未收窄,则挂载所有受支持的认证 home),然后在运行前将它们复制到容器 home 中,以便外部 CLI OAuth 可以刷新令牌,而不会修改主机认证存储: +live-model Docker 运行器还会只 bind-mount 所需的 CLI 认证 home(如果运行未收窄,则挂载所有受支持的目录),然后在运行前将它们复制到容器 home 中,这样外部 CLI OAuth 就能刷新 token,而不会修改主机上的认证存储: -- 直连模型:`pnpm test:docker:live-models`(脚本:`scripts/test-live-models-docker.sh`) -- ACP 绑定冒烟测试:`pnpm test:docker:live-acp-bind`(脚本:`scripts/test-live-acp-bind-docker.sh`) -- CLI 后端冒烟测试:`pnpm test:docker:live-cli-backend`(脚本:`scripts/test-live-cli-backend-docker.sh`) -- Codex app-server 测试框架冒烟测试:`pnpm test:docker:live-codex-harness`(脚本:`scripts/test-live-codex-harness-docker.sh`) +- Direct models:`pnpm test:docker:live-models`(脚本:`scripts/test-live-models-docker.sh`) +- ACP 绑定冒烟:`pnpm test:docker:live-acp-bind`(脚本:`scripts/test-live-acp-bind-docker.sh`) +- CLI 后端冒烟:`pnpm test:docker:live-cli-backend`(脚本:`scripts/test-live-cli-backend-docker.sh`) +- Codex app-server harness 冒烟:`pnpm test:docker:live-codex-harness`(脚本:`scripts/test-live-codex-harness-docker.sh`) - Gateway 网关 + dev 智能体:`pnpm test:docker:live-gateway`(脚本:`scripts/test-live-gateway-models-docker.sh`) -- Open WebUI 实时冒烟测试:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`) +- Open WebUI live 冒烟:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`) - 新手引导向导(TTY,完整脚手架):`pnpm test:docker:onboard`(脚本:`scripts/e2e/onboard-docker.sh`) -- Npm tarball 新手引导/渠道/智能体冒烟测试:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装已打包的 OpenClaw tarball,通过 env-ref 新手引导配置 OpenAI,并默认配置 Telegram,验证启用插件会按需安装其运行时依赖,运行 doctor,并运行一次模拟的 OpenAI 智能体回合。可通过 `OPENCLAW_NPM_ONBOARD_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,通过 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机构建,或通过 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换渠道。 +- Npm tarball 新手引导/channel/智能体冒烟:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装打包好的 OpenClaw tarball,通过 env-ref 新手引导配置 OpenAI,并默认配置 Telegram,验证启用插件时会按需安装其运行时依赖,运行 doctor,并执行一次 mocked OpenAI 智能体轮次。可通过 `OPENCLAW_NPM_ONBOARD_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,通过 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机构建,或通过 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换 channel。 - Gateway 网关网络(两个容器,WS 认证 + 健康检查):`pnpm test:docker:gateway-network`(脚本:`scripts/e2e/gateway-network-docker.sh`) -- OpenAI Responses `web_search` 最小推理回归:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)会通过 Gateway 网关运行一个模拟的 OpenAI 服务器,验证 `web_search` 会将 `reasoning.effort` 从 `minimal` 提升为 `low`,然后强制提供商 schema 拒绝,并检查原始细节是否出现在 Gateway 网关日志中。 -- MCP 渠道桥接(已播种 Gateway 网关 + stdio bridge + 原始 Claude 通知帧冒烟测试):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`) -- Pi 内置 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 网关 + 在隔离的 cron 和一次性 subagent 运行后清理 stdio MCP 子进程):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`) -- 插件(安装冒烟测试 + `/plugin` 别名 + Claude 内置包重启语义):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-docker.sh`) -- 插件更新未变化冒烟测试:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-docker.sh`) -- 配置热重载元数据冒烟测试:`pnpm test:docker:config-reload`(脚本:`scripts/e2e/config-reload-source-docker.sh`) -- 内置插件运行时依赖:`pnpm test:docker:bundled-channel-deps` 默认会构建一个小型 Docker 运行器镜像,在主机上构建并打包一次 OpenClaw,然后将该 tarball 挂载到每个 Linux 安装场景中。可通过 `OPENCLAW_SKIP_DOCKER_BUILD=1` 复用镜像,在本地刚完成构建后通过 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 跳过主机构建,或通过 `OPENCLAW_BUNDLED_CHANNEL_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向现有 tarball。 -- 在迭代时可通过禁用无关场景来收窄内置插件运行时依赖测试,例如: +- OpenAI Responses `web_search` 最小推理回归:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)会通过 Gateway 网关运行一个 mocked OpenAI 服务器,验证 `web_search` 会将 `reasoning.effort` 从 `minimal` 提升为 `low`,然后强制让提供商 schema 拒绝,并检查原始细节是否出现在 Gateway 网关日志中。 +- MCP 渠道桥接(已播种的 Gateway 网关 + stdio bridge + 原始 Claude notification-frame 冒烟):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`) +- Pi 内置 MCP 工具(真实 stdio MCP 服务器 + embedded 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`) +- 插件(安装冒烟 + `/plugin` 别名 + Claude-bundle 重启语义):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-docker.sh`) +- 插件更新未变更冒烟:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-docker.sh`) +- 配置重载元数据冒烟:`pnpm test:docker:config-reload`(脚本:`scripts/e2e/config-reload-source-docker.sh`) +- 内置插件运行时依赖:`pnpm test:docker:bundled-channel-deps` 默认会构建一个小型 Docker 运行器镜像,在主机上构建并打包一次 OpenClaw,然后将该 tarball 挂载到每个 Linux 安装场景中。可通过 `OPENCLAW_SKIP_DOCKER_BUILD=1` 复用镜像,通过 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 在完成一次新的本地构建后跳过主机构建,或通过 `OPENCLAW_BUNDLED_CHANNEL_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向现有 tarball。 +- 在迭代时,可通过禁用无关场景来收窄内置插件运行时依赖测试,例如: `OPENCLAW_BUNDLED_CHANNEL_SCENARIOS=0 OPENCLAW_BUNDLED_CHANNEL_UPDATE_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_ROOT_OWNED_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_SETUP_ENTRY_SCENARIO=0 pnpm test:docker:bundled-channel-deps`。 -若要手动预构建并复用共享的已构建应用镜像: +如需手动预构建并复用共享的 built-app 镜像: ```bash OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e:local pnpm test:docker:e2e-build OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels ``` -设置特定套件的镜像覆盖(例如 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`)后,仍然会优先生效。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果该镜像尚未在本地存在,这些脚本会先拉取它。QR 和安装器 Docker 测试仍保留各自的 Dockerfile,因为它们验证的是打包/安装行为,而不是共享的已构建应用运行时。 +设置 suite 特定镜像覆盖(例如 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`)时,它们仍然具有更高优先级。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果该镜像尚未存在于本地,脚本会先拉取它。QR 和安装器 Docker 测试保留各自独立的 Dockerfile,因为它们验证的是包/安装行为,而不是共享的 built-app 运行时。 -实时模型 Docker 运行器还会以只读方式绑定挂载当前检出内容,并 -将其暂存到容器内的临时工作目录中。这样可以保持运行时 -镜像轻量,同时仍让 Vitest 针对你精确的本地源代码/配置运行。 -暂存步骤会跳过大型本地专用缓存和应用构建输出,例如 -`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及应用本地 `.build` 或 -Gradle 输出目录,因此 Docker 实时运行不会花费数分钟复制 -与机器相关的工件。 -它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,以便 Gateway 网关实时探针不会在 -容器中启动真实的 Telegram/Discord 等渠道工作进程。 -`test:docker:live-models` 仍然运行 `pnpm test:live`,因此当你需要收窄或排除该 Docker 通道中的 Gateway 网关实时覆盖时, -也请同时传入 -`OPENCLAW_LIVE_GATEWAY_*`。 +live-model Docker 运行器还会以只读方式 bind-mount 当前 checkout, +并将其暂存到容器内的临时 workdir 中。这样可以保持运行时 +镜像精简,同时仍能针对你本地精确的源代码/配置运行 Vitest。 +暂存步骤会跳过大型仅本地缓存和 app 构建输出,例如 +`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及 app 本地的 `.build` 或 +Gradle 输出目录,因此 Docker live 运行不会花费数分钟复制 +机器特定的产物。 +它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,以便 gateway live probes 不会在 +容器内启动真实的 Telegram/Discord 等 channel workers。 +`test:docker:live-models` 仍然运行 `pnpm test:live`,因此当你需要 +收窄或排除该 Docker 通道中的 gateway +live 覆盖时,也请一并传入 `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 可能需要完成自身的冷启动设置。 -该通道需要一个可用的实时模型密钥,并且在 Docker 化运行中, -`OPENCLAW_PROFILE_FILE` -(默认是 `~/.profile`)是提供该密钥的主要方式。 -成功运行会打印一个小型 JSON 负载,例如 `{ "ok": true, "model": +启用了 OpenAI 兼容 HTTP endpoints 的 OpenClaw gateway 容器, +再针对该 gateway 启动一个固定版本的 Open WebUI 容器,通过 +Open WebUI 完成登录,验证 `/api/models` 暴露 `openclaw/default`,然后通过 +Open WebUI 的 `/api/chat/completions` 代理发送一次真实的 +聊天请求。 +第一次运行可能会明显更慢,因为 Docker 可能需要拉取 +Open WebUI 镜像,而 Open WebUI 也可能需要完成它自己的冷启动设置。 +这个通道需要一个可用的 live 模型 key,而 `OPENCLAW_PROFILE_FILE` +(默认是 `~/.profile`)是在 Docker 化运行中提供它的主要方式。 +成功的运行会打印一个小型 JSON payload,例如 `{ "ok": true, "model": "openclaw/default", ... }`。 -`test:docker:mcp-channels` 被刻意设计为确定性的,不需要 -真实的 Telegram、Discord 或 iMessage 账户。它会启动一个已播种的 Gateway 网关 -容器,启动第二个容器来运行 `openclaw mcp serve`,然后 -通过真实的 stdio MCP bridge 验证路由后的会话发现、转录读取、附件元数据、 -实时事件队列行为、出站发送路由,以及 Claude 风格的渠道 + -权限通知。通知检查会直接检查原始 stdio MCP 帧, -因此该冒烟测试验证的是 bridge 实际发出的内容, -而不只是某个特定客户端 SDK 恰好暴露出的内容。 -`test:docker:pi-bundle-mcp-tools` 是确定性的,不需要实时 -模型密钥。它会构建仓库 Docker 镜像,在容器中启动一个真实的 stdio MCP 探测服务器, -通过嵌入式 Pi 内置 MCP 运行时实例化该服务器, -执行该工具,然后验证 `coding` 和 `messaging` 会保留 +`test:docker:mcp-channels` 是刻意设计为确定性的,不需要真实的 +Telegram、Discord 或 iMessage 账号。它会启动一个已播种的 Gateway +容器,再启动第二个容器来运行 `openclaw mcp serve`,然后 +验证路由后的会话发现、transcript 读取、附件元数据、 +实时事件队列行为、出站发送路由,以及通过真实 stdio MCP bridge 传输的 Claude 风格 channel + +权限通知。通知检查会直接检查原始 stdio MCP frames, +因此这个冒烟测试验证的是 bridge 实际发出的内容, +而不仅仅是某个特定 client SDK 恰好暴露出的内容。 +`test:docker:pi-bundle-mcp-tools` 是确定性的,不需要 live +模型 key。它会构建仓库 Docker 镜像,在容器中启动一个真实的 stdio MCP probe 服务器, +通过 embedded Pi bundle +MCP 运行时将该服务器实例化,执行工具,然后验证 `coding` 和 `messaging` 会保留 `bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会将其过滤掉。 -`test:docker:cron-mcp-cleanup` 是确定性的,不需要实时模型 -密钥。它会启动一个带真实 stdio MCP 探测服务器的已播种 Gateway 网关,运行一次隔离的 -cron 回合和一次 `/subagents spawn` 的一次性子智能体回合,然后验证 +`test:docker:cron-mcp-cleanup` 是确定性的,不需要 live 模型 +key。它会启动一个带有真实 stdio MCP probe 服务器的已播种 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 安装 -- 位于 `$HOME` 下的外部 CLI 认证目录/文件会以只读方式挂载到 `/host-auth...` 下,然后在测试开始前复制到 `/home/node/...` +- `OPENCLAW_CONFIG_DIR=...`(默认:`~/.openclaw`)挂载到 `/home/node/.openclaw` +- `OPENCLAW_WORKSPACE_DIR=...`(默认:`~/.openclaw/workspace`)挂载到 `/home/node/.openclaw/workspace` +- `OPENCLAW_PROFILE_FILE=...`(默认:`~/.profile`)挂载到 `/home/node/.profile`,并在运行测试前读取 +- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1`:仅验证从 `OPENCLAW_PROFILE_FILE` 读取的环境变量,使用临时配置/工作区目录,且不挂载外部 CLI 认证目录 +- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(默认:`~/.cache/openclaw/docker-cli-tools`)挂载到 `/home/node/.npm-global`,用于缓存 Docker 内部的 CLI 安装 +- `$HOME` 下的外部 CLI 认证目录/文件会以只读方式挂载到 `/host-auth...` 下,然后在测试开始前复制到 `/home/node/...` - 默认目录:`.minimax` - 默认文件:`~/.codex/auth.json`、`~/.codex/config.toml`、`.claude.json`、`~/.claude/.credentials.json`、`~/.claude/settings.json`、`~/.claude/settings.local.json` - - 范围已收窄的提供商运行只会挂载从 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录/文件 - - 可通过 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none` 或逗号列表手动覆盖,例如 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` -- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` 用于收窄运行范围 -- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` 用于在容器内筛选提供商 -- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于复用现有的 `openclaw:local-live` 镜像,以便在不需要重新构建时重跑 -- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用于确保凭证来自 profile 存储(而不是 env) -- `OPENCLAW_OPENWEBUI_MODEL=...` 用于选择 Gateway 网关为 Open WebUI 冒烟测试暴露的模型 -- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试使用的 nonce 检查提示词 -- `OPENWEBUI_IMAGE=...` 用于覆盖固定的 Open WebUI 镜像标签 + - 收窄后的提供商运行只会挂载根据 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的必需目录/文件 + - 可通过 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none`,或类似 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 的逗号列表手动覆盖 +- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...`:收窄运行范围 +- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...`:在容器内过滤提供商 +- `OPENCLAW_SKIP_DOCKER_BUILD=1`:复用现有的 `openclaw:local-live` 镜像,用于那些不需要重新构建的重跑 +- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`:确保凭证来自 profile store(而不是环境变量) +- `OPENCLAW_OPENWEBUI_MODEL=...`:为 Open WebUI 冒烟测试选择 gateway 暴露的模型 +- `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 安全) -这些是在没有真实提供商情况下的“真实流水线”回归测试: +这些是在不依赖真实提供商的情况下进行的“真实链路”回归测试: -- Gateway 网关工具调用(模拟 OpenAI,真实 Gateway 网关 + 智能体循环):`src/gateway/gateway.test.ts`(用例:“runs a mock OpenAI tool call end-to-end via gateway agent loop”) +- Gateway 网关工具调用(mock OpenAI,真实 gateway + 智能体循环):`src/gateway/gateway.test.ts`(用例:“runs a mock OpenAI tool call end-to-end via gateway agent loop”) - Gateway 网关向导(WS `wizard.start`/`wizard.next`,强制写入配置 + 认证):`src/gateway/gateway.test.ts`(用例:“runs wizard over ws and writes auth token config”) ## 智能体可靠性评估(Skills) -我们已经有一些对 CI 安全的测试,行为上类似“智能体可靠性评估”: +我们已经有一些对 CI 安全、行为类似“智能体可靠性评估”的测试: -- 通过真实 Gateway 网关 + 智能体循环进行模拟工具调用(`src/gateway/gateway.test.ts`)。 +- 通过真实 gateway + 智能体循环进行 mock 工具调用(`src/gateway/gateway.test.ts`)。 - 验证会话接线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。 -对于 Skills(见 [Skills](/zh-CN/tools/skills)),目前仍缺少: +对于 Skills(参见 [Skills](/zh-CN/tools/skills)),当前仍然缺少的部分: -- **决策:** 当 prompt 中列出 Skills 时,智能体是否会选择正确的 Skill(或避开无关 Skill)? -- **合规:** 智能体在使用前是否会读取 `SKILL.md`,并遵循所需步骤/参数? -- **工作流契约:** 断言工具顺序、会话历史延续和沙箱边界的多轮场景。 +- **决策能力:** 当提示词中列出 Skills 时,智能体是否会选择正确的 skill(或避开无关的 skill)? +- **合规性:** 智能体是否会在使用前读取 `SKILL.md`,并遵循必需的步骤/参数? +- **工作流契约:** 用于断言工具顺序、会话历史继承和沙箱边界的多轮场景。 未来的评估应优先保持确定性: -- 一个使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、Skill 文件读取和会话接线。 -- 一小组面向 Skill 的场景(使用 vs 避免、门控、prompt 注入)。 -- 只有在 CI 安全套件就位之后,才添加可选的实时评估(按需启用、由 env 控制)。 +- 一个使用 mock 提供商的场景运行器,用于断言工具调用 + 顺序、skill 文件读取以及会话接线。 +- 一小组面向 skill 的场景(使用 vs 避免、门控、提示注入)。 +- 只有在对 CI 安全的测试套件到位之后,才考虑可选的 live 评估(按需启用、由环境变量控制)。 -## 契约测试(插件和渠道形态) +## 契约测试(plugin 和 channel 形状) -契约测试用于验证每个已注册的插件和渠道都符合其 -接口契约。它们会遍历所有已发现的插件,并运行一组形态和行为断言。默认的 `pnpm test` 单元通道会刻意 -跳过这些共享接缝和冒烟测试文件;当你修改共享渠道或提供商表面时, +契约测试用于验证每个已注册的 plugin 和 channel 都符合其 +接口契约。它们会遍历所有发现到的插件,并运行一组形状与行为断言。默认的 `pnpm test` unit 通道会刻意 +跳过这些共享接缝和冒烟文件;当你修改共享 channel 或 provider 接口时, 请显式运行契约命令。 ### 命令 - 所有契约:`pnpm test:contracts` -- 仅渠道契约:`pnpm test:contracts:channels` -- 仅提供商契约:`pnpm test:contracts:plugins` +- 仅 channel 契约:`pnpm test:contracts:channels` +- 仅 provider 契约:`pnpm test:contracts:plugins` -### 渠道契约 +### Channel 契约 位于 `src/channels/plugins/contracts/*.contract.test.ts`: -- **plugin** - 基本插件形态(id、name、capabilities) +- **plugin** - 基本插件形状(id、name、capabilities) - **setup** - 设置向导契约 - **session-binding** - 会话绑定行为 -- **outbound-payload** - 消息负载结构 +- **outbound-payload** - 消息 payload 结构 - **inbound** - 入站消息处理 -- **actions** - 渠道操作处理器 +- **actions** - channel 操作处理器 - **threading** - 线程 ID 处理 -- **directory** - 目录/成员表 API -- **group-policy** - 群组策略执行 +- **directory** - 目录/成员列表 API +- **group-policy** - 群组策略强制执行 -### 提供商状态契约 +### Provider 状态契约 位于 `src/plugins/contracts/*.contract.test.ts`。 -- **status** - 渠道状态探测 -- **registry** - 插件注册表形态 +- **status** - channel 状态探测 +- **registry** - 插件注册表形状 -### 提供商契约 +### Provider 契约 位于 `src/plugins/contracts/*.contract.test.ts`: - **auth** - 认证流程契约 -- **auth-choice** - 认证选项/选择 +- **auth-choice** - 认证选择/选择逻辑 - **catalog** - 模型目录 API - **discovery** - 插件发现 - **loader** - 插件加载 - **runtime** - 提供商运行时 -- **shape** - 插件形态/接口 +- **shape** - 插件形状/接口 - **wizard** - 设置向导 ### 何时运行 -- 修改插件 SDK 导出或子路径后 -- 添加或修改渠道或提供商插件后 -- 重构插件注册或发现逻辑后 +- 修改 plugin-sdk 导出或子路径之后 +- 添加或修改 channel 或 provider 插件之后 +- 重构插件注册或发现逻辑之后 -契约测试会在 CI 中运行,并且不需要真实 API 密钥。 +契约测试会在 CI 中运行,不需要真实 API keys。 ## 添加回归测试(指南) -当你修复了在实时测试中发现的提供商/模型问题时: +当你修复了一个在 live 中发现的 provider/model 问题时: -- 如果可能,添加一个对 CI 安全的回归测试(模拟/存根提供商,或捕获精确的请求形态转换) -- 如果它本质上只能在实时环境中复现(速率限制、认证策略),则保持实时测试范围窄,并通过环境变量按需启用 -- 优先锁定能捕获该缺陷的最小层级: - - 提供商请求转换/回放缺陷 → 直连模型测试 - - Gateway 网关会话/历史/工具流水线缺陷 → Gateway 网关实时冒烟测试或对 CI 安全的 Gateway 网关模拟测试 -- SecretRef 遍历保护措施: - - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言遍历段 exec id 会被拒绝。 - - 如果你在 `src/secrets/target-registry-data.ts` 中添加了新的 `includeInPlan` SecretRef 目标族,请更新该测试中的 `classifyTargetClass`。该测试会在遇到未分类目标 id 时故意失败,从而避免静默跳过新类别。 +- 如果可能,添加一个对 CI 安全的回归测试(mock/stub provider,或精确捕获请求形状转换) +- 如果它本质上只能在 live 中复现(限流、认证策略),就让 live 测试保持收窄,并通过环境变量按需启用 +- 优先定位到能捕捉该 bug 的最小层级: + - provider 请求转换/重放 bug → direct models 测试 + - gateway 会话/历史/工具链路 bug → gateway live 冒烟测试,或对 CI 安全的 gateway mock 测试 +- SecretRef 遍历防护栏: + - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言基于遍历段的 exec id 会被拒绝。 + - 如果你在 `src/secrets/target-registry-data.ts` 中添加了一个新的 `includeInPlan` SecretRef 目标族,请更新该测试中的 `classifyTargetClass`。该测试会在遇到未分类目标 id 时故意失败,这样新类别就无法被悄悄跳过。 diff --git a/docs/zh-CN/plugins/manifest.md b/docs/zh-CN/plugins/manifest.md index e0347ba4e..4fcaa6b6b 100644 --- a/docs/zh-CN/plugins/manifest.md +++ b/docs/zh-CN/plugins/manifest.md @@ -5,61 +5,61 @@ read_when: summary: 插件清单 + JSON schema 要求(严格配置校验) title: 插件清单 x-i18n: - generated_at: "2026-04-23T06:24:03Z" + generated_at: "2026-04-23T07:42:11Z" model: gpt-5.4 provider: openai - source_hash: de71b9d556c2696d3279f202b66d57aa8014e9c89d81e3f453602744120d1675 + source_hash: d48810f604aa0c3ff8553528cfa4cb735d1d5e7a15b1bbca6152070d6c8f9cce source_path: plugins/manifest.md workflow: 15 --- # 插件清单(`openclaw.plugin.json`) -本页仅适用于 **原生 OpenClaw 插件清单**。 +本页仅介绍 **原生 OpenClaw 插件清单**。 -关于兼容的 bundle 布局,请参阅 [插件 bundles](/zh-CN/plugins/bundles)。 +有关兼容的 bundle 布局,请参阅 [Plugin bundles](/zh-CN/plugins/bundles)。 兼容的 bundle 格式使用不同的清单文件: - Codex bundle:`.codex-plugin/plugin.json` -- Claude bundle:`.claude-plugin/plugin.json`,或不使用清单的默认 Claude 组件布局 +- Claude bundle:`.claude-plugin/plugin.json`,或不带清单文件的默认 Claude 组件布局 - Cursor bundle:`.cursor-plugin/plugin.json` -OpenClaw 也会自动检测这些 bundle 布局,但不会依据这里描述的 `openclaw.plugin.json` schema 对它们进行校验。 +OpenClaw 也会自动检测这些 bundle 布局,但不会按照这里介绍的 `openclaw.plugin.json` schema 对它们进行校验。 -对于兼容的 bundles,当其布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据,以及声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值,以及受支持的 hook packs。 +对于兼容 bundle,当其布局符合 OpenClaw 运行时预期时,OpenClaw 目前会读取 bundle 元数据,以及声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值,以及受支持的 hook pack。 -每个原生 OpenClaw 插件 **必须** 在 **插件根目录** 中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用这个清单在 **不执行插件代码** 的情况下校验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。 +每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码的情况下**校验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。 -请参阅完整的插件系统指南:[插件](/zh-CN/tools/plugin)。 -关于原生能力模型和当前的外部兼容性指南,请参阅: -[能力模型](/zh-CN/plugins/architecture#public-capability-model)。 +查看完整的插件系统指南:[Plugins](/zh-CN/tools/plugin)。 +有关原生能力模型和当前外部兼容性指导,请参阅: +[Capability model](/zh-CN/plugins/architecture#public-capability-model)。 -## 这个文件的作用 +## 此文件的作用 `openclaw.plugin.json` 是 OpenClaw 在加载你的插件代码之前读取的元数据。 -用于: +可将其用于: - 插件标识 - 配置校验 -- 无需启动插件运行时即可获得的认证和新手引导元数据 -- 运行时加载前,控制平面界面可检查的低成本激活提示 -- 运行时加载前,设置 / 新手引导界面可检查的低成本设置描述符 -- 运行时加载前应解析的别名和自动启用元数据 -- 运行时加载前应自动激活插件的简写模型族归属元数据 +- 无需启动插件运行时即可获取的认证和新手引导元数据 +- 控制平面界面可在运行时加载前检查的轻量激活提示 +- 设置/新手引导界面可在运行时加载前检查的轻量设置描述符 +- 应在插件运行时加载前解析的别名和自动启用元数据 +- 应在插件运行时加载前自动激活插件的简写模型家族归属元数据 - 用于内置兼容接线和契约覆盖的静态能力归属快照 -- 共享 `openclaw qa` 主机在插件运行时加载前可检查的低成本 QA 运行器元数据 -- 无需加载运行时即可合并到目录和校验界面的渠道特定配置元数据 +- 共享 `openclaw qa` 主机可在插件运行时加载前检查的轻量 QA 运行器元数据 +- 可在不加载运行时的情况下合并到目录和校验界面的渠道专用配置元数据 - 配置 UI 提示 -不要用于: +不要将其用于: - 注册运行时行为 - 声明代码入口点 - npm 安装元数据 -这些应放在你的插件代码和 `package.json` 中。 +这些内容属于你的插件代码和 `package.json`。 ## 最小示例 @@ -108,19 +108,19 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会依据这里描述的 "provider": "openrouter", "method": "api-key", "choiceId": "openrouter-api-key", - "choiceLabel": "OpenRouter API key", + "choiceLabel": "OpenRouter API 密钥", "groupId": "openrouter", "groupLabel": "OpenRouter", "optionKey": "openrouterApiKey", "cliFlag": "--openrouter-api-key", "cliOption": "--openrouter-api-key ", - "cliDescription": "OpenRouter API key", + "cliDescription": "OpenRouter API 密钥", "onboardingScopes": ["text-inference"] } ], "uiHints": { "apiKey": { - "label": "API key", + "label": "API 密钥", "placeholder": "sk-or-v1-...", "sensitive": true } @@ -143,61 +143,61 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会依据这里描述的 | ------------------------------------ | -------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | 是 | `string` | 规范的插件 id。这是在 `plugins.entries.` 中使用的 id。 | | `configSchema` | 是 | `object` | 此插件配置的内联 JSON Schema。 | -| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略该字段,或将其设置为任何非 `true` 的值,以保持插件默认禁用。 | +| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或设置为任何非 `true` 的值,则插件默认保持禁用。 | | `legacyPluginIds` | 否 | `string[]` | 会规范化为此规范插件 id 的旧版 id。 | -| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些 provider id 时,应自动启用此插件。 | -| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的互斥插件类型。 | +| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提及这些 provider id 时,应自动启用此插件。 | +| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明由 `plugins.slots.*` 使用的排他性插件类型。 | | `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于设备发现和配置校验。 | | `providers` | 否 | `string[]` | 由此插件拥有的 provider id。 | -| `modelSupport` | 否 | `object` | 由清单拥有的简写模型族元数据,用于在运行时之前自动加载插件。 | -| `providerEndpoints` | 否 | `object[]` | 由清单拥有的 endpoint host/baseUrl 元数据,用于核心系统必须在 provider 运行时加载前分类的 provider 路由。 | +| `modelSupport` | 否 | `object` | 由清单拥有的简写模型家族元数据,用于在运行时之前自动加载插件。 | +| `providerEndpoints` | 否 | `object[]` | 由清单拥有的端点 host/baseUrl 元数据,用于核心在 provider 运行时加载前对 provider 路由进行分类。 | | `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 | -| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用;在运行时加载前的冷启动模型发现期间,应探测其由插件拥有的 synthetic auth hook。 | -| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API key 值,用于表示非机密的本地、OAuth 或环境凭证状态。 | -| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称;在运行时加载前,应产出带有插件感知能力的配置和 CLI 诊断信息。 | -| `providerAuthEnvVars` | 否 | `Record` | OpenClaw 无需加载插件代码即可检查的低成本 provider 认证环境变量元数据。 | -| `providerAuthAliases` | 否 | `Record` | 应复用另一个 provider id 进行认证查找的 provider id,例如共享基础 provider API key 和认证配置文件的编码 provider。 | -| `channelEnvVars` | 否 | `Record` | OpenClaw 无需加载插件代码即可检查的低成本渠道环境变量元数据。将其用于通用启动 / 配置辅助工具应能看到的、由环境变量驱动的渠道设置或认证界面。 | -| `providerAuthChoices` | 否 | `object[]` | 用于新手引导选择器、首选 provider 解析和简单 CLI 标志接线的低成本认证选项元数据。 | -| `activation` | 否 | `object` | 用于 provider、命令、渠道、路由和能力触发加载的低成本激活提示。仅为元数据;插件运行时仍然拥有实际行为。 | -| `setup` | 否 | `object` | 设备发现和设置界面无需加载插件运行时即可检查的低成本设置 / 新手引导描述符。 | -| `qaRunners` | 否 | `object[]` | 共享 `openclaw qa` 主机在插件运行时加载前使用的低成本 QA 运行器描述符。 | -| `contracts` | 否 | `object` | 外部认证 hooks、语音、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属的静态内置能力快照。 | -| `mediaUnderstandingProviderMetadata` | 否 | `Record` | 为 `contracts.mediaUnderstandingProviders` 中声明的 provider id 提供的低成本媒体理解默认值。 | -| `channelConfigs` | 否 | `Record` | 由清单拥有的渠道配置元数据,会在运行时加载前合并到设备发现和校验界面中。 | +| `syntheticAuthRefs` | 否 | `string[]` | 在运行时加载前的冷启动模型发现期间,应探测其由插件拥有的合成认证 hook 的 provider 或 CLI 后端引用。 | +| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API 密钥值,用于表示非机密的本地、OAuth 或环境凭据状态。 | +| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称,应在运行时加载前生成带有插件感知能力的配置和 CLI 诊断信息。 | +| `providerAuthEnvVars` | 否 | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量 provider 认证环境变量元数据。 | +| `providerAuthAliases` | 否 | `Record` | 应复用另一个 provider id 进行认证查找的 provider id,例如共享基础 provider API 密钥和认证配置文件的编码 provider。 | +| `channelEnvVars` | 否 | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量渠道环境变量元数据。将其用于由环境变量驱动的渠道设置或认证界面,以便通用启动/配置辅助工具能够识别。 | +| `providerAuthChoices` | 否 | `object[]` | 用于新手引导选择器、首选 provider 解析和简单 CLI 标志接线的轻量认证选项元数据。 | +| `activation` | 否 | `object` | 面向 provider、命令、渠道、路由和能力触发加载的轻量激活提示。仅是元数据;实际行为仍由插件运行时负责。 | +| `setup` | 否 | `object` | 设备发现和设置界面可在不加载插件运行时的情况下检查的轻量设置/新手引导描述符。 | +| `qaRunners` | 否 | `object[]` | 共享 `openclaw qa` 主机在插件运行时加载前使用的轻量 QA 运行器描述符。 | +| `contracts` | 否 | `object` | 面向外部认证 hook、speech、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、web-fetch、Web 搜索和工具归属的静态内置能力快照。 | +| `mediaUnderstandingProviderMetadata` | 否 | `Record` | 为 `contracts.mediaUnderstandingProviders` 中声明的 provider id 提供的轻量媒体理解默认值。 | +| `channelConfigs` | 否 | `Record` | 由清单拥有的渠道配置元数据,在运行时加载前合并到设备发现和校验界面中。 | | `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 | | `name` | 否 | `string` | 人类可读的插件名称。 | -| `description` | 否 | `string` | 在插件界面中显示的简短摘要。 | +| `description` | 否 | `string` | 显示在插件界面中的简短摘要。 | | `version` | 否 | `string` | 仅供参考的插件版本。 | | `uiHints` | 否 | `Record` | 配置字段的 UI 标签、占位符和敏感性提示。 | ## `providerAuthChoices` 参考 每个 `providerAuthChoices` 条目描述一个新手引导或认证选项。 -OpenClaw 会在 provider 运行时加载前读取它。 +OpenClaw 会在 provider 运行时加载前读取这些内容。 | 字段 | 必填 | 类型 | 含义 | | --------------------- | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `provider` | 是 | `string` | 此选项所属的 provider id。 | | `method` | 是 | `string` | 要分发到的认证方法 id。 | -| `choiceId` | 是 | `string` | 新手引导和 CLI 流程使用的稳定认证选项 id。 | -| `choiceLabel` | 否 | `string` | 面向用户的标签。如果省略,OpenClaw 会回退到 `choiceId`。 | +| `choiceId` | 是 | `string` | 由新手引导和 CLI 流程使用的稳定认证选项 id。 | +| `choiceLabel` | 否 | `string` | 面向用户的标签。如省略,OpenClaw 会回退到 `choiceId`。 | | `choiceHint` | 否 | `string` | 选择器的简短辅助文本。 | -| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,值越小排序越靠前。 | -| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏该选项,但仍允许手动通过 CLI 选择。 | +| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,值越小越靠前。 | +| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏此选项,但仍允许通过手动 CLI 进行选择。 | | `deprecatedChoiceIds` | 否 | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 | -| `groupId` | 否 | `string` | 用于对相关选项分组的可选组 id。 | -| `groupLabel` | 否 | `string` | 该分组的面向用户标签。 | +| `groupId` | 否 | `string` | 用于分组相关选项的可选分组 id。 | +| `groupLabel` | 否 | `string` | 该分组面向用户的标签。 | | `groupHint` | 否 | `string` | 该分组的简短辅助文本。 | | `optionKey` | 否 | `string` | 用于简单单标志认证流程的内部选项键。 | -| `cliFlag` | 否 | `string` | CLI 标志名,例如 `--openrouter-api-key`。 | +| `cliFlag` | 否 | `string` | CLI 标志名称,例如 `--openrouter-api-key`。 | | `cliOption` | 否 | `string` | 完整的 CLI 选项形式,例如 `--openrouter-api-key `。 | -| `cliDescription` | 否 | `string` | 在 CLI 帮助中使用的描述。 | -| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如果省略,默认值为 `["text-inference"]`。 | +| `cliDescription` | 否 | `string` | CLI 帮助中使用的说明。 | +| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如省略,默认值为 `["text-inference"]`。 | ## `commandAliases` 参考 -当插件拥有一个运行时命令名称,而用户可能误将其放入 `plugins.allow` 或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用这些元数据提供诊断信息,而无需导入插件运行时代码。 +当某个插件拥有一个运行时命令名称,而用户可能会误将其放入 `plugins.allow`,或尝试将其作为根级 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用此元数据进行诊断,而无需导入插件运行时代码。 ```json { @@ -214,16 +214,16 @@ OpenClaw 会在 provider 运行时加载前读取它。 | 字段 | 必填 | 类型 | 含义 | | ------------ | -------- | ----------------- | ----------------------------------------------------------------------- | | `name` | 是 | `string` | 属于此插件的命令名称。 | -| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根 CLI 命令。 | -| `cliCommand` | 否 | `string` | 用于 CLI 操作时建议的相关根 CLI 命令(如果存在)。 | +| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根级 CLI 命令。 | +| `cliCommand` | 否 | `string` | 如果存在,用于建议 CLI 操作的相关根级 CLI 命令。 | ## `activation` 参考 -当插件可以低成本地声明哪些控制平面事件应在后续激活它时,请使用 `activation`。 +当插件能够以低成本声明哪些控制平面事件应在后续激活它时,请使用 `activation`。 ## `qaRunners` 参考 -当插件在共享的 `openclaw qa` 根命令下提供一个或多个传输运行器时,请使用 `qaRunners`。保持这些元数据低成本且静态;插件运行时仍通过导出 `qaRunnerCliRegistrations` 的轻量级 `runtime-api.ts` 界面来拥有实际的 CLI 注册。 +当插件在共享 `openclaw qa` 根命令下贡献一个或多个传输运行器时,请使用 `qaRunners`。保持这些元数据轻量且静态;插件运行时仍通过导出 `qaRunnerCliRegistrations` 的轻量 `runtime-api.ts` 接口负责实际的 CLI 注册。 ```json { @@ -239,9 +239,10 @@ OpenClaw 会在 provider 运行时加载前读取它。 | 字段 | 必填 | 类型 | 含义 | | ------------- | -------- | -------- | ------------------------------------------------------------------ | | `commandName` | 是 | `string` | 挂载在 `openclaw qa` 下的子命令,例如 `matrix`。 | -| `description` | 否 | `string` | 当共享主机需要一个存根命令时使用的回退帮助文本。 | +| `description` | 否 | `string` | 当共享主机需要一个占位命令时使用的回退帮助文本。 | -此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。当前使用方将其作为在更广泛的插件加载之前进行缩小范围的提示,因此缺少激活元数据通常只会带来性能损耗;在旧版清单归属回退仍存在时,它不应改变正确性。 +此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时/插件入口点。 +当前使用方将其作为更广泛插件加载前的缩小范围提示,因此缺少激活元数据通常只会带来性能损耗;在旧版清单归属回退机制仍存在时,它不应改变正确性。 ```json { @@ -261,17 +262,17 @@ OpenClaw 会在 provider 运行时加载前读取它。 | `onCommands` | 否 | `string[]` | 应激活此插件的命令 id。 | | `onChannels` | 否 | `string[]` | 应激活此插件的渠道 id。 | | `onRoutes` | 否 | `string[]` | 应激活此插件的路由类型。 | -| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的广义能力提示。 | +| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的宽泛能力提示。 | -当前在线使用方: +当前的在线使用方: - 由命令触发的 CLI 规划会回退到旧版的 `commandAliases[].cliCommand` 或 `commandAliases[].name` -- 当缺少显式渠道激活元数据时,由渠道触发的设置 / 渠道规划会回退到旧版 `channels[]` 归属 -- 当缺少显式 provider 激活元数据时,由 provider 触发的设置 / 运行时规划会回退到旧版的 `providers[]` 和顶层 `cliBackends[]` 归属 +- 由渠道触发的设置/渠道规划会在缺少显式渠道激活元数据时,回退到旧版 `channels[]` 归属 +- 由 provider 触发的设置/运行时规划会在缺少显式 provider 激活元数据时,回退到旧版的 `providers[]` 和顶层 `cliBackends[]` 归属 ## `setup` 参考 -当设置和新手引导界面需要在运行时加载前获取由插件拥有的低成本元数据时,请使用 `setup`。 +当设置和新手引导界面在运行时加载前需要轻量的插件自有元数据时,请使用 `setup`。 ```json { @@ -290,32 +291,32 @@ OpenClaw 会在 provider 运行时加载前读取它。 } ``` -顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是用于控制平面 / 设置流程的、特定于设置的描述符界面,应保持为仅元数据。 +顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是面向控制平面/设置流程的设置专用描述符界面,应保持为纯元数据。 -存在 `setup.providers` 和 `setup.cliBackends` 时,它们是设置发现过程中优先使用的、描述符优先的查找界面。如果该描述符仅缩小候选插件范围,而设置仍需要更丰富的设置时运行时 hooks,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。 +存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现的首选“描述符优先”查找界面。如果该描述符仅用于缩小候选插件范围,而设置仍需要更丰富的设置期运行时 hook,请将 `requiresRuntime` 设为 `true`,并保留 `setup-api` 作为回退执行路径。 -由于设置查找可能执行由插件拥有的 `setup-api` 代码,规范化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值在已发现插件之间必须保持唯一。归属不明确时会以保守方式失败,而不是按发现顺序选出一个赢家。 +由于设置查找可能会执行插件自有的 `setup-api` 代码,规范化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值必须在所有已发现插件之间保持唯一。若归属不明确,系统会采用失败关闭,而不是按发现顺序选出一个胜者。 ### `setup.providers` 参考 | 字段 | 必填 | 类型 | 含义 | | ------------- | -------- | ---------- | ------------------------------------------------------------------------------------ | | `id` | 是 | `string` | 在设置或新手引导期间公开的 provider id。保持规范化 id 在全局范围内唯一。 | -| `authMethods` | 否 | `string[]` | 此 provider 在无需加载完整运行时的情况下支持的设置 / 认证方法 id。 | -| `envVars` | 否 | `string[]` | 通用设置 / 状态界面可在插件运行时加载前检查的环境变量。 | +| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置/认证方法 id。 | +| `envVars` | 否 | `string[]` | 通用设置/状态界面可在插件运行时加载前检查的环境变量。 | ### `setup` 字段 | 字段 | 必填 | 类型 | 含义 | | ------------------ | -------- | ---------- | --------------------------------------------------------------------------------------------------- | | `providers` | 否 | `object[]` | 在设置和新手引导期间公开的 provider 设置描述符。 | -| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查找的设置时后端 id。保持规范化 id 在全局范围内唯一。 | +| `cliBackends` | 否 | `string[]` | 用于“描述符优先”设置查找的设置期后端 id。保持规范化 id 在全局范围内唯一。 | | `configMigrations` | 否 | `string[]` | 由此插件的设置界面拥有的配置迁移 id。 | -| `requiresRuntime` | 否 | `boolean` | 描述符查找之后,设置是否仍需要执行 `setup-api`。 | +| `requiresRuntime` | 否 | `boolean` | 在描述符查找之后,设置是否仍需要执行 `setup-api`。 | ## `uiHints` 参考 -`uiHints` 是一个从配置字段名到小型渲染提示的映射。 +`uiHints` 是一个从配置字段名映射到小型渲染提示的映射表。 ```json { @@ -337,13 +338,13 @@ OpenClaw 会在 provider 运行时加载前读取它。 | `label` | `string` | 面向用户的字段标签。 | | `help` | `string` | 简短辅助文本。 | | `tags` | `string[]` | 可选的 UI 标签。 | -| `advanced` | `boolean` | 将该字段标记为高级项。 | -| `sensitive` | `boolean` | 将该字段标记为机密或敏感项。 | +| `advanced` | `boolean` | 将该字段标记为高级字段。 | +| `sensitive` | `boolean` | 将该字段标记为机密或敏感。 | | `placeholder` | `string` | 表单输入的占位文本。 | ## `contracts` 参考 -仅当 OpenClaw 无需导入插件运行时即可读取静态能力归属元数据时,才使用 `contracts`。 +仅当 `contracts` 用于 OpenClaw 可在不导入插件运行时的情况下读取的静态能力归属元数据时,才应使用它。 ```json { @@ -369,21 +370,21 @@ OpenClaw 会在 provider 运行时加载前读取它。 | -------------------------------- | ---------- | ----------------------------------------------------------------- | | `embeddedExtensionFactories` | `string[]` | 内置插件可为其注册工厂的嵌入式运行时 id。 | | `externalAuthProviders` | `string[]` | 此插件拥有其外部认证配置文件 hook 的 provider id。 | -| `speechProviders` | `string[]` | 此插件拥有的语音 provider id。 | +| `speechProviders` | `string[]` | 此插件拥有的 speech provider id。 | | `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转录 provider id。 | | `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音 provider id。 | | `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解 provider id。 | | `imageGenerationProviders` | `string[]` | 此插件拥有的图像生成 provider id。 | | `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成 provider id。 | -| `webFetchProviders` | `string[]` | 此插件拥有的网页抓取 provider id。 | -| `webSearchProviders` | `string[]` | 此插件拥有的网页搜索 provider id。 | -| `tools` | `string[]` | 此插件为内置契约检查所拥有的智能体工具名称。 | +| `webFetchProviders` | `string[]` | 此插件拥有的 Web-fetch provider id。 | +| `webSearchProviders` | `string[]` | 此插件拥有的 Web 搜索 provider id。 | +| `tools` | `string[]` | 此插件拥有、用于内置契约检查的智能体工具名称。 | -实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未作此声明的插件仍会通过已弃用的兼容性回退路径运行,但该回退更慢,并将在迁移窗口结束后移除。 +实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明该项的插件仍会通过已弃用的兼容性回退路径运行,但该回退路径更慢,并将在迁移窗口结束后移除。 ## `mediaUnderstandingProviderMetadata` 参考 -当某个媒体理解 provider 具有默认模型、自动认证回退优先级,或通用核心辅助工具在运行时加载前所需的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。其中的键也必须在 `contracts.mediaUnderstandingProviders` 中声明。 +当某个媒体理解 provider 具有默认模型、自动认证回退优先级,或通用核心辅助工具在运行时加载前所需的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。其键也必须在 `contracts.mediaUnderstandingProviders` 中声明。 ```json { @@ -412,12 +413,12 @@ OpenClaw 会在 provider 运行时加载前读取它。 | ---------------------- | ----------------------------------- | ---------------------------------------------------------------------------- | | `capabilities` | `("image" \| "audio" \| "video")[]` | 此 provider 提供的媒体能力。 | | `defaultModels` | `Record` | 当配置未指定模型时使用的“能力到模型”默认值。 | -| `autoPriority` | `Record` | 用于基于凭证的自动 provider 回退时,数值越小排序越靠前。 | -| `nativeDocumentInputs` | `"pdf"[]` | provider 支持的原生文档输入。 | +| `autoPriority` | `Record` | 用于基于凭据的自动 provider 回退时,数字越小越靠前。 | +| `nativeDocumentInputs` | `"pdf"[]` | 此 provider 支持的原生文档输入。 | ## `channelConfigs` 参考 -当某个渠道插件在运行时加载前需要低成本配置元数据时,请使用 `channelConfigs`。 +当某个渠道插件在运行时加载前需要轻量配置元数据时,请使用 `channelConfigs`。 ```json { @@ -448,15 +449,15 @@ OpenClaw 会在 provider 运行时加载前读取它。 | 字段 | 类型 | 含义 | | ------------- | ------------------------ | ----------------------------------------------------------------------------------------- | -| `schema` | `object` | `channels.` 的 JSON Schema。对每个已声明的渠道配置条目来说是必填项。 | -| `uiHints` | `Record` | 该渠道配置部分可选的 UI 标签 / 占位符 / 敏感性提示。 | +| `schema` | `object` | `channels.` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 | +| `uiHints` | `Record` | 该渠道配置部分的可选 UI 标签/占位符/敏感性提示。 | | `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 | | `description` | `string` | 用于检查和目录界面的简短渠道描述。 | | `preferOver` | `string[]` | 在选择界面中,此渠道应优先于的旧版或较低优先级插件 id。 | ## `modelSupport` 参考 -当 OpenClaw 应在插件运行时加载前,根据简写模型 id(如 `gpt-5.4` 或 `claude-sonnet-4.6`)推断你的 provider 插件时,请使用 `modelSupport`。 +当 OpenClaw 应在插件运行时加载前,根据 `gpt-5.4` 或 `claude-sonnet-4.6` 之类的简写模型 id 推断你的 provider 插件时,请使用 `modelSupport`。 ```json { @@ -469,67 +470,68 @@ OpenClaw 会在 provider 运行时加载前读取它。 OpenClaw 应用以下优先级: -- 显式 `provider/model` 引用使用所属的 `providers` 清单元数据 +- 显式 `provider/model` 引用使用其所属 `providers` 清单元数据 - `modelPatterns` 优先于 `modelPrefixes` -- 如果一个非内置插件和一个内置插件都匹配,则非内置插件胜出 -- 剩余的歧义会被忽略,直到用户或配置指定 provider +- 如果一个非内置插件和一个内置插件同时匹配,则非内置插件胜出 +- 剩余歧义会被忽略,直到用户或配置显式指定 provider 字段: | 字段 | 类型 | 含义 | | --------------- | ---------- | ------------------------------------------------------------------------------- | -| `modelPrefixes` | `string[]` | 对简写模型 id 使用 `startsWith` 匹配的前缀。 | -| `modelPatterns` | `string[]` | 在移除 profile 后缀后,对简写模型 id 进行匹配的正则表达式源码。 | +| `modelPrefixes` | `string[]` | 使用 `startsWith` 针对简写模型 id 进行匹配的前缀。 | +| `modelPatterns` | `string[]` | 在移除配置文件后缀之后,针对简写模型 id 进行匹配的正则表达式源码。 | -旧版顶层能力键已弃用。使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载不再将这些顶层字段视为能力归属。 +旧版顶层能力键已弃用。请使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载不再将这些顶层字段视为能力归属声明。 -## 清单与 package.json 的区别 +## 清单与 `package.json` 的区别 -这两个文件承担不同的职责: +这两个文件承担不同职责: | 文件 | 用途 | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `openclaw.plugin.json` | 设备发现、配置校验、认证选项元数据,以及必须在插件代码运行前存在的 UI 提示 | | `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 块 | -如果你不确定某段元数据应放在哪里,请使用这条规则: +如果你不确定某段元数据应该放在哪里,请遵循以下规则: -- 如果 OpenClaw 必须在加载插件代码前知道它,就把它放在 `openclaw.plugin.json` -- 如果它与打包、入口文件或 npm 安装行为有关,就把它放在 `package.json` +- 如果 OpenClaw 必须在加载插件代码前知道它,就将它放在 `openclaw.plugin.json` +- 如果它与打包、入口文件或 npm 安装行为有关,就将它放在 `package.json` -### 影响设备发现的 `package.json` 字段 +### 会影响设备发现的 `package.json` 字段 -某些运行时前的插件元数据有意放在 `package.json` 的 `openclaw` 块下,而不是 `openclaw.plugin.json` 中。 +某些运行时前插件元数据有意放在 `package.json` 的 `openclaw` 块下,而不是 `openclaw.plugin.json` 中。 重要示例: | 字段 | 含义 | | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `openclaw.extensions` | 声明原生插件入口点。必须保持在插件包目录内。 | -| `openclaw.runtimeExtensions` | 声明已安装包的构建后 JavaScript 运行时入口点。必须保持在插件包目录内。 | -| `openclaw.setupEntry` | 仅用于设置的轻量级入口点,在新手引导、延迟渠道启动以及只读渠道状态 / SecretRef 发现期间使用。必须保持在插件包目录内。 | -| `openclaw.runtimeSetupEntry` | 声明已安装包的构建后 JavaScript 设置入口点。必须保持在插件包目录内。 | -| `openclaw.channel` | 低成本渠道目录元数据,例如标签、文档路径、别名和选择文案。 | -| `openclaw.channel.configuredState` | 轻量级已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已存在仅环境变量驱动的设置?”。 | -| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已有任何账号登录?”。 | -| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 内置插件和外部发布插件的安装 / 更新提示。 | -| `openclaw.install.defaultChoice` | 当存在多个安装来源时的首选安装路径。 | -| `openclaw.install.minHostVersion` | 最低支持的 OpenClaw 主机版本,使用如 `>=2026.3.22` 这样的 semver 下限。 | -| `openclaw.install.expectedIntegrity` | 期望的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验拉取的制品。 | -| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一个范围很窄的内置插件重新安装恢复路径。 | -| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置用途的渠道界面,再加载完整渠道插件。 | +| `openclaw.runtimeExtensions` | 为已安装包声明构建后的 JavaScript 运行时入口点。必须保持在插件包目录内。 | +| `openclaw.setupEntry` | 在新手引导、延迟渠道启动和只读渠道状态/SecretRef 发现期间使用的轻量仅设置入口点。必须保持在插件包目录内。 | +| `openclaw.runtimeSetupEntry` | 为已安装包声明构建后的 JavaScript 设置入口点。必须保持在插件包目录内。 | +| `openclaw.channel` | 轻量的渠道目录元数据,例如标签、文档路径、别名和选择文案。 | +| `openclaw.channel.configuredState` | 轻量的已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已存在仅环境变量设置?”。 | +| `openclaw.channel.persistedAuthState` | 轻量的持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经有任何登录状态?”。 | +| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 面向内置插件和外部发布插件的安装/更新提示。 | +| `openclaw.install.defaultChoice` | 当有多个安装来源可用时的首选安装路径。 | +| `openclaw.install.minHostVersion` | 支持的最低 OpenClaw 主机版本,使用类似 `>=2026.3.22` 的 semver 下限。 | +| `openclaw.install.expectedIntegrity` | 预期的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验获取到的制品。 | +| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一个受限的内置插件重装恢复路径。 | +| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置的渠道界面,再加载完整渠道插件。 | -清单元数据决定了哪些 provider / 渠道 / 设置选项会在运行时加载前出现在新手引导中。`package.json#openclaw.install` 则告诉新手引导:当用户选择这些选项之一时,应如何获取或启用该插件。不要把安装提示移到 `openclaw.plugin.json` 中。 +清单元数据决定了在运行时加载前,新手引导中会出现哪些 provider/渠道/设置选项。`package.json#openclaw.install` 则告诉新手引导,当用户选择其中某个选项时,应如何获取或启用该插件。不要将安装提示移到 `openclaw.plugin.json` 中。 -`openclaw.install.minHostVersion` 会在安装期间和清单注册表加载期间强制执行。无效值会被拒绝;值如果有效但要求更新版本,则在较旧主机上会跳过该插件。 +`openclaw.install.minHostVersion` 会在安装期间和清单注册表加载期间强制执行。无效值会被拒绝;合法但更新的值会让旧主机跳过该插件。 -精确的 npm 版本固定已通过 `npmSpec` 提供,例如 `"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。如果你希望在拉取到的 npm 制品不再匹配已固定版本时,让更新流程以保守方式失败,请将其与 `expectedIntegrity` 搭配使用。交互式新手引导只有在 `npmSpec` 是精确版本且存在 `expectedIntegrity` 时,才会从受信任的目录元数据中提供 npm 安装选项;否则会回退到本地来源或跳过。 +精确的 npm 版本固定已经存在于 `npmSpec` 中,例如 +`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。当你希望如果获取到的 npm 制品不再匹配固定版本时,让更新流程以失败关闭方式终止,请将其与 `expectedIntegrity` 搭配使用。交互式新手引导会提供受信任注册表的 npm spec,包括裸包名和 dist-tag。存在 `expectedIntegrity` 时,安装/更新流程会强制校验它;省略时,会记录注册表解析结果,但不带完整性固定。 -当状态、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账号时,渠道插件应提供 `openclaw.setupEntry`。该设置入口点应暴露渠道元数据,以及适用于设置场景的安全配置、状态和 secrets 适配器;网络客户端、Gateway 网关监听器和传输协议运行时应保留在主扩展入口点中。 +当状态、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`。设置入口点应公开渠道元数据,以及适用于设置阶段的安全配置、状态和 secrets 适配器;网络客户端、Gateway 网关监听器和传输运行时应保留在主扩展入口点中。 运行时入口点字段不会覆盖源码入口点字段的包边界检查。例如,`openclaw.runtimeExtensions` 不能让一个越界的 `openclaw.extensions` 路径变得可加载。 -`openclaw.install.allowInvalidConfigRecovery` 的作用范围被有意限制得很窄。它不会让任意损坏的配置变得可安装。当前它仅允许安装流程从特定的陈旧内置插件升级失败中恢复,例如缺失的内置插件路径,或该同一内置插件的陈旧 `channels.` 条目。无关的配置错误仍会阻止安装,并将操作人员引导到 `openclaw doctor --fix`。 +`openclaw.install.allowInvalidConfigRecovery` 的设计范围是刻意受限的。它不会让任意损坏配置都变得可安装。当前它只允许安装流程从某些特定的过时内置插件升级失败中恢复,例如缺失的内置插件路径,或该同一内置插件对应的过时 `channels.` 条目。无关的配置错误仍会阻止安装,并将操作人员引导至 `openclaw doctor --fix`。 `openclaw.channel.persistedAuthState` 是一个微型检查器模块的包元数据: @@ -547,9 +549,9 @@ OpenClaw 应用以下优先级: } ``` -当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前执行低成本的“是 / 否”认证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 转发它。 +当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前进行一个轻量的“是/否”认证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 转发它。 -`openclaw.channel.configuredState` 对低成本、仅环境变量的已配置检查采用相同结构: +`openclaw.channel.configuredState` 对轻量的仅环境变量已配置检查使用相同结构: ```json { @@ -565,54 +567,55 @@ OpenClaw 应用以下优先级: } ``` -当某个渠道可以从环境变量或其他微小的非运行时输入中回答已配置状态时,请使用它。如果检查需要完整配置解析或真实的渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` hook 中。 +当某个渠道能够通过环境变量或其他轻量级非运行时输入回答已配置状态时,请使用它。如果该检查需要完整配置解析或真实渠道运行时,请改为将该逻辑保留在插件 `config.hasConfiguredState` hook 中。 ## 设备发现优先级(重复插件 id) -OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区、配置中显式选择的路径)。如果两个发现结果共享同一个 `id`,则只保留 **优先级最高** 的清单;较低优先级的重复项会被丢弃,而不是与其并行加载。 +OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区、配置中显式选择的路径)。如果两次发现共享同一个 `id`,则只保留**优先级最高**的清单;较低优先级的重复项会被丢弃,而不是与其并行加载。 优先级从高到低如下: -1. **配置选定** —— 在 `plugins.entries.` 中显式固定的路径 -2. **内置** —— 随 OpenClaw 一同发布的插件 +1. **配置选择** —— 在 `plugins.entries.` 中显式固定的路径 +2. **内置** —— 随 OpenClaw 一起发布的插件 3. **全局安装** —— 安装到全局 OpenClaw 插件根目录中的插件 4. **工作区** —— 相对于当前工作区发现的插件 影响: -- 工作区中某个内置插件的 fork 或陈旧副本不会遮蔽内置构建版本。 -- 若要真正用本地插件覆盖内置插件,请通过 `plugins.entries.` 固定它,使其凭借优先级胜出,而不要依赖工作区发现。 +- 位于工作区中的某个内置插件分叉版本或过时副本,不会遮蔽内置构建。 +- 如果你确实要用本地插件覆盖内置插件,请通过 `plugins.entries.` 固定它,以便它凭借优先级获胜,而不是依赖工作区发现。 - 被丢弃的重复项会被记录日志,以便 Doctor 和启动诊断能够指向被舍弃的副本。 ## JSON Schema 要求 - **每个插件都必须提供一个 JSON Schema**,即使它不接受任何配置。 -- 可以接受空 schema(例如 `{ "type": "object", "additionalProperties": false }`)。 -- schema 会在配置读取 / 写入时校验,而不是在运行时校验。 +- 空 schema 也是可以接受的(例如 `{ "type": "object", "additionalProperties": false }`)。 +- Schema 会在配置读取/写入时校验,而不是在运行时校验。 ## 校验行为 -- 未知的 `channels.*` 键是 **错误**,除非该渠道 id 由某个插件清单声明。 -- `plugins.entries.`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*` 必须引用 **可发现** 的插件 id。未知 id 属于 **错误**。 -- 如果某个插件已安装,但其清单或 schema 损坏或缺失,校验会失败,且 Doctor 会报告该插件错误。 -- 如果插件配置存在,但插件 **已禁用**,则会保留该配置,并在 Doctor + 日志中显示 **警告**。 +- 未知的 `channels.*` 键会被视为**错误**,除非该渠道 id 已由插件清单声明。 +- `plugins.entries.`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*` 必须引用**可发现的**插件 id。未知 id 会被视为**错误**。 +- 如果某个插件已安装,但其清单或 schema 损坏或缺失,则校验会失败,Doctor 会报告该插件错误。 +- 如果插件配置存在,但插件处于**禁用**状态,则配置会被保留,并在 Doctor + 日志中显示**警告**。 -完整的 `plugins.*` schema 请参阅 [配置参考](/zh-CN/gateway/configuration)。 +完整的 `plugins.*` schema,请参阅[配置参考](/zh-CN/gateway/configuration)。 ## 说明 -- 对于原生 OpenClaw 插件,清单是 **必需的**,包括本地文件系统加载的插件。 +- **原生 OpenClaw 插件必须提供清单**,包括本地文件系统加载的插件。 - 运行时仍会单独加载插件模块;清单仅用于设备发现 + 校验。 -- 原生清单使用 JSON5 解析,因此允许注释、尾随逗号和未加引号的键,只要最终值仍然是一个对象即可。 -- 清单加载器只会读取文档中列出的清单字段。避免在这里添加自定义顶层键。 -- `providerAuthEnvVars` 是用于认证探测、环境变量标记校验以及类似 provider 认证界面的低成本元数据路径;这些场景不应只是为了检查环境变量名称而启动插件运行时。 -- `providerAuthAliases` 允许 provider 变体复用另一个 provider 的认证环境变量、认证配置文件、基于配置的认证以及 API key 新手引导选项,而无需在核心中硬编码这种关系。 -- `providerEndpoints` 允许 provider 插件拥有简单 endpoint host/baseUrl 匹配元数据。仅将其用于核心已支持的 endpoint 类别;插件仍然拥有运行时行为。 -- `syntheticAuthRefs` 是用于 provider 拥有的 synthetic auth hooks 的低成本元数据路径;这些 hooks 必须在运行时注册表存在之前就对冷启动模型发现可见。只列出其运行时 provider 或 CLI 后端实际实现了 `resolveSyntheticAuth` 的引用。 -- `nonSecretAuthMarkers` 是用于内置插件拥有的占位 API key 的低成本元数据路径,例如本地、OAuth 或环境凭证标记。核心系统会将这些值视为非机密,用于认证显示和 secret 审计,而无需硬编码所属 provider。 -- `channelEnvVars` 是 shell 环境变量回退、设置提示和类似渠道界面的低成本元数据路径;这些场景不应只是为了检查环境变量名称而启动插件运行时。环境变量名称只是元数据,本身并不触发激活:状态、审计、cron 投递校验和其他只读界面在将某个环境变量视为已配置渠道之前,仍会应用插件信任和有效激活策略。 -- `providerAuthChoices` 是用于认证选项选择器、`--auth-choice` 解析、首选 provider 映射和简单新手引导 CLI 标志注册的低成本元数据路径,会在 provider 运行时加载前生效。关于需要 provider 代码的运行时向导元数据,请参阅 [Provider 运行时 hooks](/zh-CN/plugins/architecture#provider-runtime-hooks)。 -- 互斥插件类型通过 `plugins.slots.*` 进行选择。 +- 原生清单使用 JSON5 解析,因此只要最终值仍然是一个对象,就接受注释、尾随逗号和未加引号的键。 +- 清单加载器只会读取文档中说明的清单字段。避免在这里添加自定义顶层键。 +- `providerAuthEnvVars` 是认证探测、环境变量标记校验以及类似 provider 认证界面的轻量元数据路径,这些场景不应仅为检查环境变量名称就启动插件运行时。 +- `providerAuthAliases` 允许 provider 变体复用另一个 provider 的认证环境变量、认证配置文件、基于配置的认证和 API 密钥新手引导选项,而无需在核心中硬编码这种关系。 +- `providerEndpoints` 允许 provider 插件拥有简单的端点 host/baseUrl 匹配元数据。仅将其用于核心已支持的端点类别;运行时行为仍由插件负责。 +- `syntheticAuthRefs` 是 provider 自有合成认证 hook 的轻量元数据路径,这些 hook 必须在运行时注册表存在之前就对冷启动模型发现可见。只列出其运行时 provider 或 CLI 后端实际实现了 `resolveSyntheticAuth` 的引用。 +- `nonSecretAuthMarkers` 是内置插件自有占位 API 密钥(例如本地、OAuth 或环境凭据标记)的轻量元数据路径。核心会将这些值视为非机密,以用于认证展示和 secret 审计,而无需硬编码其所属 provider。 +- `channelEnvVars` 是 shell 环境变量回退、设置提示和类似渠道界面的轻量元数据路径,这些场景不应仅为检查环境变量名称就启动插件运行时。环境变量名称只是元数据,本身并不会触发激活:状态、审计、cron 投递校验和其他只读界面在将某个环境变量视为已配置渠道之前,仍会应用插件信任和生效激活策略。 +- `providerAuthChoices` 是认证选项选择器、`--auth-choice` 解析、首选 provider 映射,以及 provider 运行时加载前简单新手引导 CLI 标志注册的轻量元数据路径。对于需要 provider 代码的运行时向导元数据,请参阅 + [Provider runtime hooks](/zh-CN/plugins/architecture#provider-runtime-hooks)。 +- 排他性插件类型通过 `plugins.slots.*` 选择。 - `kind: "memory"` 由 `plugins.slots.memory` 选择。 - `kind: "context-engine"` 由 `plugins.slots.contextEngine` 选择(默认:内置 `legacy`)。 - 当插件不需要时,可以省略 `channels`、`providers`、`cliBackends` 和 `skills`。 @@ -621,6 +624,6 @@ OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区 ## 相关内容 -- [构建插件](/zh-CN/plugins/building-plugins) —— 插件入门指南 -- [插件架构](/zh-CN/plugins/architecture) —— 内部架构 -- [SDK 概览](/zh-CN/plugins/sdk-overview) —— 插件 SDK 参考 +- [Building Plugins](/zh-CN/plugins/building-plugins) — 插件入门 +- [Plugin Architecture](/zh-CN/plugins/architecture) — 内部架构 +- [SDK Overview](/zh-CN/plugins/sdk-overview) — 插件 SDK 参考 diff --git a/docs/zh-CN/plugins/sdk-setup.md b/docs/zh-CN/plugins/sdk-setup.md index c77e36a4a..10a6ef41e 100644 --- a/docs/zh-CN/plugins/sdk-setup.md +++ b/docs/zh-CN/plugins/sdk-setup.md @@ -1,26 +1,26 @@ --- read_when: - 你正在为一个插件添加设置向导 - - 你需要了解 `setup-entry.ts` 与 `index.ts` 的区别 - - 你正在定义插件配置 schema 或 `package.json` 中的 OpenClaw 元数据 + - 你需要理解 `setup-entry.ts` 与 `index.ts` 的区别 + - 你正在定义插件配置模式或 `package.json` 中的 OpenClaw 元数据 sidebarTitle: Setup and Config -summary: 设置向导、`setup-entry.ts`、配置 schema,以及 `package.json` 元数据 +summary: 设置向导、`setup-entry.ts`、配置模式,以及 `package.json` 元数据 title: 插件设置和配置 x-i18n: - generated_at: "2026-04-23T05:14:54Z" + generated_at: "2026-04-23T07:42:11Z" model: gpt-5.4 provider: openai - source_hash: ccdafb9a562353a7851fcd47bbc382961a449f5d645362c800f64c60579ce7b2 + source_hash: 110cf9aa1bfaeb286d38963cfba2006502e853dd603a126d1c179cbc9b60aea1 source_path: plugins/sdk-setup.md workflow: 15 --- # 插件设置和配置 -关于插件打包(`package.json` 元数据)、清单(`openclaw.plugin.json`)、设置入口和配置 schema 的参考。 +关于插件打包(`package.json` 元数据)、清单(`openclaw.plugin.json`)、设置入口和配置模式的参考。 - **想看操作演练?** 操作指南会结合上下文讲解打包流程: + **想看操作演练?** 操作指南会在具体上下文中介绍打包: [渠道插件](/zh-CN/plugins/sdk-channel-plugins#step-1-package-and-manifest) 和 [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-1-package-and-manifest)。 @@ -42,7 +42,7 @@ x-i18n: "channel": { "id": "my-channel", "label": "My Channel", - "blurb": "渠道的简短描述。" + "blurb": "Short description of the channel." } } } @@ -69,44 +69,46 @@ x-i18n: } ``` -如果你要在 ClawHub 上对外发布插件,则这些 `compat` 和 `build` 字段是必需的。规范的发布片段位于 `docs/snippets/plugin-publish/` 中。 +如果你要在 ClawHub 上对外发布插件,那么这些 `compat` 和 `build` +字段是必需的。规范的发布代码片段位于 +`docs/snippets/plugin-publish/`。 ### `openclaw` 字段 -| 字段 | 类型 | 描述 | -| ------------ | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `extensions` | `string[]` | 入口点文件(相对于包根目录) | -| `setupEntry` | `string` | 仅用于设置的轻量入口(可选) | -| `channel` | `object` | 用于设置、选择器、快速开始和状态界面的渠道目录元数据 | -| `providers` | `string[]` | 由该插件注册的提供商 id | -| `install` | `object` | 安装提示:`npmSpec`、`localPath`、`defaultChoice`、`minHostVersion`、`expectedIntegrity`、`allowInvalidConfigRecovery` | -| `startup` | `object` | 启动行为标志 | +| 字段 | 类型 | 说明 | +| ------------ | ---------- | ---------------------------------------------------------------------------------------- | +| `extensions` | `string[]` | 入口点文件(相对于包根目录) | +| `setupEntry` | `string` | 仅用于设置的轻量级入口(可选) | +| `channel` | `object` | 用于设置、选择器、快速开始和状态界面的渠道目录元数据 | +| `providers` | `string[]` | 由此插件注册的提供商 id | +| `install` | `object` | 安装提示:`npmSpec`、`localPath`、`defaultChoice`、`minHostVersion`、`expectedIntegrity`、`allowInvalidConfigRecovery` | +| `startup` | `object` | 启动行为标志 | ### `openclaw.channel` -`openclaw.channel` 是低成本的包元数据,用于在运行时加载前支持渠道发现和设置界面。 +`openclaw.channel` 是低成本的包元数据,用于在运行时加载之前完成渠道发现和设置界面展示。 -| 字段 | 类型 | 含义 | -| -------------------------------------- | ---------- | ------------------------------------------------- | -| `id` | `string` | 规范的渠道 id。 | -| `label` | `string` | 主要渠道标签。 | -| `selectionLabel` | `string` | 当需要与 `label` 不同时,在选择器 / 设置中显示的标签。 | -| `detailLabel` | `string` | 用于更丰富的渠道目录和状态界面的次级详情标签。 | -| `docsPath` | `string` | 用于设置和选择链接的文档路径。 | -| `docsLabel` | `string` | 当文档链接标签需要与渠道 id 不同时使用的覆盖标签。 | -| `blurb` | `string` | 简短的新手引导 / 目录描述。 | -| `order` | `number` | 在渠道目录中的排序顺序。 | -| `aliases` | `string[]` | 用于渠道选择的额外查找别名。 | -| `preferOver` | `string[]` | 该渠道应优先于的低优先级插件 / 渠道 id。 | -| `systemImage` | `string` | 用于渠道 UI 目录的可选图标 / system-image 名称。 | -| `selectionDocsPrefix` | `string` | 在选择界面中,文档链接前显示的前缀文本。 | -| `selectionDocsOmitLabel` | `boolean` | 在选择文案中直接显示文档路径,而不是带标签的文档链接。 | -| `selectionExtras` | `string[]` | 附加在选择文案中的额外短文本。 | -| `markdownCapable` | `boolean` | 将该渠道标记为支持 Markdown,用于出站格式决策。 | -| `exposure` | `object` | 渠道在设置、已配置列表和文档界面中的可见性控制。 | -| `quickstartAllowFrom` | `boolean` | 让该渠道加入标准快速开始 `allowFrom` 设置流程。 | -| `forceAccountBinding` | `boolean` | 即使只存在一个账户,也要求显式账户绑定。 | -| `preferSessionLookupForAnnounceTarget` | `boolean` | 在为该渠道解析公告目标时,优先使用会话查找。 | +| 字段 | 类型 | 含义 | +| -------------------------------------- | ---------- | ------------------------------------------------------------ | +| `id` | `string` | 规范的渠道 id。 | +| `label` | `string` | 渠道主标签。 | +| `selectionLabel` | `string` | 当需要与 `label` 不同时,在选择器/设置中使用的标签。 | +| `detailLabel` | `string` | 用于更丰富的渠道目录和状态界面的次级详情标签。 | +| `docsPath` | `string` | 用于设置和选择链接的文档路径。 | +| `docsLabel` | `string` | 当文档链接标签需要与渠道 id 不同时使用的覆盖标签。 | +| `blurb` | `string` | 简短的新手引导/目录描述。 | +| `order` | `number` | 在渠道目录中的排序顺序。 | +| `aliases` | `string[]` | 渠道选择时的额外查找别名。 | +| `preferOver` | `string[]` | 此渠道应优先于的低优先级插件/渠道 id。 | +| `systemImage` | `string` | 渠道 UI 目录中可选的图标/system-image 名称。 | +| `selectionDocsPrefix` | `string` | 在选择界面中文档链接前显示的前缀文本。 | +| `selectionDocsOmitLabel` | `boolean` | 在选择文案中直接显示文档路径,而不是带标签的文档链接。 | +| `selectionExtras` | `string[]` | 附加在选择文案中的额外短文本。 | +| `markdownCapable` | `boolean` | 将该渠道标记为支持 Markdown,用于出站格式决策。 | +| `exposure` | `object` | 用于设置、已配置列表和文档界面的渠道可见性控制。 | +| `quickstartAllowFrom` | `boolean` | 允许该渠道接入标准快速开始 `allowFrom` 设置流程。 | +| `forceAccountBinding` | `boolean` | 即使只存在一个账号,也要求显式账号绑定。 | +| `preferSessionLookupForAnnounceTarget` | `boolean` | 为该渠道解析公告目标时,优先使用会话查找。 | 示例: @@ -120,11 +122,11 @@ x-i18n: "detailLabel": "My Channel Bot", "docsPath": "/channels/my-channel", "docsLabel": "my-channel", - "blurb": "基于 Webhook 的自托管聊天集成。", + "blurb": "Webhook-based self-hosted chat integration.", "order": 80, "aliases": ["mc"], "preferOver": ["my-channel-legacy"], - "selectionDocsPrefix": "指南:", + "selectionDocsPrefix": "Guide:", "selectionExtras": ["Markdown"], "markdownCapable": true, "exposure": { @@ -140,11 +142,12 @@ x-i18n: `exposure` 支持: -- `configured`:在已配置 / 状态类列表界面中包含该渠道 -- `setup`:在交互式设置 / 配置选择器中包含该渠道 -- `docs`:将该渠道标记为在文档 / 导航界面中面向公开展示 +- `configured`:在已配置/状态类列表界面中包含该渠道 +- `setup`:在交互式设置/配置选择器中包含该渠道 +- `docs`:将该渠道标记为在文档/导航界面中对外可见 -`showConfigured` 和 `showInSetup` 仍然作为旧版别名受到支持。请优先使用 `exposure`。 +`showConfigured` 和 `showInSetup` 仍然作为旧版别名受支持。推荐优先使用 +`exposure`。 ### `openclaw.install` @@ -152,18 +155,25 @@ x-i18n: | 字段 | 类型 | 含义 | | ---------------------------- | -------------------- | -------------------------------------------------------------------------------- | -| `npmSpec` | `string` | 用于安装 / 更新流程的规范 npm spec。 | +| `npmSpec` | `string` | 用于安装/更新流程的规范 npm spec。 | | `localPath` | `string` | 本地开发或内置安装路径。 | -| `defaultChoice` | `"npm"` \| `"local"` | 当两者都可用时的首选安装来源。 | -| `minHostVersion` | `string` | 支持的最低 OpenClaw 版本,格式为 `>=x.y.z`。 | +| `defaultChoice` | `"npm"` \| `"local"` | 当两者都可用时,首选的安装来源。 | +| `minHostVersion` | `string` | 最低支持的 OpenClaw 版本,格式为 `>=x.y.z`。 | | `expectedIntegrity` | `string` | 预期的 npm dist 完整性字符串,通常为 `sha512-...`,用于固定版本安装。 | -| `allowInvalidConfigRecovery` | `boolean` | 允许内置插件重装流程从特定的过期配置失败中恢复。 | +| `allowInvalidConfigRecovery` | `boolean` | 允许内置插件的重新安装流程从特定的陈旧配置失败中恢复。 | -交互式新手引导也会将 `openclaw.install` 用于按需安装界面。如果你的插件在运行时加载前就暴露提供商认证选项,或暴露渠道设置 / 目录元数据,则新手引导可以显示该选项、提示用户选择 npm 还是本地安装、安装或启用插件,然后继续执行所选流程。npm 新手引导选项要求可信的目录元数据,其中必须包含精确版本的 `npmSpec` 和 `expectedIntegrity`;未固定版本的包名和 dist-tag 不会用于自动新手引导安装。请将“显示什么”的元数据保留在 `openclaw.plugin.json` 中,将“如何安装”的元数据保留在 `package.json` 中。 +交互式新手引导也会使用 `openclaw.install` 来支持按需安装界面。 +如果你的插件在运行时加载之前就暴露提供商认证选项,或提供渠道设置/目录元数据, +新手引导就可以展示这些选项,提示选择 npm 或本地安装,安装或启用插件, +然后继续所选流程。npm 新手引导选项要求使用带有注册表 `npmSpec` 的可信目录元数据; +精确版本和 `expectedIntegrity` 是可选的固定项。如果存在 +`expectedIntegrity`,安装/更新流程会强制校验它。请将“显示什么”的元数据放在 +`openclaw.plugin.json` 中,将“如何安装它”的元数据放在 `package.json` 中。 -如果设置了 `minHostVersion`,则安装和清单注册表加载都会强制执行它。较旧的宿主会跳过该插件;无效的版本字符串会被拒绝。 +如果设置了 `minHostVersion`,安装和清单注册表加载都会强制执行它。 +较旧的宿主会跳过该插件;无效的版本字符串会被拒绝。 -对于固定版本的 npm 安装,请在 `npmSpec` 中保留精确版本,并添加预期的制品完整性: +对于固定版本的 npm 安装,请在 `npmSpec` 中保留精确版本,并添加预期的制品完整性值: ```json { @@ -177,7 +187,11 @@ x-i18n: } ``` -`allowInvalidConfigRecovery` 并不是对损坏配置的一般性绕过。它仅用于狭窄范围内的内置插件恢复,以便重装 / 设置可以修复已知的升级遗留问题,例如缺失的内置插件路径,或同一插件对应的过期 `channels.` 条目。如果配置因无关原因损坏,安装仍会默认拒绝,并提示操作者运行 `openclaw doctor --fix`。 +`allowInvalidConfigRecovery` 并不是针对损坏配置的通用绕过方式。 +它仅用于狭义的内置插件恢复场景,以便重新安装/设置可以修复已知的升级遗留问题, +例如缺失的内置插件路径,或该插件对应的过期 `channels.` 条目。 +如果配置因无关原因损坏,安装仍会以安全关闭方式失败,并提示操作员运行 +`openclaw doctor --fix`。 ### 延迟完整加载 @@ -195,31 +209,37 @@ x-i18n: } ``` -启用后,在监听前的启动阶段,OpenClaw 即使对已经配置的渠道也只会加载 `setupEntry`。完整入口会在 Gateway 网关开始监听后再加载。 +启用后,OpenClaw 在监听前的启动阶段只会加载 `setupEntry`, +即使对于已经配置好的渠道也是如此。完整入口会在 Gateway 网关开始监听后再加载。 - 只有在你的 `setupEntry` 已经注册了 Gateway 网关在开始监听前所需的一切内容时,才应启用延迟加载(渠道注册、HTTP 路由、Gateway 网关方法)。如果完整入口拥有必需的启动能力,请保持默认行为。 + 只有当你的 `setupEntry` 在 Gateway 网关开始监听前已经注册了所有必需内容时, + 才应启用延迟加载(渠道注册、HTTP 路由、Gateway 网关方法)。 + 如果完整入口负责必需的启动能力,请保持默认行为。 -如果你的设置 / 完整入口会注册 Gateway 网关 RPC 方法,请保持使用插件专属前缀。保留的核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍归核心所有,并始终解析到 `operator.admin`。 +如果你的设置/完整入口会注册 Gateway 网关 RPC 方法,请把它们放在插件专用前缀下。 +保留的核心管理命名空间(`config.*`、 +`exec.approvals.*`、`wizard.*`、`update.*`)仍由核心拥有, +并始终解析到 `operator.admin`。 ## 插件清单 每个原生插件都必须在包根目录中提供一个 `openclaw.plugin.json`。 -OpenClaw 会用它在不执行插件代码的情况下验证配置。 +OpenClaw 会使用它在不执行插件代码的情况下验证配置。 ```json { "id": "my-plugin", "name": "My Plugin", - "description": "为 OpenClaw 增加 My Plugin 功能", + "description": "Adds My Plugin capabilities to OpenClaw", "configSchema": { "type": "object", "additionalProperties": false, "properties": { "webhookSecret": { "type": "string", - "description": "Webhook 验证密钥" + "description": "Webhook verification secret" } } } @@ -241,7 +261,7 @@ OpenClaw 会用它在不执行插件代码的情况下验证配置。 } ``` -即使插件没有任何配置,也必须提供一个 schema。空 schema 是有效的: +即使插件没有任何配置,也必须提供一个模式。空模式也是有效的: ```json { @@ -253,22 +273,24 @@ OpenClaw 会用它在不执行插件代码的情况下验证配置。 } ``` -完整的 schema 参考请参阅 [插件清单](/zh-CN/plugins/manifest)。 +完整模式参考请见 [插件清单](/zh-CN/plugins/manifest)。 ## ClawHub 发布 -对于插件包,请使用针对包的 ClawHub 命令: +对于插件包,请使用面向包的 ClawHub 专用命令: ```bash clawhub package publish your-org/your-plugin --dry-run clawhub package publish your-org/your-plugin ``` -旧的仅限 Skills 的发布别名用于 Skills。插件包应始终使用 `clawhub package publish`。 +旧版仅限 Skills 的发布别名只用于 Skills。插件包应始终使用 +`clawhub package publish`。 ## 设置入口 -`setup-entry.ts` 文件是 `index.ts` 的轻量替代方案,当 OpenClaw 只需要设置界面时(新手引导、配置修复、已禁用渠道检查),会加载它。 +`setup-entry.ts` 文件是 `index.ts` 的轻量替代方案, +当 OpenClaw 只需要设置界面时(新手引导、配置修复、已禁用渠道检查),就会加载它。 ```typescript // setup-entry.ts @@ -278,66 +300,74 @@ import { myChannelPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(myChannelPlugin); ``` -这可以避免在设置流程中加载沉重的运行时代码(加密库、CLI 注册、后台服务)。 +这样可以避免在设置流程中加载重量级运行时代码(加密库、CLI 注册、后台服务)。 -对于将设置安全导出保存在 sidecar 模块中的内置工作区渠道,可以使用 +对于那些将设置安全导出保存在辅助模块中的内置工作区渠道,可以使用 `openclaw/plugin-sdk/channel-entry-contract` 中的 `defineBundledChannelSetupEntry(...)`,而不是 -`defineSetupPluginEntry(...)`。该内置契约还支持可选的 `runtime` 导出,以便让设置时的运行时接线保持轻量且明确。 +`defineSetupPluginEntry(...)`。该内置契约还支持可选的 `runtime` 导出, +从而让设置时的运行时接线保持轻量且明确。 -**OpenClaw 何时使用 `setupEntry` 而不是完整入口:** +**OpenClaw 在以下情况下会使用 `setupEntry` 而不是完整入口:** -- 渠道已禁用,但仍需要设置 / 新手引导界面 +- 渠道已禁用,但需要设置/新手引导界面 - 渠道已启用,但尚未配置 - 已启用延迟加载(`deferConfiguredChannelFullLoadUntilAfterListen`) **`setupEntry` 必须注册的内容:** - 渠道插件对象(通过 `defineSetupPluginEntry`) -- 任何在 Gateway 网关开始监听前所需的 HTTP 路由 -- 启动期间需要的任何 Gateway 网关方法 +- Gateway 网关监听前所需的任何 HTTP 路由 +- 启动期间所需的任何 Gateway 网关方法 -这些启动期 Gateway 网关方法仍应避免使用保留的核心管理命名空间,例如 `config.*` 或 `update.*`。 +这些启动期 Gateway 网关方法仍应避免使用保留的核心管理命名空间, +例如 `config.*` 或 `update.*`。 **`setupEntry` 不应包含的内容:** - CLI 注册 - 后台服务 -- 沉重的运行时导入(加密库、SDK) +- 重量级运行时导入(加密、SDK) - 仅在启动后才需要的 Gateway 网关方法 -### 精简的设置辅助导入 +### 狭义设置辅助导入 -对于仅设置的热路径,当你只需要部分设置功能时,应优先使用更精简的设置辅助接缝,而不是更宽泛的 `plugin-sdk/setup` 总入口: +对于仅限设置的热路径,如果你只需要部分设置能力,优先使用狭义的设置辅助接缝, +而不是更宽泛的 `plugin-sdk/setup` 聚合入口: -| 导入路径 | 适用场景 | 关键导出 | -| ---------------------------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `plugin-sdk/setup-runtime` | 在 `setupEntry` / 延迟渠道启动期间仍可用的设置时运行时辅助工具 | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | -| `plugin-sdk/setup-adapter-runtime` | 识别环境的账户设置适配器 | `createEnvPatchedAccountSetupAdapter` | -| `plugin-sdk/setup-tools` | 设置 / 安装 CLI / 归档 / 文档辅助工具 | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | +| 导入路径 | 适用场景 | 关键导出 | +| ---------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `plugin-sdk/setup-runtime` | 在 `setupEntry` / 延迟渠道启动中仍可用的设置期运行时辅助工具 | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | +| `plugin-sdk/setup-adapter-runtime` | 感知环境的账号设置适配器 | `createEnvPatchedAccountSetupAdapter` | +| `plugin-sdk/setup-tools` | 设置/安装 CLI/归档/文档辅助工具 | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | -当你需要完整的共享设置工具箱时,请使用更宽泛的 `plugin-sdk/setup` 接缝,其中包括配置补丁辅助工具,例如 +当你需要完整的共享设置工具箱时,请使用更宽泛的 +`plugin-sdk/setup` 接缝,其中包括配置补丁辅助工具,例如 `moveSingleAccountChannelSectionToDefaultAccount(...)`。 -这些设置补丁适配器在导入时仍然对热路径安全。它们对内置单账户提升契约面的查找是惰性的,因此导入 -`plugin-sdk/setup-runtime` 不会在适配器真正使用前,急切加载内置契约面发现逻辑。 +这些设置补丁适配器在导入时仍可安全用于热路径。它们针对内置单账号提升的契约表面查找是惰性的, +因此导入 `plugin-sdk/setup-runtime` 不会在适配器真正使用前急切加载内置契约表面发现逻辑。 -### 渠道自有的单账户提升 +### 渠道自有的单账号提升 -当渠道从单账户顶层配置升级到 -`channels..accounts.*` 时,默认的共享行为会把提升后的账户作用域值移入 `accounts.default`。 +当一个渠道从单账号顶层配置升级到 +`channels..accounts.*` 时,默认的共享行为是将被提升的账号级值移动到 +`accounts.default` 中。 -内置渠道可以通过其设置契约面来收窄或覆盖这一提升行为: +内置渠道可以通过其设置契约表面收窄或覆盖这一提升行为: -- `singleAccountKeysToMove`:应移入提升后账户的额外顶层键 -- `namedAccountPromotionKeys`:如果已存在具名账户,则仅将这些键移入提升后的账户;共享的 policy / delivery 键保留在渠道根级别 -- `resolveSingleAccountPromotionTarget(...)`:选择由哪个现有账户接收提升后的值 +- `singleAccountKeysToMove`:应移动到被提升账号中的额外顶层键 +- `namedAccountPromotionKeys`:当已存在命名账号时,只有这些键会移动到被提升账号中; + 共享的策略/投递键会保留在渠道根级 +- `resolveSingleAccountPromotionTarget(...)`:选择哪个现有账号接收被提升的值 -Matrix 是当前的内置示例。如果恰好已经存在一个具名 Matrix 账户,或者如果 `defaultAccount` 指向现有的非规范键名(例如 `Ops`),那么提升会保留该账户,而不是创建新的 `accounts.default` 条目。 +Matrix 是当前的内置示例。如果恰好已存在一个命名的 Matrix 账号, +或者如果 `defaultAccount` 指向一个现有的非规范键(例如 `Ops`), +提升过程会保留该账号,而不是新建一个 `accounts.default` 条目。 -## 配置 schema +## 配置模式 -插件配置会根据你的清单中的 JSON Schema 进行验证。用户通过以下方式配置插件: +插件配置会根据你在清单中定义的 JSON Schema 进行验证。用户通过以下方式配置插件: ```json5 { @@ -353,9 +383,9 @@ Matrix 是当前的内置示例。如果恰好已经存在一个具名 Matrix } ``` -你的插件会在注册期间通过 `api.pluginConfig` 收到该配置。 +你的插件会在注册期间通过 `api.pluginConfig` 接收这份配置。 -对于渠道专属配置,请改用渠道配置部分: +对于渠道专用配置,请改用渠道配置段: ```json5 { @@ -368,10 +398,10 @@ Matrix 是当前的内置示例。如果恰好已经存在一个具名 Matrix } ``` -### 构建渠道配置 schema +### 构建渠道配置模式 -使用 `openclaw/plugin-sdk/core` 中的 `buildChannelConfigSchema`,将 -Zod schema 转换为 OpenClaw 可验证的 `ChannelConfigSchema` 包装器: +使用 `openclaw/plugin-sdk/core` 中的 `buildChannelConfigSchema`, +将 Zod 模式转换为 OpenClaw 会验证的 `ChannelConfigSchema` 包装器: ```typescript import { z } from "zod"; @@ -398,8 +428,8 @@ import type { ChannelSetupWizard } from "openclaw/plugin-sdk/channel-setup"; const setupWizard: ChannelSetupWizard = { channel: "my-channel", status: { - configuredLabel: "已连接", - unconfiguredLabel: "未配置", + configuredLabel: "Connected", + unconfiguredLabel: "Not configured", resolveConfigured: ({ cfg }) => Boolean((cfg.channels as any)?.["my-channel"]?.token), }, credentials: [ @@ -408,9 +438,9 @@ const setupWizard: ChannelSetupWizard = { providerHint: "my-channel", credentialLabel: "Bot token", preferredEnvVar: "MY_CHANNEL_BOT_TOKEN", - envPrompt: "使用环境中的 MY_CHANNEL_BOT_TOKEN 吗?", - keepPrompt: "保留当前 token 吗?", - inputPrompt: "输入你的 bot token:", + envPrompt: "Use MY_CHANNEL_BOT_TOKEN from environment?", + keepPrompt: "Keep current token?", + inputPrompt: "Enter your bot token:", inspect: ({ cfg, accountId }) => { const token = (cfg.channels as any)?.["my-channel"]?.token; return { @@ -424,21 +454,22 @@ const setupWizard: ChannelSetupWizard = { ``` `ChannelSetupWizard` 类型支持 `credentials`、`textInputs`、 -`dmPolicy`、`allowFrom`、`groupAccess`、`prepare`、`finalize` 等等。 -完整示例请参阅内置插件包(例如 Discord 插件的 `src/channel.setup.ts`)。 +`dmPolicy`、`allowFrom`、`groupAccess`、`prepare`、`finalize` 等。 +完整示例请参见内置插件包(例如 Discord 插件的 `src/channel.setup.ts`)。 -对于只需要标准 -`note -> prompt -> parse -> merge -> patch` 流程的私信白名单提示,应优先使用 -`openclaw/plugin-sdk/setup` 中的共享设置辅助工具: +对于仅需要标准 +`note -> prompt -> parse -> merge -> patch` 流程的私信白名单提示, +优先使用 `openclaw/plugin-sdk/setup` 中的共享设置辅助工具: `createPromptParsedAllowFromForAccount(...)`、 `createTopLevelChannelParsedAllowFromPrompt(...)` 和 `createNestedChannelParsedAllowFromPrompt(...)`。 -对于仅在标签、分数和可选附加行方面有所不同的渠道设置状态块,应优先使用 -`openclaw/plugin-sdk/setup` 中的 -`createStandardChannelSetupStatus(...)`,而不是在每个插件中手写相同的 `status` 对象。 +对于仅在标签、分数和可选附加行上有所不同的渠道设置状态块, +优先使用 `openclaw/plugin-sdk/setup` 中的 +`createStandardChannelSetupStatus(...)`, +而不是在每个插件中手写相同的 `status` 对象。 -对于只应在某些上下文中显示的可选设置界面,请使用 +对于只应在特定上下文中出现的可选设置界面,请使用 `openclaw/plugin-sdk/channel-setup` 中的 `createOptionalChannelSetupSurface`: @@ -451,26 +482,31 @@ const setupSurface = createOptionalChannelSetupSurface({ npmSpec: "@myorg/openclaw-my-channel", docsPath: "/channels/my-channel", }); -// 返回 { setupAdapter, setupWizard } +// Returns { setupAdapter, setupWizard } ``` `plugin-sdk/channel-setup` 还暴露了更底层的 `createOptionalChannelSetupAdapter(...)` 和 -`createOptionalChannelSetupWizard(...)` 构建器,用于你只需要该可选安装界面其中一半能力的场景。 +`createOptionalChannelSetupWizard(...)` 构建器, +适用于你只需要该可选安装界面其中一半的情况。 -生成的可选适配器 / 向导在真实配置写入时会默认拒绝失败关闭。它们会在 -`validateInput`、`applyAccountConfig` 和 `finalize` 之间复用一条“需要安装”的提示信息,并在设置了 `docsPath` 时附加文档链接。 +生成的可选适配器/向导在真实配置写入时会以安全关闭方式失败。 +它们会在 `validateInput`、`applyAccountConfig` 和 `finalize` +之间复用同一条“需要安装”的消息,并在设置了 `docsPath` 时附加文档链接。 -对于由二进制驱动的设置 UI,应优先使用共享的委托辅助工具,而不是在每个渠道中复制相同的二进制 / 状态粘合逻辑: +对于由二进制程序支持的设置 UI,优先使用共享的委托辅助工具, +而不是把相同的二进制/状态胶水逻辑复制到每个渠道中: -- `createDetectedBinaryStatus(...)`:用于仅在标签、提示、分数和二进制检测上有所不同的状态块 -- `createCliPathTextInput(...)`:用于基于路径的文本输入 +- `createDetectedBinaryStatus(...)`:适用于仅在标签、提示、分数和二进制检测上不同的状态块 +- `createCliPathTextInput(...)`:适用于基于路径的文本输入 - `createDelegatedSetupWizardStatusResolvers(...)`、 `createDelegatedPrepare(...)`、`createDelegatedFinalize(...)` 和 - `createDelegatedResolveConfigured(...)`:用于当 `setupEntry` 需要惰性转发到更重的完整向导时 -- `createDelegatedTextInputShouldPrompt(...)`:用于当 `setupEntry` 只需要委托 `textInputs[*].shouldPrompt` 决策时 + `createDelegatedResolveConfigured(...)`:适用于当 `setupEntry` + 需要惰性转发到更重的完整向导时 +- `createDelegatedTextInputShouldPrompt(...)`:适用于当 `setupEntry` + 只需要委托 `textInputs[*].shouldPrompt` 决策时 -## 发布与安装 +## 发布和安装 **外部插件:** 发布到 [ClawHub](/zh-CN/tools/clawhub) 或 npm,然后安装: @@ -478,13 +514,15 @@ const setupSurface = createOptionalChannelSetupSurface({ openclaw plugins install @myorg/openclaw-my-plugin ``` -OpenClaw 会先尝试 ClawHub,并在失败后自动回退到 npm。你也可以显式强制使用 ClawHub: +OpenClaw 会先尝试 ClawHub,失败后再自动回退到 npm。 +你也可以显式强制使用 ClawHub: ```bash -openclaw plugins install clawhub:@myorg/openclaw-my-plugin # 仅 ClawHub +openclaw plugins install clawhub:@myorg/openclaw-my-plugin # ClawHub only ``` -没有对应的 `npm:` 覆盖写法。当你希望在 ClawHub 回退后走 npm 路径时,请使用普通的 npm 包 spec: +没有对应的 `npm:` 覆盖方式。当你希望在 ClawHub 回退之后走 npm 路径时, +请使用普通的 npm 包 spec: ```bash openclaw plugins install @myorg/openclaw-my-plugin @@ -492,7 +530,7 @@ openclaw plugins install @myorg/openclaw-my-plugin **仓库内插件:** 放在内置插件工作区树下,构建期间会自动发现。 -**用户可以安装:** +**用户可安装:** ```bash openclaw plugins install @@ -500,13 +538,19 @@ openclaw plugins install 对于来源于 npm 的安装,`openclaw plugins install` 会运行 - `npm install --ignore-scripts`(不执行 lifecycle scripts)。请保持插件依赖树为纯 JS / TS,并避免使用需要 `postinstall` 构建的包。 + `npm install --ignore-scripts`(不执行生命周期脚本)。 + 请保持插件依赖树为纯 JS/TS,并避免依赖那些需要 `postinstall` + 构建的包。 -内置的 OpenClaw 自有插件是唯一的启动修复例外:当打包安装检测到某个插件已通过插件配置、旧版渠道配置或其内置默认启用清单启用时,启动流程会在导入前为该插件安装缺失的运行时依赖。第三方插件不应依赖启动期安装;请继续使用显式的插件安装器。 +只有 OpenClaw 自有的内置插件属于启动修复的例外情况: +当打包安装检测到某个插件已通过插件配置、旧版渠道配置, +或其内置的默认启用清单被启用时, +启动过程会在导入前安装该插件缺失的运行时依赖。 +第三方插件不应依赖启动期安装;请继续使用显式的插件安装器。 ## 相关内容 -- [SDK 概览 入口点](/zh-CN/plugins/sdk-entrypoints) -- `definePluginEntry` 和 `defineChannelPluginEntry` -- [插件清单](/zh-CN/plugins/manifest) -- 完整清单 schema 参考 -- [构建插件](/zh-CN/plugins/building-plugins) -- 分步入门指南 +- [SDK 概览](/zh-CN/plugins/sdk-entrypoints) -- `definePluginEntry` 和 `defineChannelPluginEntry` +- [插件清单](/zh-CN/plugins/manifest) -- 完整清单模式参考 +- [构建插件](/zh-CN/plugins/building-plugins) -- 分步式入门指南