测试
OpenClaw 有三个 Vitest 测试套件(单元 / 集成、e2e、实时)以及一小组 Docker 运行器。 本文档是一份“我们如何测试”的指南:- 每个测试套件覆盖什么内容(以及它刻意 不 覆盖什么)
- 常见工作流(本地、推送前、调试)应运行哪些命令
- 实时测试如何发现凭证并选择模型 / 提供商
- 如何为真实世界中的模型 / 提供商问题添加回归测试
快速开始
大多数时候:- 完整门禁(推送前预期运行):
pnpm build && pnpm check && 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
- 覆盖率门禁:
pnpm test:coverage - E2E 测试套件:
pnpm test:e2e
- 实时测试套件(模型 + Gateway 网关工具 / 图像探针):
pnpm test:live - 安静地只运行一个实时测试文件:
pnpm test:live -- src/agents/models.profiles.live.test.ts
测试套件(各自在哪里运行)
可以把这些测试套件理解为“真实性逐步增加”(同时不稳定性 / 成本也逐步增加):单元 / 集成(默认)
- 命令:
pnpm test - 配置:对现有分域 Vitest 项目执行十个串行分片运行(
vitest.full-*.config.ts) - 文件:
src/**/*.test.ts、packages/**/*.test.ts、test/**/*.test.ts下的核心 / 单元测试清单,以及由vitest.unit.config.ts覆盖的白名单uiNode 测试 - 范围:
- 纯单元测试
- 进程内集成测试(Gateway 网关认证、路由、工具、解析、配置)
- 已知缺陷的确定性回归测试
- 预期:
- 在 CI 中运行
- 不需要真实密钥
- 应该快速且稳定
- 项目说明:
- 无目标的
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),而不是一个巨大的原生根项目进程。这样可以降低高负载机器上的峰值 RSS,并避免 auto-reply / 扩展工作饿死无关测试套件。 pnpm test --watch仍然使用原生根vitest.config.ts项目图,因为多分片监听循环并不现实。pnpm test、pnpm test:watch和pnpm test:perf:imports现在会先把显式文件 / 目录目标路由到分域测试通道,因此pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts不需要付出完整根项目启动成本。- 当差异只涉及可路由的源文件 / 测试文件时,
pnpm test:changed会把变更的 Git 路径扩展到同样的分域测试通道;配置 / setup 修改仍会回退到更广泛的根项目重跑。 - 选定的
plugin-sdk和commands测试也会通过专用的轻量通道运行,这些通道会跳过test/setup-openclaw-runtime.ts;有状态 / 运行时较重的文件仍留在现有通道中。 - 选定的
plugin-sdk和commands辅助源文件也会在 changed 模式下把运行映射到这些轻量通道中的显式同级测试,因此辅助文件的编辑无需重跑该目录下完整的重型测试套件。 auto-reply现在有三个专用桶:顶层核心辅助函数、顶层reply.*集成测试,以及src/auto-reply/reply/**子树。这样可以把最重的 reply 测试支架工作与便宜的 status / chunk / token 测试分离。
- 无目标的
- 嵌入式运行器说明:
- 当你修改消息工具发现输入或压缩运行时上下文时, 要同时保持两个层级的覆盖。
- 为纯路由 / 规范化边界添加聚焦的辅助函数回归测试。
- 还要保持嵌入式运行器集成测试套件健康:
src/agents/pi-embedded-runner/compact.hooks.test.ts、src/agents/pi-embedded-runner/run.overflow-compaction.test.ts,以及src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts。 - 这些测试套件会验证分域 id 和压缩行为仍然通过真实的
run.ts/compact.ts路径流转;仅有辅助函数测试并不能充分替代这些集成路径。
- Pool 说明:
- 基础 Vitest 配置现在默认使用
threads。 - 共享 Vitest 配置还固定了
isolate: false,并在根项目、e2e 和实时配置中使用非隔离运行器。 - 根 UI 通道保留其
jsdomsetup 和优化器,但现在也在共享的非隔离运行器上运行。 - 每个
pnpm test分片都继承共享 Vitest 配置中的同一组threads+isolate: false默认值。 - 共享的
scripts/run-vitest.mjs启动器现在还会默认为 Vitest 子 Node 进程添加--no-maglev,以减少大型本地运行中的 V8 编译抖动。如果你需要与原始 V8 行为进行对比,请设置OPENCLAW_VITEST_ENABLE_MAGLEV=1。
- 基础 Vitest 配置现在默认使用
- 本地快速迭代说明:
pnpm test:changed会在变更路径能清晰映射到较小套件时,通过分域测试通道运行。pnpm test:max和pnpm test:changed:max保持相同的路由行为,只是使用更高的 worker 上限。- 本地 worker 自动缩放现在刻意更加保守,并且在主机负载平均值已经较高时也会回退,因此默认情况下多个并发 Vitest 运行的破坏性更小。
- 基础 Vitest 配置把项目 / 配置文件标记为
forceRerunTriggers,因此测试接线变化时,changed 模式重跑仍然保持正确。 - 在受支持的主机上,该配置会保持启用
OPENCLAW_VITEST_FS_MODULE_CACHE;如果你想为直接性能分析指定一个明确的缓存位置,请设置OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path。
- 性能调试说明:
pnpm test:perf:imports会启用 Vitest 导入时长报告以及导入明细输出。pnpm test:perf:imports:changed会将同样的性能分析视图限定为自origin/main以来变更的文件。
pnpm test:perf:changed:bench -- --ref <git-ref>会把已提交差异的路由式test:changed与原生根项目路径进行比较,并输出总耗时和 macOS 最大 RSS。pnpm test:perf:changed:bench -- --worktree会通过scripts/test-projects.mjs和根 Vitest 配置,将当前脏工作树的变更文件列表路由后进行基准测试。pnpm test:perf:profile:main会为 Vitest / Vite 启动和转换开销写出主线程 CPU profile。pnpm test:perf:profile:runner会在禁用文件并行的情况下,为单元测试套件写出运行器 CPU + 堆 profile。
E2E(Gateway 网关冒烟)
- 命令:
pnpm test:e2e - 配置:
vitest.e2e.config.ts - 文件:
src/**/*.e2e.test.ts、test/**/*.e2e.test.ts - 运行时默认值:
- 使用 Vitest
threads且isolate: false,与仓库其余部分保持一致。 - 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。
- 默认以静默模式运行,以减少控制台 I/O 开销。
- 使用 Vitest
- 常用覆盖项:
OPENCLAW_E2E_WORKERS=<n>:强制指定 worker 数量(上限 16)。OPENCLAW_E2E_VERBOSE=1:重新启用详细控制台输出。
- 范围:
- 多实例 Gateway 网关端到端行为
- WebSocket / HTTP 表面、节点配对以及更重的网络交互
- 预期:
- 在 CI 中运行(当流水线启用时)
- 不需要真实密钥
- 比单元测试包含更多可变因素(可能更慢)
E2E:OpenShell 后端冒烟
- 命令:
pnpm test:e2e:openshell - 文件:
test/openshell-sandbox.e2e.test.ts - 范围:
- 通过 Docker 在主机上启动一个隔离的 OpenShell Gateway 网关
- 从临时本地 Dockerfile 创建一个沙箱
- 通过真实的
sandbox ssh-config+ SSH 执行,演练 OpenClaw 的 OpenShell 后端 - 通过沙箱 fs bridge 验证远端标准化文件系统行为
- 预期:
- 仅限显式选择加入;不属于默认
pnpm test:e2e运行的一部分 - 需要本地
openshellCLI 和可用的 Docker daemon - 使用隔离的
HOME/XDG_CONFIG_HOME,然后销毁测试 Gateway 网关和沙箱
- 仅限显式选择加入;不属于默认
- 常用覆盖项:
OPENCLAW_E2E_OPENSHELL=1:在手动运行更广泛的 e2e 套件时启用该测试OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell:指向非默认 CLI 二进制或包装脚本
实时(真实提供商 + 真实模型)
- 命令:
pnpm test:live - 配置:
vitest.live.config.ts - 文件:
src/**/*.live.test.ts - 默认:由
pnpm test:live启用(会设置OPENCLAW_LIVE_TEST=1) - 范围:
- “这个提供商 / 模型今天是否真的能工作,并且使用真实凭证?”
- 捕获提供商格式变化、工具调用怪癖、认证问题和速率限制行为
- 预期:
- 设计上不保证 CI 稳定性(真实网络、真实提供商策略、配额、故障)
- 会花钱 / 消耗速率限制
- 优先运行缩小范围的子集,而不是“全部”
- 实时运行会 source
~/.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 网关 / 探针心跳。
我该运行哪个测试套件?
使用这个决策表:- 编辑逻辑 / 测试:运行
pnpm test(如果你改动很多,也运行pnpm test:coverage) - 触碰 Gateway 网关网络 / WS 协议 / 配对:额外运行
pnpm test:e2e - 调试“我的机器人挂了” / 提供商专属失败 / 工具调用:运行缩小范围的
pnpm test:live
实时:Android 节点能力扫描
- 测试:
src/gateway/android-node.capabilities.live.test.ts - 脚本:
pnpm android:test:integration - 目标:调用已连接 Android 节点当前声明的每一个命令,并断言命令契约行为。
- 范围:
- 预设条件 / 手动 setup(该测试套件不会安装 / 运行 / 配对应用)。
- 对选定 Android 节点逐命令进行 Gateway 网关
node.invoke验证。
- 必要预设:
- Android 应用已经连接并与 Gateway 网关配对。
- 应用保持在前台。
- 对你期望通过的能力已授予权限 / 捕获同意。
- 可选目标覆盖项:
OPENCLAW_ANDROID_NODE_ID或OPENCLAW_ANDROID_NODE_NAME。OPENCLAW_ANDROID_GATEWAY_URL/OPENCLAW_ANDROID_GATEWAY_TOKEN/OPENCLAW_ANDROID_GATEWAY_PASSWORD。
- 完整 Android setup 细节:Android App
实时:模型冒烟(profile keys)
实时测试被拆分为两层,以便我们隔离故障:- “直接模型”告诉我们,使用给定密钥时,提供商 / 模型是否至少能响应。
- “Gateway 网关冒烟”告诉我们,针对该模型,完整的 Gateway 网关 + 智能体流水线是否正常工作(会话、历史、工具、沙箱策略等)。
第 1 层:直接模型补全(无 Gateway 网关)
- 测试:
src/agents/models.profiles.live.test.ts - 目标:
- 枚举已发现的模型
- 使用
getApiKeyForModel选择你有凭证的模型 - 对每个模型运行一个小型补全(以及必要时的定向回归测试)
- 如何启用:
pnpm test:live(或者如果直接调用 Vitest,则设置OPENCLAW_LIVE_TEST=1)
- 设置
OPENCLAW_LIVE_MODELS=modern(或all,即 modern 的别名)才会实际运行该测试套件;否则它会跳过,以便让pnpm test:live聚焦于 Gateway 网关冒烟 - 如何选择模型:
OPENCLAW_LIVE_MODELS=modern:运行 modern allowlist(Opus / Sonnet 4.6+、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4)OPENCLAW_LIVE_MODELS=all是 modern allowlist 的别名- 或
OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,..."(逗号分隔的 allowlist)
- 如何选择提供商:
OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"(逗号分隔的 allowlist)
- 密钥来源:
- 默认:profile store 和环境变量回退
- 设置
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1以强制仅使用 profile store
- 存在原因:
- 将“提供商 API 坏了 / 密钥无效”与“Gateway 网关智能体流水线坏了”分离开
- 容纳小型、隔离的回归测试(例如:OpenAI Responses / Codex Responses 的推理回放 + 工具调用流程)
第 2 层:Gateway 网关 + dev 智能体冒烟(即 “@openclaw” 实际做的事情)
- 测试:
src/gateway/gateway-models.profiles.live.test.ts - 目标:
- 启动一个进程内 Gateway 网关
- 创建 / 修补一个
agent:dev:*会话(每次运行可覆盖模型) - 遍历带密钥的模型,并断言:
- “有意义”的响应(无工具)
- 一次真实工具调用可以工作(read probe)
- 可选的额外工具探针(exec+read probe)
- OpenAI 回归路径(仅工具调用 → 后续跟进)持续可用
- 探针细节(便于你快速解释失败原因):
readprobe:测试会在工作区写入一个 nonce 文件,并要求智能体read该文件并回显 nonce。exec+readprobe:测试会要求智能体使用exec将 nonce 写入一个临时文件,然后再read回来。- image probe:测试会附加一个生成的 PNG(猫 + 随机代码),并期望模型返回
cat <CODE>。 - 实现参考:
src/gateway/gateway-models.profiles.live.test.ts和src/gateway/live-image-probe.ts。
- 如何启用:
pnpm test:live(或者如果直接调用 Vitest,则设置OPENCLAW_LIVE_TEST=1)
- 如何选择模型:
- 默认:modern allowlist(Opus / Sonnet 4.6+、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4)
OPENCLAW_LIVE_GATEWAY_MODELS=all是 modern allowlist 的别名- 或设置
OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"(或逗号列表)来缩小范围
- 如何选择提供商(避免“OpenRouter 上所有内容”):
OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"(逗号分隔的 allowlist)
- 工具 + 图像探针在此实时测试中始终开启:
readprobe +exec+readprobe(工具压力测试)- 如果模型声明支持图像输入,则运行 image probe
- 流程(高层):
- 测试会生成一个带有 “CAT” + 随机代码的小 PNG(
src/gateway/live-image-probe.ts) - 通过
agentattachments: [{ mimeType: "image/png", content: "<base64>" }]发送 - Gateway 网关会将附件解析为
images[](src/gateway/server-methods/agent.ts+src/gateway/chat-attachments.ts) - 嵌入式智能体向模型转发一条多模态用户消息
- 断言:回复中包含
cat+ 该代码(OCR 容忍:允许轻微错误)
- 测试会生成一个带有 “CAT” + 随机代码的小 PNG(
provider/model id),请运行:
实时: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)OPENCLAW_LIVE_CLI_BACKEND=1
- 默认值:
- 默认提供商 / 模型:
claude-cli/claude-sonnet-4-6 - 命令 / 参数 / 图像行为来自其所属 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强制开启)。
- 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)。 - 实时 CLI 后端冒烟测试现在会为 Claude、Codex 和 Gemini 演练相同的端到端流程:文本轮次、图像分类轮次,然后通过 Gateway 网关 CLI 验证 MCP
cron工具调用。 - Claude 的默认冒烟测试还会把会话从 Sonnet 修补到 Opus,并验证恢复后的会话仍记得更早的备注。
实时:ACP 绑定冒烟(/acp spawn ... --bind here)
- 测试:
src/gateway/gateway-acp-bind.live.test.ts - 目标:使用实时 ACP 智能体验证真实的 ACP 会话绑定流程:
- 发送
/acp spawn <agent> --bind here - 原地绑定一个合成的消息渠道会话
- 在同一会话上发送一次正常后续消息
- 验证该后续消息落入已绑定的 ACP 会话转录中
- 发送
- 启用:
pnpm test:live src/gateway/gateway-acp-bind.live.test.tsOPENCLAW_LIVE_ACP_BIND=1
- 默认值:
- Docker 中的 ACP 智能体:
claude,codex,gemini - 直接
pnpm test:live ...使用的 ACP 智能体:claude - 合成渠道:Slack 私信风格的会话上下文
- ACP 后端:
acpx
- Docker 中的 ACP 智能体:
- 覆盖项:
OPENCLAW_LIVE_ACP_BIND_AGENT=claudeOPENCLAW_LIVE_ACP_BIND_AGENT=codexOPENCLAW_LIVE_ACP_BIND_AGENT=geminiOPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,geminiOPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND='npx -y @agentclientprotocol/claude-agent-acp@<version>'
- 说明:
- 该通道使用 Gateway 网关
chat.send表面,并带有仅管理员可用的合成 originating-route 字段,因此测试可以附加消息渠道上下文,而不必假装向外部投递。 - 当
OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND未设置时,测试会使用嵌入式acpx插件的内置智能体注册表来获取选定的 ACP 测试智能体。
- 该通道使用 Gateway 网关
- 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可缩小矩阵。 - 它会 source
~/.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 保持从已 source 的 profile 中取得的提供商环境变量,供子测试 CLI 使用。
推荐的实时测试配方
范围窄、显式的 allowlist 最快,也最不容易出问题:-
单模型,直接(无 Gateway 网关):
OPENCLAW_LIVE_MODELS="openai/gpt-5.4" pnpm test:live src/agents/models.profiles.live.test.ts
-
单模型,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 密钥 + Antigravity):
- Gemini(API 密钥):
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
- Gemini(API 密钥):
google/...使用 Gemini API(API 密钥)。google-antigravity/...使用 Antigravity OAuth bridge(类似 Cloud Code Assist 风格的智能体端点)。google-gemini-cli/...使用你机器上的本地 Gemini CLI(单独的认证 + 工具怪癖)。- Gemini API 与 Gemini CLI:
- API:OpenClaw 通过 HTTP 调用 Google 托管的 Gemini API(API 密钥 / profile 认证);这也是大多数用户说“Gemini”时的意思。
- CLI:OpenClaw 会调用本地
gemini二进制;它有自己的认证,并且行为可能不同(流式传输 / 工具支持 / 版本偏差)。
实时:模型矩阵(我们覆盖什么)
没有固定的“CI 模型列表”(实时测试是选择加入的),但以下是建议在有密钥的开发机器上定期覆盖的推荐模型。现代冒烟集(工具调用 + 图像)
这是我们期望保持可用的“常见模型”运行集:- OpenAI(非 Codex):
openai/gpt-5.4(可选:openai/gpt-5.4-mini) - OpenAI Codex:
openai-codex/gpt-5.4 - Anthropic:
anthropic/claude-opus-4-6(或anthropic/claude-sonnet-4-6) - Google(Gemini API):
google/gemini-3.1-pro-preview和google/gemini-3-flash-preview(避免较旧的 Gemini 2.x 模型) - Google(Antigravity):
google-antigravity/claude-opus-4-6-thinking和google-antigravity/gemini-3-flash - Z.AI(GLM):
zai/glm-4.7 - MiniMax:
minimax/MiniMax-M2.7
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) - Google:
google/gemini-3-flash-preview(或google/gemini-3.1-pro-preview) - Z.AI(GLM):
zai/glm-4.7 - MiniMax:
minimax/MiniMax-M2.7
- xAI:
xai/grok-4(或最新可用版本) - Mistral:
mistral/…(选择一个你已启用、支持 tools 的模型) - Cerebras:
cerebras/…(如果你有访问权限) - LM Studio:
lmstudio/…(本地;工具调用取决于 API 模式)
Vision:图像发送(附件 → 多模态消息)
在OPENCLAW_LIVE_GATEWAY_MODELS 中至少包含一个支持图像的模型(Claude / Gemini / OpenAI 的视觉变体等),以便执行图像探针。
聚合器 / 其他 Gateway 网关
如果你启用了密钥,我们也支持通过以下方式进行测试:- OpenRouter:
openrouter/...(数百种模型;使用openclaw models scan查找支持工具 + 图像的候选模型) - OpenCode:
opencode/...用于 Zen,opencode-go/...用于 Go(通过OPENCODE_API_KEY/OPENCODE_ZEN_API_KEY认证)
- 内置:
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 等)
discoverModels(...) 返回的内容,以及当前可用的所有密钥。
凭证(永远不要提交)
实时测试发现凭证的方式与 CLI 相同。实际含义:- 如果 CLI 能工作,实时测试应该也能找到相同的密钥。
-
如果某个实时测试提示“没有凭证”,就像调试
openclaw models list/ 模型选择那样去调试。 -
每个智能体的认证 profile:
~/.openclaw/agents/<agentId>/agent/auth-profiles.json(这就是实时测试中“profile keys”的含义) -
配置:
~/.openclaw/openclaw.json(或OPENCLAW_CONFIG_PATH) -
旧版状态目录:
~/.openclaw/credentials/(如果存在,会复制到 staged 实时 home 中,但它不是主 profile-key 存储) -
本地实时运行默认会把当前配置、每个智能体的
auth-profiles.json文件、旧版credentials/以及受支持的外部 CLI 认证目录复制到临时测试 home 中;staged 实时 home 会跳过workspace/和sandboxes/,并剥离agents.*.workspace/agentDir路径覆盖项,这样探针就不会碰到你真实主机工作区。
~/.profile 中),请在本地测试前运行 source ~/.profile,或者使用下面的 Docker 运行器(它们可以将 ~/.profile 挂载到容器中)。
Deepgram 实时测试(音频转录)
- 测试:
src/media-understanding/providers/deepgram/audio.live.test.ts - 启用:
DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live src/media-understanding/providers/deepgram/audio.live.test.ts
BytePlus(国际版)编码方案实时测试
- 测试:
src/agents/byteplus.live.test.ts - 启用:
BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live src/agents/byteplus.live.test.ts - 可选模型覆盖:
BYTEPLUS_CODING_MODEL=ark-code-latest
ComfyUI 工作流媒体实时测试
- 测试:
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.<capability>,否则会跳过各项能力 - 在修改 comfy 工作流提交、轮询、下载或插件注册后很有用
- 演练内置 comfy 图像、视频和
图像生成实时测试
- 测试:
src/image-generation/runtime.live.test.ts - 命令:
pnpm test:live src/image-generation/runtime.live.test.ts - 测试支架:
pnpm test:live:media image - 范围:
- 枚举每个已注册的图像生成提供商插件
- 在探测前从你的登录 shell(
~/.profile)加载缺失的提供商环境变量 - 默认优先使用实时 / 环境变量 API 密钥,而不是存储的 auth profiles,因此
auth-profiles.json中陈旧的测试密钥不会掩盖真实 shell 凭证 - 跳过没有可用认证 / profile / 模型的提供商
- 通过共享运行时能力运行标准图像生成变体:
google:flash-generategoogle:pro-generategoogle:pro-editopenai:default-generate
- 当前覆盖的内置提供商:
openaigoogle
- 可选缩小范围:
OPENCLAW_LIVE_IMAGE_GENERATION_PROVIDERS="openai,google"OPENCLAW_LIVE_IMAGE_GENERATION_MODELS="openai/gpt-image-1,google/gemini-3.1-flash-image-preview"OPENCLAW_LIVE_IMAGE_GENERATION_CASES="google:flash-generate,google:pro-edit"
- 可选认证行为:
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1:强制使用 profile-store 认证并忽略仅环境变量覆盖
音乐生成实时测试
- 测试:
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 - 范围:
- 演练共享的内置音乐生成提供商路径
- 当前覆盖 Google 和 MiniMax
- 在探测前从你的登录 shell(
~/.profile)加载提供商环境变量 - 默认优先使用实时 / 环境变量 API 密钥,而不是存储的 auth profiles,因此
auth-profiles.json中陈旧的测试密钥不会掩盖真实 shell 凭证 - 跳过没有可用认证 / profile / 模型的提供商
- 在可用时运行两种已声明的运行时模式:
generate:仅提示词输入edit:当提供商声明capabilities.edit.enabled时
- 当前共享通道覆盖:
google:generate、editminimax:generatecomfy:单独的 Comfy 实时测试文件,不在这个共享扫描中
- 可选缩小范围:
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-store 认证并忽略仅环境变量覆盖
视频生成实时测试
- 测试:
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 - 范围:
- 演练共享的内置视频生成提供商路径
- 在探测前从你的登录 shell(
~/.profile)加载提供商环境变量 - 默认优先使用实时 / 环境变量 API 密钥,而不是存储的 auth profiles,因此
auth-profiles.json中陈旧的测试密钥不会掩盖真实 shell 凭证 - 跳过没有可用认证 / profile / 模型的提供商
- 在可用时运行两种已声明的运行时模式:
generate:仅提示词输入imageToVideo:当提供商声明capabilities.imageToVideo.enabled,且选定的提供商 / 模型在共享扫描中接受基于 buffer 的本地图像输入时videoToVideo:当提供商声明capabilities.videoToVideo.enabled,且选定的提供商 / 模型在共享扫描中接受基于 buffer 的本地视频输入时
- 当前在共享扫描中已声明但被跳过的
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文本转视频,以及一个默认使用远程图像 URL 夹具的kling通道
- 当前
videoToVideo实时覆盖:- 仅
runway,且选定模型为runway/gen4_aleph时
- 仅
- 当前在共享扫描中已声明但被跳过的
videoToVideo提供商:alibaba、qwen、xai,因为这些路径目前需要远程http(s)/ MP4 参考 URLgoogle,因为当前共享 Gemini / Veo 通道使用基于本地 buffer 的输入,而该路径在共享扫描中不被接受openai,因为当前共享通道缺乏对特定组织视频修补 / 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_REQUIRE_PROFILE_KEYS=1:强制使用 profile-store 认证并忽略仅环境变量覆盖
媒体实时测试支架
- 命令:
pnpm test:live:media - 目的:
- 通过一个仓库原生入口点运行共享的图像、音乐和视频实时测试套件
- 自动从
~/.profile加载缺失的提供商环境变量 - 默认自动将每个测试套件缩小到当前具有可用认证的提供商
- 复用
scripts/test-live.mjs,因此心跳和安静模式行为保持一致
- 示例:
pnpm test:live:mediapnpm test:live:media image video --providers openai,google,minimaxpnpm test:live:media video --video-providers openai,runway --all-providerspnpm test:live:media music --quiet
Docker 运行器(可选的“在 Linux 中能工作”检查)
这些 Docker 运行器分为两类:- 实时模型运行器:
test:docker:live-models和test:docker:live-gateway仅在仓库 Docker 镜像中运行各自对应的 profile-key 实时测试文件(src/agents/models.profiles.live.test.ts和src/gateway/gateway-models.profiles.live.test.ts),并挂载你的本地配置目录和工作区(如果已挂载,也会 source~/.profile)。对应的本地入口点是test:live:models-profiles和test:live:gateway-profiles。 - Docker 实时运行器默认使用更小的冒烟上限,以便完整的 Docker 扫描保持可行:
test:docker:live-models默认设置OPENCLAW_LIVE_MAX_MODELS=12,而test:docker:live-gateway默认设置OPENCLAW_LIVE_GATEWAY_SMOKE=1、OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8、OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000,以及OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000。当你明确需要更大、更彻底的扫描时,可覆盖这些环境变量。 test:docker:all会先通过test:docker:live-build构建一次实时 Docker 镜像,然后在两个实时 Docker 通道中复用它。- 容器冒烟运行器:
test:docker:openwebui、test:docker:onboard、test:docker:gateway-network、test:docker:mcp-channels和test:docker:plugins会启动一个或多个真实容器,并验证更高层级的集成路径。
- 直接模型:
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) - 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) - 新手引导向导(TTY,完整脚手架):
pnpm test:docker:onboard(脚本:scripts/e2e/onboard-docker.sh) - Gateway 网关网络(两个容器,WS 认证 + 健康检查):
pnpm test:docker:gateway-network(脚本:scripts/e2e/gateway-network-docker.sh) - MCP 渠道桥接(带种子 Gateway 网关 + stdio bridge + 原始 Claude 通知帧冒烟):
pnpm test:docker:mcp-channels(脚本:scripts/e2e/mcp-channels-docker.sh) - 插件(安装冒烟 +
/plugin别名 + Claude bundle 重启语义):pnpm test:docker:plugins(脚本:scripts/e2e/plugins-docker.sh)
.pnpm-store、.worktrees、__openclaw_vitest__,以及应用本地的 .build 或
Gradle 输出目录,因此 Docker 实时运行不会花数分钟去复制
机器专属制品。
它们还会设置 OPENCLAW_SKIP_CHANNELS=1,因此 Gateway 网关实时探针不会在容器内启动
真实的 Telegram / Discord / 等渠道 worker。
test:docker:live-models 仍会运行 pnpm test:live,因此当你需要缩小或排除 Gateway 网关
实时覆盖时,也请一并传入 OPENCLAW_LIVE_GATEWAY_*。
test:docker:openwebui 是一个更高层的兼容性冒烟测试:它会启动一个
启用了 OpenAI 兼容 HTTP 端点的 OpenClaw Gateway 网关容器,
再针对该 Gateway 网关启动一个固定版本的 Open WebUI 容器,通过
Open WebUI 完成登录,验证 /api/models 暴露出 openclaw/default,然后发送一个
真实聊天请求,经过 Open WebUI 的 /api/chat/completions 代理。
首次运行可能明显更慢,因为 Docker 可能需要拉取
Open WebUI 镜像,而 Open WebUI 也可能需要完成自身的冷启动 setup。
该通道需要一个可用的实时模型密钥,而 OPENCLAW_PROFILE_FILE
(默认是 ~/.profile)是在 Docker 化运行中提供该密钥的主要方式。
成功运行会打印一个小型 JSON 负载,例如 { "ok": true, "model": "openclaw/default", ... }。
test:docker:mcp-channels 刻意设计为确定性,不需要
真实的 Telegram、Discord 或 iMessage 账号。它会启动一个带种子的 Gateway 网关
容器,再启动第二个容器来执行 openclaw mcp serve,然后
验证路由后的会话发现、转录读取、附件元数据、
实时事件队列行为、出站发送路由,以及 Claude 风格的渠道 +
权限通知是否通过真实 stdio MCP bridge 发送。通知检查
会直接检查原始 stdio MCP 帧,因此该冒烟测试验证的是
bridge 实际发出的内容,而不仅仅是某个特定客户端 SDK 恰好暴露出的内容。
手动 ACP 自然语言线程冒烟测试(不在 CI 中):
bun scripts/dev/discord-acp-plain-language-smoke.ts --channel <discord-channel-id> ...- 保留此脚本用于回归 / 调试工作流。它未来可能仍会用于 ACP 线程路由验证,因此不要删除它。
OPENCLAW_CONFIG_DIR=...(默认:~/.openclaw)挂载到/home/node/.openclawOPENCLAW_WORKSPACE_DIR=...(默认:~/.openclaw/workspace)挂载到/home/node/.openclaw/workspaceOPENCLAW_PROFILE_FILE=...(默认:~/.profile)挂载到/home/node/.profile,并在运行测试前 sourceOPENCLAW_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_LIVE_REQUIRE_PROFILE_KEYS=1:确保凭证来自 profile store(而不是环境变量)OPENCLAW_OPENWEBUI_MODEL=...:选择 Gateway 网关为 Open WebUI 冒烟测试暴露的模型OPENCLAW_OPENWEBUI_PROMPT=...:覆盖 Open WebUI 冒烟测试使用的 nonce 检查提示词OPENWEBUI_IMAGE=...:覆盖固定的 Open WebUI 镜像标签
文档完整性检查
文档编辑后请运行文档检查: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 网关向导(WS
wizard.start/wizard.next,写入配置 + 强制认证):src/gateway/gateway.test.ts(用例:“runs wizard over ws and writes auth token config”)
智能体可靠性评估(Skills)
我们已经有一些 CI 安全的测试,其行为类似“智能体可靠性评估”:- 通过真实 Gateway 网关 + 智能体循环进行模拟工具调用(
src/gateway/gateway.test.ts)。 - 验证会话接线和配置效果的端到端向导流程(
src/gateway/gateway.test.ts)。
- 决策能力: 当提示词中列出技能时,智能体是否会选择正确的技能(或避免选择无关技能)?
- 合规性: 智能体在使用前是否会读取
SKILL.md,并遵循要求的步骤 / 参数? - 工作流契约: 断言工具顺序、会话历史延续和沙箱边界的多轮场景。
- 使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、技能文件读取和会话接线。
- 一小套聚焦技能的场景(使用 vs 避免、门禁、提示词注入)。
- 仅在 CI 安全套件就位后,再添加可选的实时评估(选择加入、受环境变量控制)。
契约测试(插件和渠道形状)
契约测试用于验证每个已注册插件和渠道都符合其 接口契约。它们会遍历所有已发现的插件,并运行一组 关于形状和行为的断言。默认的pnpm test 单元通道会有意
跳过这些共享接缝和冒烟文件;当你修改共享渠道或提供商表面时,
请显式运行契约命令。
命令
- 所有契约:
pnpm test:contracts - 仅渠道契约:
pnpm test:contracts:channels - 仅提供商契约:
pnpm test:contracts:plugins
渠道契约
位于src/channels/plugins/contracts/*.contract.test.ts:
- plugin - 基本插件形状(id、name、capabilities)
- setup - 设置向导契约
- session-binding - 会话绑定行为
- outbound-payload - 消息负载结构
- inbound - 入站消息处理
- actions - 渠道操作处理器
- threading - 线程 ID 处理
- directory - 目录 / roster API
- group-policy - 群组策略强制执行
提供商状态契约
位于src/plugins/contracts/*.contract.test.ts。
- status - 渠道状态探针
- registry - 插件注册表形状
提供商契约
位于src/plugins/contracts/*.contract.test.ts:
- auth - 认证流程契约
- auth-choice - 认证选择 / 选择逻辑
- catalog - 模型目录 API
- discovery - 插件发现
- loader - 插件加载
- runtime - 提供商运行时
- shape - 插件形状 / 接口
- wizard - 设置向导
何时运行
- 修改 plugin-sdk 导出或子路径后
- 添加或修改渠道或提供商插件后
- 重构插件注册或发现逻辑后
添加回归测试(指导)
当你修复在实时测试中发现的提供商 / 模型问题时:- 如果可能,添加一个 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中添加了新的includeInPlanSecretRef 目标家族,请更新该测试中的classifyTargetClass。该测试会在遇到未分类目标 id 时故意失败,以确保新类别不会被静默跳过。