diff --git a/docs/zh-CN/gateway/configuration-reference.md b/docs/zh-CN/gateway/configuration-reference.md index ce4eada1a..74c13ebdf 100644 --- a/docs/zh-CN/gateway/configuration-reference.md +++ b/docs/zh-CN/gateway/configuration-reference.md @@ -2,67 +2,67 @@ read_when: - 你需要精确到字段级别的配置语义或默认值 - 你正在验证渠道、模型、Gateway 网关或工具配置块 -summary: 核心 OpenClaw 键、默认值以及专用子系统参考链接的 Gateway 网关配置参考 +summary: Gateway 网关配置参考,涵盖 OpenClaw 核心键名、默认值以及指向专用子系统参考文档的链接 title: 配置参考 x-i18n: - generated_at: "2026-04-23T22:57:50Z" + generated_at: "2026-04-23T23:21:48Z" model: gpt-5.4 provider: openai - source_hash: d1ac8dc6955425e3aa5c327f2024b877c1126ea821cccbef2da3a284b92d70ef + source_hash: 8d5bcafbb701c326c027059de03c647eb9b2cf2bb1a543bc91c42b5deafa4378 source_path: gateway/configuration-reference.md workflow: 15 --- -`~/.openclaw/openclaw.json` 的核心配置参考。若需要面向任务的概览,请参见 [配置](/zh-CN/gateway/configuration)。 +`~/.openclaw/openclaw.json` 的核心配置参考。若需面向任务的概览,请参阅 [Configuration](/zh-CN/gateway/configuration)。 -本页涵盖 OpenClaw 的主要配置表面,并在某个子系统拥有自己更深入的参考时提供链接。它**不会**尝试在单页中内联每个由渠道/插件拥有的命令目录,或每个深层记忆/QMD 旋钮。 +本页介绍 OpenClaw 的主要配置面,并在某个子系统拥有更深入的独立参考时提供相应链接。它**不会**尝试在单个页面中内联每个由渠道/插件拥有的命令目录,或每个深层 memory/QMD 调节项。 代码事实来源: - `openclaw config schema` 会打印用于验证和 Control UI 的实时 JSON Schema,并在可用时合并内置/插件/渠道元数据 -- `config.schema.lookup` 会返回一个按路径限定的 schema 节点,用于向下钻取工具 +- `config.schema.lookup` 会返回一个按路径限定的 schema 节点,供下钻工具使用 - `pnpm config:docs:check` / `pnpm config:docs:gen` 会根据当前 schema 表面对配置文档基线哈希进行验证 专用深度参考: -- [记忆配置参考](/zh-CN/reference/memory-config),用于 `agents.defaults.memorySearch.*`、`memory.qmd.*`、`memory.citations`,以及位于 `plugins.entries.memory-core.config.dreaming` 下的 Dreaming 配置 -- [Slash Commands](/zh-CN/tools/slash-commands),用于当前内置 + 内置插件命令目录 -- 各自的渠道/插件页面,用于渠道专属命令表面 +- [Memory configuration reference](/zh-CN/reference/memory-config),适用于 `agents.defaults.memorySearch.*`、`memory.qmd.*`、`memory.citations`,以及位于 `plugins.entries.memory-core.config.dreaming` 下的 Dreaming 配置 +- [Slash Commands](/zh-CN/tools/slash-commands),适用于当前内置 + 内置插件命令目录 +- 渠道特定命令面的所属渠道/插件页面 -配置格式为 **JSON5**(允许注释和尾随逗号)。所有字段都是可选的 —— 省略时,OpenClaw 会使用安全默认值。 +配置格式为 **JSON5**(允许注释和尾随逗号)。所有字段均为可选 —— OpenClaw 在省略时会使用安全的默认值。 --- ## 渠道 -每个渠道在其配置分区存在时都会自动启动(除非 `enabled: false`)。 +每个渠道在其配置段存在时都会自动启动(除非设置了 `enabled: false`)。 ### 私信和群组访问 所有渠道都支持私信策略和群组策略: -| 私信策略 | 行为 | -| ------------------- | -------------------------------------------------------------- | -| `pairing`(默认) | 未知发送者会收到一次性配对码;所有者必须批准 | -| `allowlist` | 仅允许 `allowFrom` 中的发送者(或已配对的允许列表存储) | -| `open` | 允许所有入站私信(要求 `allowFrom: ["*"]`) | -| `disabled` | 忽略所有入站私信 | +| 私信策略 | 行为 | +| ------------------- | ------------------------------------------------ | +| `pairing`(默认) | 未知发送者会收到一次性配对码;必须由所有者批准 | +| `allowlist` | 仅允许 `allowFrom` 中的发送者(或已配对允许存储) | +| `open` | 允许所有传入私信(需要 `allowFrom: ["*"]`) | +| `disabled` | 忽略所有传入私信 | -| 群组策略 | 行为 | -| --------------------- | -------------------------------------------------------- | -| `allowlist`(默认) | 仅允许与已配置允许列表匹配的群组 | -| `open` | 绕过群组允许列表(但仍会应用提及门控) | -| `disabled` | 阻止所有群组/房间消息 | +| 群组策略 | 行为 | +| --------------------- | ---------------------------------------- | +| `allowlist`(默认) | 仅允许与配置的允许列表匹配的群组 | +| `open` | 绕过群组允许列表(仍然适用提及门控) | +| `disabled` | 阻止所有群组/房间消息 | -当提供商的 `groupPolicy` 未设置时,`channels.defaults.groupPolicy` 会设置默认值。 +`channels.defaults.groupPolicy` 会在某个提供商的 `groupPolicy` 未设置时作为默认值。 配对码会在 1 小时后过期。待处理的私信配对请求每个渠道最多 **3 个**。 -如果某个提供商块完全缺失(`channels.` 不存在),运行时群组策略会回退为 `allowlist`(默认拒绝),并在启动时发出警告。 +如果某个提供商配置块完全缺失(即不存在 `channels.`),运行时群组策略会回退为 `allowlist`(失败关闭),并在启动时发出警告。 ### 渠道模型覆盖 -使用 `channels.modelByChannel` 可将特定渠道 ID 固定到某个模型。值接受 `provider/model` 或已配置的模型别名。当会话尚未有模型覆盖时(例如通过 `/model` 设置),会应用该渠道映射。 +使用 `channels.modelByChannel` 可将特定渠道 ID 固定到某个模型。值接受 `provider/model` 或已配置的模型别名。当某个会话尚未具有模型覆盖时(例如通过 `/model` 设置),才会应用此渠道映射。 ```json5 { @@ -85,7 +85,7 @@ x-i18n: ### 渠道默认值和心跳 -使用 `channels.defaults` 为各提供商设置共享的群组策略和心跳行为: +使用 `channels.defaults` 可为各个提供商设置共享的群组策略和心跳行为: ```json5 { @@ -103,15 +103,15 @@ x-i18n: } ``` -- `channels.defaults.groupPolicy`:当提供商级 `groupPolicy` 未设置时使用的回退群组策略。 -- `channels.defaults.contextVisibility`:所有渠道的默认补充上下文可见性模式。取值:`all`(默认,包含所有引用/线程/历史上下文)、`allowlist`(仅包含来自允许列表发送者的上下文)、`allowlist_quote`(与 allowlist 相同,但保留显式引用/回复上下文)。单渠道覆盖:`channels..contextVisibility`。 -- `channels.defaults.heartbeat.showOk`:在心跳输出中包含健康的渠道状态。 +- `channels.defaults.groupPolicy`:当提供商级别的 `groupPolicy` 未设置时的后备群组策略。 +- `channels.defaults.contextVisibility`:所有渠道的默认补充上下文可见性模式。取值:`all`(默认,包含所有引用/线程/历史上下文)、`allowlist`(仅包含来自允许列表发送者的上下文)、`allowlist_quote`(与 allowlist 相同,但保留显式引用/回复上下文)。按渠道覆盖:`channels..contextVisibility`。 +- `channels.defaults.heartbeat.showOk`:在心跳输出中包含健康渠道状态。 - `channels.defaults.heartbeat.showAlerts`:在心跳输出中包含降级/错误状态。 -- `channels.defaults.heartbeat.useIndicator`:渲染紧凑的指示器样式心跳输出。 +- `channels.defaults.heartbeat.useIndicator`:以紧凑的指示器样式渲染心跳输出。 ### WhatsApp -WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在已关联会话时,它会自动启动。 +WhatsApp 通过 Gateway 网关的 web 渠道(Baileys Web)运行。当存在已关联会话时会自动启动。 ```json5 { @@ -122,7 +122,7 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 textChunkLimit: 4000, chunkMode: "length", // length | newline mediaMaxMb: 50, - sendReadReceipts: true, // 蓝色对勾(在自聊模式中为 false) + sendReadReceipts: true, // blue ticks (false in self-chat mode) groups: { "*": { requireMention: true }, }, @@ -162,9 +162,9 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 } ``` -- 出站命令默认使用 `default` 账号(如果存在);否则使用第一个已配置的账号 ID(排序后)。 -- 可选的 `channels.whatsapp.defaultAccount` 会在其匹配某个已配置账号 ID 时,覆盖该回退默认账号选择。 -- 旧版单账号 Baileys auth 目录会由 `openclaw doctor` 迁移到 `whatsapp/default`。 +- 出站命令默认使用账号 `default`;如果不存在,则使用第一个已配置的账号 ID(按排序顺序)。 +- 可选的 `channels.whatsapp.defaultAccount` 可在其匹配某个已配置账号 ID 时,覆盖该后备默认账号选择。 +- 旧版单账号 Baileys 凭证目录会由 `openclaw doctor` 迁移到 `whatsapp/default`。 - 按账号覆盖:`channels.whatsapp.accounts..sendReadReceipts`、`channels.whatsapp.accounts..dmPolicy`、`channels.whatsapp.accounts..allowFrom`。 @@ -200,7 +200,7 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 historyLimit: 50, replyToMode: "first", // off | first | all | batched linkPreview: true, - streaming: "partial", // off | partial | block | progress(默认:off;需显式启用以避免预览编辑速率限制) + streaming: "partial", // off | partial | block | progress (default: off; opt in explicitly to avoid preview-edit rate limits) actions: { reactions: true, sendMessage: true }, reactionNotifications: "own", // off | own | all mediaMaxMb: 100, @@ -223,13 +223,13 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 } ``` -- Bot token:`channels.telegram.botToken` 或 `channels.telegram.tokenFile`(仅限常规文件;拒绝符号链接),默认账号还可回退到 `TELEGRAM_BOT_TOKEN`。 +- Bot token:`channels.telegram.botToken` 或 `channels.telegram.tokenFile`(仅允许常规文件;拒绝符号链接),默认账号还可回退使用 `TELEGRAM_BOT_TOKEN`。 - 可选的 `channels.telegram.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 -- 在多账号设置(2 个及以上账号 ID)中,请设置显式默认值(`channels.telegram.defaultAccount` 或 `channels.telegram.accounts.default`)以避免回退路由;当其缺失或无效时,`openclaw doctor` 会发出警告。 -- `configWrites: false` 会阻止由 Telegram 发起的配置写入(supergroup ID 迁移、`/config set|unset`)。 -- 顶层 `bindings[]` 中 `type: "acp"` 的条目用于为论坛主题配置持久 ACP 绑定(在 `match.peer.id` 中使用规范的 `chatId:topic:topicId`)。字段语义与 [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings) 共享。 -- Telegram 流式预览使用 `sendMessage` + `editMessageText`(在私聊和群聊中都可工作)。 -- 重试策略:参见 [重试策略](/zh-CN/concepts/retry)。 +- 在多账号设置(2 个及以上账号 ID)中,请设置显式默认值(`channels.telegram.defaultAccount` 或 `channels.telegram.accounts.default`)以避免回退路由;当该值缺失或无效时,`openclaw doctor` 会发出警告。 +- `configWrites: false` 会阻止由 Telegram 发起的配置写入(超级群组 ID 迁移、`/config set|unset`)。 +- 顶层 `bindings[]` 中类型为 `type: "acp"` 的条目用于为论坛话题配置持久 ACP 绑定(在 `match.peer.id` 中使用规范形式 `chatId:topic:topicId`)。字段语义与 [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings) 共享。 +- Telegram 流式预览使用 `sendMessage` + `editMessageText`(可在私聊和群聊中工作)。 +- 重试策略:参见 [Retry policy](/zh-CN/concepts/retry)。 ### Discord @@ -284,7 +284,7 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 historyLimit: 20, textChunkLimit: 2000, chunkMode: "length", // length | newline - streaming: "off", // off | partial | block | progress(在 Discord 上,progress 会映射为 partial) + streaming: "off", // off | partial | block | progress (progress maps to partial on Discord) maxLinesPerMessage: 17, ui: { components: { @@ -295,7 +295,7 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 enabled: true, idleHours: 24, maxAgeHours: 0, - spawnSubagentSessions: false, // 对 `sessions_spawn({ thread: true })` 选择性启用 + spawnSubagentSessions: false, // opt-in for sessions_spawn({ thread: true }) }, voice: { enabled: true, @@ -331,36 +331,36 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 } ``` -- Token:`channels.discord.token`,默认账号还可回退到 `DISCORD_BOT_TOKEN`。 -- 直接出站调用如果提供了显式的 Discord `token`,则该调用会使用该 token;账号级重试/策略设置仍来自当前运行时快照中选定的账号。 +- Token:`channels.discord.token`,默认账号还可回退使用 `DISCORD_BOT_TOKEN`。 +- 提供显式 Discord `token` 的直接出站调用会使用该 token 执行调用;账号重试/策略设置仍然来自活动运行时快照中所选账号。 - 可选的 `channels.discord.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 -- 投递目标请使用 `user:`(私信)或 `channel:`(服务器频道);裸数字 ID 会被拒绝。 -- Guild slug 会转换为小写,并将空格替换为 `-`;频道键使用 slug 化后的名称(不带 `#`)。优先使用 guild ID。 -- 默认会忽略由机器人发送的消息。`allowBots: true` 可启用它们;使用 `allowBots: "mentions"` 则仅接受提及该机器人的机器人消息(机器人自己的消息仍会被过滤)。 -- `channels.discord.guilds..ignoreOtherMentions`(以及频道级覆盖)会丢弃提及了其他用户或角色、但未提及机器人的消息(不包括 @everyone/@here)。 -- `maxLinesPerMessage`(默认 17)即使消息未超过 2000 个字符,也会拆分过高的消息。 +- 使用 `user:`(私信)或 `channel:`(服务器频道)作为投递目标;不带前缀的纯数字 ID 会被拒绝。 +- 服务器 slug 为小写,空格替换为 `-`;频道键使用 slug 化后的名称(不含 `#`)。优先使用服务器 ID。 +- 默认会忽略由机器人编写的消息。`allowBots: true` 会启用它们;使用 `allowBots: "mentions"` 则只接受提及机器人的机器人消息(机器人自己的消息仍会被过滤)。 +- `channels.discord.guilds..ignoreOtherMentions`(以及频道级覆盖)会丢弃提及其他用户或角色、但未提及机器人的消息(不包括 @everyone/@here)。 +- `maxLinesPerMessage`(默认 17)会拆分过高的消息,即使其未超过 2000 个字符。 - `channels.discord.threadBindings` 控制 Discord 线程绑定路由: - - `enabled`:线程绑定会话功能的 Discord 覆盖(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`,以及绑定投递/路由) - - `idleHours`:以小时为单位的 Discord 不活动自动取消聚焦覆盖(`0` 表示禁用) - - `maxAgeHours`:以小时为单位的 Discord 硬性最大时长覆盖(`0` 表示禁用) - - `spawnSubagentSessions`:为 `sessions_spawn({ thread: true })` 自动创建/绑定线程的选择性启用开关 -- 顶层 `bindings[]` 中 `type: "acp"` 的条目用于为频道和线程配置持久 ACP 绑定(在 `match.peer.id` 中使用频道/线程 ID)。字段语义与 [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings) 共享。 + - `enabled`:用于线程绑定会话功能的 Discord 覆盖(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`,以及绑定投递/路由) + - `idleHours`:用于不活动自动取消聚焦的 Discord 覆盖,单位为小时(`0` 表示禁用) + - `maxAgeHours`:用于硬性最大存续时间的 Discord 覆盖,单位为小时(`0` 表示禁用) + - `spawnSubagentSessions`:为 `sessions_spawn({ thread: true })` 自动创建/绑定线程启用的选择加入开关 +- 顶层 `bindings[]` 中类型为 `type: "acp"` 的条目用于为频道和线程配置持久 ACP 绑定(在 `match.peer.id` 中使用频道/线程 ID)。字段语义与 [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings) 共享。 - `channels.discord.ui.components.accentColor` 为 Discord components v2 容器设置强调色。 - `channels.discord.voice` 启用 Discord 语音频道对话,以及可选的自动加入 + TTS 覆盖。 -- `channels.discord.voice.daveEncryption` 和 `channels.discord.voice.decryptionFailureTolerance` 会透传给 `@discordjs/voice` 的 DAVE 选项(默认分别为 `true` 和 `24`)。 -- OpenClaw 还会在重复解密失败后,通过离开/重新加入语音会话来尝试恢复语音接收。 -- `channels.discord.streaming` 是规范的流式传输模式键。旧版 `streamMode` 和布尔型 `streaming` 值会自动迁移。 -- `channels.discord.autoPresence` 会将运行时可用性映射到机器人在线状态(健康 => online,降级 => idle,耗尽 => dnd),并允许可选的状态文本覆盖。 -- `channels.discord.dangerouslyAllowNameMatching` 会重新启用可变名称/tag 匹配(破窗应急兼容模式)。 -- `channels.discord.execApprovals`:Discord 原生 exec 审批投递和审批者授权。 - - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当能从 `approvers` 或 `commands.ownerAllowFrom` 解析出审批者时,exec 审批会激活。 +- `channels.discord.voice.daveEncryption` 和 `channels.discord.voice.decryptionFailureTolerance` 会透传到 `@discordjs/voice` 的 DAVE 选项(默认分别为 `true` 和 `24`)。 +- OpenClaw 还会在重复发生解密失败后,通过离开/重新加入语音会话来尝试恢复语音接收。 +- `channels.discord.streaming` 是规范的流式模式键。旧版 `streamMode` 和布尔型 `streaming` 值会被自动迁移。 +- `channels.discord.autoPresence` 会将运行时可用性映射到机器人在线状态(healthy => online,degraded => idle,exhausted => dnd),并允许可选的状态文本覆盖。 +- `channels.discord.dangerouslyAllowNameMatching` 会重新启用可变名称/tag 匹配(破玻璃兼容模式)。 +- `channels.discord.execApprovals`:原生 Discord exec 审批投递和审批人授权。 + - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当可从 `approvers` 或 `commands.ownerAllowFrom` 解析出审批人时,会激活 exec 审批。 - `approvers`:允许批准 exec 请求的 Discord 用户 ID。省略时回退到 `commands.ownerAllowFrom`。 - - `agentFilter`:可选的智能体 ID 允许列表。省略时会为所有智能体转发审批。 - - `sessionFilter`:可选的会话键模式(子串或正则)。 - - `target`:发送审批提示的位置。`"dm"`(默认)发送到审批者私信,`"channel"` 发送到原始频道,`"both"` 同时发送到两者。当目标包含 `"channel"` 时,按钮仅对已解析出的审批者可用。 - - `cleanupAfterResolve`:为 `true` 时,在批准、拒绝或超时后删除审批私信。 + - `agentFilter`:可选的智能体 ID 允许列表。省略时会转发所有智能体的审批。 + - `sessionFilter`:可选的会话键模式(子串或正则表达式)。 + - `target`:发送审批提示的位置。`"dm"`(默认)发送到审批人私信,`"channel"` 发送到发起频道,`"both"` 同时发送到两者。当目标包含 `"channel"` 时,按钮仅可由已解析的审批人使用。 + - `cleanupAfterResolve`:当为 `true` 时,在批准、拒绝或超时后删除审批私信。 -**回应通知模式:** `off`(无)、`own`(机器人的消息,默认)、`all`(所有消息)、`allowlist`(所有消息中来自 `guilds..users` 的消息)。 +**反应通知模式:** `off`(无)、`own`(机器人的消息,默认)、`all`(所有消息)、`allowlist`(所有消息中来自 `guilds..users` 的用户)。 ### Google Chat @@ -391,11 +391,11 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 } ``` -- 服务账号 JSON:内联(`serviceAccount`)或基于文件(`serviceAccountFile`)。 +- 服务账号 JSON:支持内联(`serviceAccount`)或基于文件(`serviceAccountFile`)。 - 也支持服务账号 SecretRef(`serviceAccountRef`)。 - 环境变量回退:`GOOGLE_CHAT_SERVICE_ACCOUNT` 或 `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE`。 -- 投递目标请使用 `spaces/` 或 `users/`。 -- `channels.googlechat.dangerouslyAllowNameMatching` 会重新启用可变电子邮件主体匹配(破窗应急兼容模式)。 +- 使用 `spaces/` 或 `users/` 作为投递目标。 +- `channels.googlechat.dangerouslyAllowNameMatching` 会重新启用可变电子邮件主体匹配(破玻璃兼容模式)。 ### Slack @@ -447,7 +447,7 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 chunkMode: "length", streaming: { mode: "partial", // off | partial | block | progress - nativeTransport: true, // 当 mode=partial 时使用 Slack 原生流式传输 API + nativeTransport: true, // use Slack native streaming API when mode=partial }, mediaMaxMb: 20, execApprovals: { @@ -464,28 +464,32 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当存在 - **Socket mode** 需要同时提供 `botToken` 和 `appToken`(默认账号环境变量回退为 `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`)。 - **HTTP mode** 需要 `botToken` 加 `signingSecret`(位于根级或按账号配置)。 -- `botToken`、`appToken`、`signingSecret` 和 `userToken` 接受纯文本字符串或 SecretRef 对象。 -- Slack 账号快照会暴露按凭证区分的来源/状态字段,例如 `botTokenSource`、`botTokenStatus`、`appTokenStatus`,以及在 HTTP 模式下的 `signingSecretStatus`。`configured_unavailable` 表示该账号通过 SecretRef 配置,但当前命令/运行时路径无法解析出密钥值。 +- `botToken`、`appToken`、`signingSecret` 和 `userToken` 接受明文 + 字符串或 SecretRef 对象。 +- Slack 账号快照会公开按凭证划分的来源/状态字段,例如 + `botTokenSource`、`botTokenStatus`、`appTokenStatus`,以及在 HTTP 模式下的 + `signingSecretStatus`。`configured_unavailable` 表示该账号是通过 SecretRef + 配置的,但当前命令/运行时路径无法解析该 secret 值。 - `configWrites: false` 会阻止由 Slack 发起的配置写入。 - 可选的 `channels.slack.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 -- `channels.slack.streaming.mode` 是规范的 Slack 流式传输模式键。`channels.slack.streaming.nativeTransport` 控制 Slack 的原生流式传输方式。旧版 `streamMode`、布尔型 `streaming` 和 `nativeStreaming` 值会自动迁移。 -- 投递目标请使用 `user:`(私信)或 `channel:`。 +- `channels.slack.streaming.mode` 是规范的 Slack 流式模式键。`channels.slack.streaming.nativeTransport` 控制 Slack 的原生流式传输。旧版 `streamMode`、布尔型 `streaming` 和 `nativeStreaming` 值会被自动迁移。 +- 使用 `user:`(私信)或 `channel:` 作为投递目标。 -**回应通知模式:** `off`、`own`(默认)、`all`、`allowlist`(来自 `reactionAllowlist`)。 +**反应通知模式:** `off`、`own`(默认)、`all`、`allowlist`(来自 `reactionAllowlist`)。 -**线程会话隔离:** `thread.historyScope` 可设为按线程(默认)或在频道间共享。`thread.inheritParent` 会将父频道转录复制到新线程。 +**线程会话隔离:** `thread.historyScope` 可设为按线程(默认)或在频道内共享。`thread.inheritParent` 会将父频道转录复制到新线程。 -- Slack 原生流式传输加上 Slack 助手样式的“正在输入...”线程状态需要一个回复线程目标。顶层私信默认保持在线程外,因此它们会使用 `typingReaction` 或普通投递,而不是线程样式预览。 -- `typingReaction` 会在回复运行期间临时给入站 Slack 消息添加一个回应,并在完成后移除。请使用 Slack emoji 简码,例如 `"hourglass_flowing_sand"`。 -- `channels.slack.execApprovals`:Slack 原生 exec 审批投递和审批者授权。其 schema 与 Discord 相同:`enabled`(`true`/`false`/`"auto"`)、`approvers`(Slack 用户 ID)、`agentFilter`、`sessionFilter` 和 `target`(`"dm"`、`"channel"` 或 `"both"`)。 +- Slack 原生流式传输以及 Slack 助手风格的“正在输入...”线程状态需要回复线程目标。顶层私信默认保持非线程,因此会使用 `typingReaction` 或常规投递,而不是线程样式预览。 +- `typingReaction` 会在回复运行期间为传入的 Slack 消息添加一个临时反应,并在完成后移除。请使用 Slack emoji 简码,例如 `"hourglass_flowing_sand"`。 +- `channels.slack.execApprovals`:原生 Slack exec 审批投递和审批人授权。其 schema 与 Discord 相同:`enabled`(`true`/`false`/`"auto"`)、`approvers`(Slack 用户 ID)、`agentFilter`、`sessionFilter` 和 `target`(`"dm"`、`"channel"` 或 `"both"`)。 -| 操作组 | 默认值 | 说明 | -| ------------ | ------- | -------------------- | -| reactions | 启用 | 添加回应 + 列出回应 | -| messages | 启用 | 读取/发送/编辑/删除 | -| pins | 启用 | 固定/取消固定/列出 | -| memberInfo | 启用 | 成员信息 | -| emojiList | 启用 | 自定义 emoji 列表 | +| 操作组 | 默认值 | 说明 | +| ---------- | ------- | -------------------- | +| reactions | 启用 | 反应 + 列出反应 | +| messages | 启用 | 读取/发送/编辑/删除 | +| pins | 启用 | 置顶/取消置顶/列出 | +| memberInfo | 启用 | 成员信息 | +| emojiList | 启用 | 自定义 emoji 列表 | ### Mattermost @@ -506,10 +510,10 @@ Mattermost 作为插件提供:`openclaw plugins install @openclaw/mattermost` "team-channel-id": { requireMention: false }, }, commands: { - native: true, // 选择性启用 + native: true, // opt-in nativeSkills: true, callbackPath: "/api/channels/mattermost/command", - // 面向反向代理/公网部署的可选显式 URL + // Optional explicit URL for reverse-proxy/public deployments callbackUrl: "https://gateway.example.com/api/channels/mattermost/command", }, textChunkLimit: 4000, @@ -519,20 +523,20 @@ Mattermost 作为插件提供:`openclaw plugins install @openclaw/mattermost` } ``` -聊天模式:`oncall`(在 @ 提及时回复,默认)、`onmessage`(每条消息都回复)、`onchar`(以触发前缀开头的消息)。 +聊天模式:`oncall`(在 @ 提及时响应,默认)、`onmessage`(每条消息都响应)、`onchar`(以触发前缀开头的消息)。 启用 Mattermost 原生命令时: -- `commands.callbackPath` 必须是路径(例如 `/api/channels/mattermost/command`),而不是完整 URL。 -- `commands.callbackUrl` 必须解析到 OpenClaw Gateway 网关端点,并且 Mattermost 服务器可以访问该地址。 -- 原生斜杠命令回调使用 Mattermost 在注册斜杠命令期间返回的按命令 token 进行认证。如果注册失败或没有命令被激活,OpenClaw 会拒绝回调,并返回 +- `commands.callbackPath` 必须是一个路径(例如 `/api/channels/mattermost/command`),不能是完整 URL。 +- `commands.callbackUrl` 必须解析到 OpenClaw Gateway 网关端点,并且 Mattermost 服务器可访问。 +- 原生斜杠命令回调会使用 Mattermost 在斜杠命令注册期间返回的按命令划分 token 进行认证。如果注册失败或未激活任何命令,OpenClaw 会拒绝回调,并返回 `Unauthorized: invalid command token.`。 -- 对于私有/tailnet/内部回调主机,Mattermost 可能要求 - `ServiceSettings.AllowedUntrustedInternalConnections` 包含该回调主机/域名。 +- 对于私有/tailnet/内网回调主机,Mattermost 可能要求 + `ServiceSettings.AllowedUntrustedInternalConnections` 包含回调主机/域名。 请使用主机/域名值,而不是完整 URL。 - `channels.mattermost.configWrites`:允许或拒绝由 Mattermost 发起的配置写入。 - `channels.mattermost.requireMention`:在频道中回复前要求 `@mention`。 -- `channels.mattermost.groups..requireMention`:按频道覆盖提及门控(默认值使用 `"*"`)。 +- `channels.mattermost.groups..requireMention`:按频道覆盖提及门控(`"*"` 表示默认值)。 - 可选的 `channels.mattermost.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 ### Signal @@ -542,7 +546,7 @@ Mattermost 作为插件提供:`openclaw plugins install @openclaw/mattermost` channels: { signal: { enabled: true, - account: "+15555550123", // 可选账号绑定 + account: "+15555550123", // optional account binding dmPolicy: "pairing", allowFrom: ["+15551234567", "uuid:123e4567-e89b-12d3-a456-426614174000"], configWrites: true, @@ -554,9 +558,9 @@ Mattermost 作为插件提供:`openclaw plugins install @openclaw/mattermost` } ``` -**回应通知模式:** `off`、`own`(默认)、`all`、`allowlist`(来自 `reactionAllowlist`)。 +**反应通知模式:** `off`、`own`(默认)、`all`、`allowlist`(来自 `reactionAllowlist`)。 -- `channels.signal.account`:将渠道启动固定到某个特定的 Signal 账号身份。 +- `channels.signal.account`:将渠道启动固定到特定的 Signal 账号身份。 - `channels.signal.configWrites`:允许或拒绝由 Signal 发起的配置写入。 - 可选的 `channels.signal.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 @@ -570,8 +574,8 @@ BlueBubbles 是推荐的 iMessage 路径(由插件支持,配置位于 `chann bluebubbles: { enabled: true, dmPolicy: "pairing", - // serverUrl、password、webhookPath、群组控制和高级操作: - // 参见 /channels/bluebubbles + // serverUrl, password, webhookPath, group controls, and advanced actions: + // see /channels/bluebubbles }, }, } @@ -579,12 +583,12 @@ BlueBubbles 是推荐的 iMessage 路径(由插件支持,配置位于 `chann - 此处涵盖的核心键路径:`channels.bluebubbles`、`channels.bluebubbles.dmPolicy`。 - 可选的 `channels.bluebubbles.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 -- 顶层 `bindings[]` 中 `type: "acp"` 的条目可以将 BlueBubbles 对话绑定到持久 ACP 会话。在 `match.peer.id` 中使用 BlueBubbles handle 或目标字符串(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义: [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings)。 +- 顶层 `bindings[]` 中类型为 `type: "acp"` 的条目可将 BlueBubbles 会话绑定到持久 ACP 会话。在 `match.peer.id` 中使用 BlueBubbles handle 或目标字符串(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义: [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings)。 - 完整的 BlueBubbles 渠道配置记录在 [BlueBubbles](/zh-CN/channels/bluebubbles) 中。 ### iMessage -OpenClaw 会生成 `imsg rpc`(通过 stdio 的 JSON-RPC)。不需要守护进程或端口。 +OpenClaw 会启动 `imsg rpc`(通过 stdio 的 JSON-RPC)。不需要守护进程或端口。 ```json5 { @@ -610,13 +614,13 @@ OpenClaw 会生成 `imsg rpc`(通过 stdio 的 JSON-RPC)。不需要守护 - 可选的 `channels.imessage.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 -- 需要对 Messages 数据库授予完全磁盘访问权限。 +- 需要对 Messages 数据库授予完整磁盘访问权限。 - 优先使用 `chat_id:` 目标。使用 `imsg chats --limit 20` 列出聊天。 -- `cliPath` 可以指向 SSH 包装器;设置 `remoteHost`(`host` 或 `user@host`)以便通过 SCP 获取附件。 -- `attachmentRoots` 和 `remoteAttachmentRoots` 会限制入站附件路径(默认值:`/Users/*/Library/Messages/Attachments`)。 +- `cliPath` 可以指向 SSH 包装器;设置 `remoteHost`(`host` 或 `user@host`)以通过 SCP 获取附件。 +- `attachmentRoots` 和 `remoteAttachmentRoots` 用于限制传入附件路径(默认值:`/Users/*/Library/Messages/Attachments`)。 - SCP 使用严格主机密钥检查,因此请确保中继主机密钥已存在于 `~/.ssh/known_hosts` 中。 - `channels.imessage.configWrites`:允许或拒绝由 iMessage 发起的配置写入。 -- 顶层 `bindings[]` 中 `type: "acp"` 的条目可以将 iMessage 对话绑定到持久 ACP 会话。在 `match.peer.id` 中使用标准化 handle 或显式聊天目标(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义: [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings)。 +- 顶层 `bindings[]` 中类型为 `type: "acp"` 的条目可将 iMessage 会话绑定到持久 ACP 会话。在 `match.peer.id` 中使用规范化 handle 或显式聊天目标(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义: [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings)。 @@ -661,17 +665,17 @@ Matrix 由插件支持,配置位于 `channels.matrix` 下。 - Token 认证使用 `accessToken`;密码认证使用 `userId` + `password`。 - `channels.matrix.proxy` 会通过显式 HTTP(S) 代理路由 Matrix HTTP 流量。命名账号可通过 `channels.matrix.accounts..proxy` 覆盖它。 -- `channels.matrix.network.dangerouslyAllowPrivateNetwork` 允许私有/内部 homeserver。`proxy` 与这个网络选择性启用是相互独立的控制项。 +- `channels.matrix.network.dangerouslyAllowPrivateNetwork` 允许私有/内部 homeserver。`proxy` 和此网络选择加入是彼此独立的控制项。 - `channels.matrix.defaultAccount` 在多账号设置中选择首选账号。 -- `channels.matrix.autoJoin` 默认值为 `off`,因此受邀请的房间和新的私信式邀请会被忽略,直到你设置 `autoJoin: "allowlist"` 并配合 `autoJoinAllowlist`,或设置 `autoJoin: "always"`。 -- `channels.matrix.execApprovals`:Matrix 原生 exec 审批投递和审批者授权。 - - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当能从 `approvers` 或 `commands.ownerAllowFrom` 解析出审批者时,exec 审批会激活。 +- `channels.matrix.autoJoin` 默认为 `off`,因此受邀房间和新的私信式邀请会被忽略,直到你设置 `autoJoin: "allowlist"` 并搭配 `autoJoinAllowlist`,或设置 `autoJoin: "always"`。 +- `channels.matrix.execApprovals`:原生 Matrix exec 审批投递和审批人授权。 + - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当可从 `approvers` 或 `commands.ownerAllowFrom` 解析出审批人时,会激活 exec 审批。 - `approvers`:允许批准 exec 请求的 Matrix 用户 ID(例如 `@owner:example.org`)。 - - `agentFilter`:可选的智能体 ID 允许列表。省略时会为所有智能体转发审批。 - - `sessionFilter`:可选的会话键模式(子串或正则)。 - - `target`:发送审批提示的位置。`"dm"`(默认)、`"channel"`(原始房间)或 `"both"`。 + - `agentFilter`:可选的智能体 ID 允许列表。省略时会转发所有智能体的审批。 + - `sessionFilter`:可选的会话键模式(子串或正则表达式)。 + - `target`:发送审批提示的位置。`"dm"`(默认)、`"channel"`(发起房间)或 `"both"`。 - 按账号覆盖:`channels.matrix.accounts..execApprovals`。 -- `channels.matrix.dm.sessionScope` 控制 Matrix 私信如何归组到会话中:`per-user`(默认)按路由对端共享,而 `per-room` 会隔离每个私信房间。 +- `channels.matrix.dm.sessionScope` 控制 Matrix 私信如何归并为会话:`per-user`(默认)按路由对端共享,而 `per-room` 会隔离每个私信房间。 - Matrix 状态探测和实时目录查找使用与运行时流量相同的代理策略。 - 完整的 Matrix 配置、目标规则和设置示例记录在 [Matrix](/zh-CN/channels/matrix) 中。 @@ -685,8 +689,8 @@ Microsoft Teams 由插件支持,配置位于 `channels.msteams` 下。 msteams: { enabled: true, configWrites: true, - // appId、appPassword、tenantId、webhook、团队/频道策略: - // 参见 /channels/msteams + // appId, appPassword, tenantId, webhook, team/channel policies: + // see /channels/msteams }, }, } @@ -720,11 +724,11 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 - 此处涵盖的核心键路径:`channels.irc`、`channels.irc.dmPolicy`、`channels.irc.configWrites`、`channels.irc.nickserv.*`。 - 可选的 `channels.irc.defaultAccount` 会在其匹配某个已配置账号 ID 时覆盖默认账号选择。 -- 完整的 IRC 渠道配置(host/port/TLS/channels/allowlists/mention gating)记录在 [IRC](/zh-CN/channels/irc) 中。 +- 完整的 IRC 渠道配置(host/port/TLS/channels/allowlists/提及门控)记录在 [IRC](/zh-CN/channels/irc) 中。 ### 多账号(所有渠道) -为每个渠道运行多个账号(每个账号都有自己的 `accountId`): +在每个渠道中运行多个账号(每个都有自己的 `accountId`): ```json5 { @@ -745,28 +749,28 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 } ``` -- 当省略 `accountId` 时,使用 `default`(CLI + 路由)。 -- 环境变量 token 仅适用于**默认**账号。 -- 基础渠道设置适用于所有账号,除非某个账号单独覆盖。 -- 使用 `bindings[].match.accountId` 将每个账号路由到不同的智能体。 -- 如果你在仍处于单账号顶层渠道配置的情况下,通过 `openclaw channels add`(或渠道新手引导)添加非默认账号,OpenClaw 会先将按账号范围的顶层单账号值提升到渠道账号映射中,以便原账号继续工作。大多数渠道会将其移到 `channels..accounts.default`;Matrix 则可保留现有匹配的命名/default 目标。 -- 现有仅限渠道的绑定(无 `accountId`)仍会匹配默认账号;按账号范围的绑定仍然是可选的。 -- `openclaw doctor --fix` 也会通过将按账号范围的顶层单账号值移动到为该渠道选择的提升账号中来修复混合形状。大多数渠道使用 `accounts.default`;Matrix 则可保留现有匹配的命名/default 目标。 +- 省略 `accountId` 时会使用 `default`(CLI + 路由)。 +- 环境变量 token 仅适用于 **default** 账号。 +- 基础渠道设置会应用于所有账号,除非在账号级别覆盖。 +- 使用 `bindings[].match.accountId` 可将每个账号路由到不同的智能体。 +- 如果你在仍使用单账号顶层渠道配置时,通过 `openclaw channels add`(或渠道新手引导)添加一个非默认账号,OpenClaw 会先将按账号划分的顶层单账号值提升到渠道账号映射中,以便原始账号继续工作。多数渠道会将这些值移至 `channels..accounts.default`;而 Matrix 则可以改为保留现有匹配的命名/default 目标。 +- 现有仅按渠道生效的绑定(无 `accountId`)将继续匹配默认账号;按账号划分的绑定仍然是可选的。 +- `openclaw doctor --fix` 也会通过将按账号划分的顶层单账号值移入该渠道选定的提升后账号,来修复混合形态。多数渠道使用 `accounts.default`;而 Matrix 则可以改为保留现有匹配的命名/default 目标。 -### 其他渠道插件 +### 其他插件渠道 -许多渠道插件以 `channels.` 形式配置,并在各自专属的渠道页面中记录(例如 Feishu、Matrix、LINE、Nostr、Zalo、Nextcloud Talk、Synology Chat 和 Twitch)。 -查看完整渠道索引:[Channels](/zh-CN/channels)。 +许多插件渠道都配置为 `channels.`,并记录在各自专用的渠道页面中(例如 Feishu、Matrix、LINE、Nostr、Zalo、Nextcloud Talk、Synology Chat 和 Twitch)。 +请参阅完整渠道索引:[Channels](/zh-CN/channels)。 ### 群聊提及门控 -群组消息默认**要求提及**(元数据提及或安全 regex 模式)。适用于 WhatsApp、Telegram、Discord、Google Chat 和 iMessage 群聊。 +群组消息默认 **需要提及**(元数据提及或安全正则模式)。适用于 WhatsApp、Telegram、Discord、Google Chat 和 iMessage 群聊。 **提及类型:** -- **元数据提及**:原生平台 @ 提及。在 WhatsApp 自聊模式中会被忽略。 -- **文本模式**:位于 `agents.list[].groupChat.mentionPatterns` 中的安全 regex 模式。无效模式和不安全的嵌套重复会被忽略。 -- 仅当能检测到提及时(原生提及或至少一个模式)才会强制执行提及门控。 +- **元数据提及**:原生平台 @ 提及。在 WhatsApp 自聊模式下会被忽略。 +- **文本模式**:位于 `agents.list[].groupChat.mentionPatterns` 中的安全正则模式。无效模式和不安全的嵌套重复会被忽略。 +- 仅当能够检测到提及时才会强制执行提及门控(原生提及或至少一个模式)。 ```json5 { @@ -779,9 +783,9 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 } ``` -`messages.groupChat.historyLimit` 设置全局默认值。渠道可通过 `channels..historyLimit`(或按账号)覆盖。设置为 `0` 可禁用。 +`messages.groupChat.historyLimit` 设置全局默认值。各渠道可通过 `channels..historyLimit`(或按账号)覆盖。设置为 `0` 可禁用。 -#### 私信历史记录限制 +#### 私信历史限制 ```json5 { @@ -796,13 +800,13 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 } ``` -解析顺序:按私信覆盖 → 提供商默认值 → 不限制(全部保留)。 +解析顺序:按私信覆盖 → 提供商默认值 → 不限制(保留全部)。 支持:`telegram`、`whatsapp`、`discord`、`slack`、`signal`、`imessage`、`msteams`。 #### 自聊模式 -将你自己的号码包含在 `allowFrom` 中即可启用自聊模式(忽略原生 @ 提及,仅响应文本模式): +将你自己的号码加入 `allowFrom` 以启用自聊模式(忽略原生 @ 提及,仅响应文本模式): ```json5 { @@ -823,21 +827,21 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 } ``` -### 命令(聊天命令处理) +### Commands(聊天命令处理) ```json5 { commands: { - native: "auto", // 在支持时注册原生命令 - nativeSkills: "auto", // 在支持时注册原生 Skills 命令 - text: true, // 解析聊天消息中的 /commands - bash: false, // 允许 !(别名:/bash) + native: "auto", // register native commands when supported + nativeSkills: "auto", // register native skill commands when supported + text: true, // parse /commands in chat messages + bash: false, // allow ! (alias: /bash) bashForegroundMs: 2000, - config: false, // 允许 /config - mcp: false, // 允许 /mcp - plugins: false, // 允许 /plugins - debug: false, // 允许 /debug - restart: true, // 允许 /restart + gateway restart 工具 + config: false, // allow /config + mcp: false, // allow /mcp + plugins: false, // allow /plugins + debug: false, // allow /debug + restart: true, // allow /restart + gateway restart tool ownerAllowFrom: ["discord:123456789012345678"], ownerDisplay: "raw", // raw | hash ownerDisplaySecret: "${OWNER_ID_HASH_SECRET}", @@ -852,32 +856,32 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 -- 此块用于配置命令表面。有关当前内置 + 内置插件命令目录,请参见 [Slash Commands](/zh-CN/tools/slash-commands)。 -- 本页是**配置键参考**,而不是完整命令目录。诸如 QQ Bot `/bot-ping` `/bot-help` `/bot-logs`、LINE `/card`、device-pair `/pair`、记忆 `/dreaming`、phone-control `/phone` 和 Talk `/voice` 等由渠道/插件拥有的命令,记录在其渠道/插件页面以及 [Slash Commands](/zh-CN/tools/slash-commands) 中。 -- 文本命令必须是带有前导 `/` 的**独立**消息。 -- `native: "auto"` 会为 Discord/Telegram 开启原生命令,而保持 Slack 关闭。 -- `nativeSkills: "auto"` 会为 Discord/Telegram 开启原生 Skills 命令,而保持 Slack 关闭。 -- 按渠道覆盖:`channels.discord.commands.native`(bool 或 `"auto"`)。`false` 会清除先前已注册的命令。 -- 使用 `channels..commands.nativeSkills` 按渠道覆盖原生 Skills 命令注册。 -- `channels.telegram.customCommands` 会添加额外的 Telegram 机器人菜单项。 -- `bash: true` 会为宿主 shell 启用 `! `。要求 `tools.elevated.enabled`,且发送者位于 `tools.elevated.allowFrom.` 中。 -- `config: true` 会启用 `/config`(读取/写入 `openclaw.json`)。对于 Gateway 网关 `chat.send` 客户端,持久化的 `/config set|unset` 写入还需要 `operator.admin`;只读的 `/config show` 对普通写作用域 operator 客户端仍然可用。 -- `mcp: true` 会启用 `/mcp`,用于 `mcp.servers` 下由 OpenClaw 管理的 MCP 服务器配置。 -- `plugins: true` 会启用 `/plugins`,用于插件发现、安装以及启用/禁用控制。 -- `channels..configWrites` 会按渠道控制配置变更(默认:true)。 -- 对于多账号渠道,`channels..accounts..configWrites` 也会控制以该账号为目标的写入(例如 `/allowlist --config --account ` 或 `/config set channels..accounts....`)。 +- 此配置块用于配置命令面。当前内置 + 内置插件命令目录,请参阅 [Slash Commands](/zh-CN/tools/slash-commands)。 +- 本页是**配置键参考**,不是完整的命令目录。诸如 QQ Bot `/bot-ping` `/bot-help` `/bot-logs`、LINE `/card`、device-pair `/pair`、memory `/dreaming`、phone-control `/phone` 和 Talk `/voice` 等由渠道/插件拥有的命令,记录在各自的渠道/插件页面以及 [Slash Commands](/zh-CN/tools/slash-commands) 中。 +- 文本命令必须是带前导 `/` 的**独立**消息。 +- `native: "auto"` 会为 Discord/Telegram 打开原生命令,而对 Slack 保持关闭。 +- `nativeSkills: "auto"` 会为 Discord/Telegram 打开原生 Skills 命令,而对 Slack 保持关闭。 +- 按渠道覆盖:`channels.discord.commands.native`(布尔值或 `"auto"`)。`false` 会清除先前已注册的命令。 +- 使用 `channels..commands.nativeSkills` 可按渠道覆盖原生 Skills 注册。 +- `channels.telegram.customCommands` 可添加额外的 Telegram 机器人菜单项。 +- `bash: true` 会为主机 shell 启用 `! `。要求 `tools.elevated.enabled` 已启用,且发送者位于 `tools.elevated.allowFrom.` 中。 +- `config: true` 会启用 `/config`(读取/写入 `openclaw.json`)。对于 Gateway 网关 `chat.send` 客户端,持久化 `/config set|unset` 写入还需要 `operator.admin`;只读的 `/config show` 对普通写作用域的 operator 客户端仍然可用。 +- `mcp: true` 会为 `mcp.servers` 下由 OpenClaw 管理的 MCP 服务器配置启用 `/mcp`。 +- `plugins: true` 会启用 `/plugins`,用于插件发现、安装和启用/禁用控制。 +- `channels..configWrites` 控制每个渠道是否允许配置变更(默认:true)。 +- 对于多账号渠道,`channels..accounts..configWrites` 也会控制针对该账号的写入(例如 `/allowlist --config --account ` 或 `/config set channels..accounts....`)。 - `restart: false` 会禁用 `/restart` 和 Gateway 网关重启工具操作。默认值:`true`。 - `ownerAllowFrom` 是 owner 专用命令/工具的显式 owner 允许列表。它与 `allowFrom` 分开。 -- `ownerDisplay: "hash"` 会在系统提示词中对 owner ID 进行哈希。设置 `ownerDisplaySecret` 可控制哈希。 -- `allowFrom` 是按提供商划分的。设置后,它会成为**唯一**授权来源(渠道允许列表/配对以及 `useAccessGroups` 会被忽略)。 -- `useAccessGroups: false` 会在未设置 `allowFrom` 时允许命令绕过访问组策略。 +- `ownerDisplay: "hash"` 会在 system prompt 中对 owner ID 进行哈希。设置 `ownerDisplaySecret` 可控制哈希行为。 +- `allowFrom` 按提供商配置。设置后,它会成为**唯一**的授权来源(渠道允许列表/配对以及 `useAccessGroups` 都会被忽略)。 +- `useAccessGroups: false` 会在未设置 `allowFrom` 时,让命令绕过访问组策略。 - 命令文档映射: - 内置 + 内置插件目录:[Slash Commands](/zh-CN/tools/slash-commands) - - 渠道专属命令表面:[Channels](/zh-CN/channels) + - 渠道特定命令面:[Channels](/zh-CN/channels) - QQ Bot 命令:[QQ Bot](/zh-CN/channels/qqbot) - 配对命令:[Pairing](/zh-CN/channels/pairing) - LINE 卡片命令:[LINE](/zh-CN/channels/line) - - 记忆 Dreaming:[Dreaming](/zh-CN/concepts/dreaming) + - memory Dreaming:[Dreaming](/zh-CN/concepts/dreaming) @@ -897,7 +901,7 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 ### `agents.defaults.repoRoot` -可选的仓库根目录,会显示在系统提示词的 Runtime 行中。如果未设置,OpenClaw 会从工作区向上遍历自动检测。 +可选的仓库根目录,会显示在 system prompt 的 Runtime 行中。如果未设置,OpenClaw 会从工作区向上遍历并自动检测。 ```json5 { @@ -907,29 +911,31 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 ### `agents.defaults.skills` -适用于未设置 `agents.list[].skills` 的智能体的可选默认 Skills 允许列表。 +未设置 +`agents.list[].skills` 的智能体可使用的可选默认 Skills 允许列表。 ```json5 { agents: { defaults: { skills: ["github", "weather"] }, list: [ - { id: "writer" }, // 继承 github、weather - { id: "docs", skills: ["docs-search"] }, // 替换默认值 - { id: "locked-down", skills: [] }, // 无 Skills + { id: "writer" }, // inherits github, weather + { id: "docs", skills: ["docs-search"] }, // replaces defaults + { id: "locked-down", skills: [] }, // no skills ], }, } ``` -- 省略 `agents.defaults.skills`,则默认 Skills 不受限制。 -- 省略 `agents.list[].skills`,则继承默认值。 -- 设置 `agents.list[].skills: []` 表示无 Skills。 -- 非空的 `agents.list[].skills` 列表就是该智能体的最终集合;它不会与默认值合并。 +- 省略 `agents.defaults.skills` 表示默认 Skills 不受限制。 +- 省略 `agents.list[].skills` 表示继承默认值。 +- 设置 `agents.list[].skills: []` 表示没有 Skills。 +- 非空的 `agents.list[].skills` 列表就是该智能体的最终集合;它 + 不会与默认值合并。 ### `agents.defaults.skipBootstrap` -禁用自动创建工作区引导文件(`AGENTS.md`、`SOUL.md`、`TOOLS.md`、`IDENTITY.md`、`USER.md`、`HEARTBEAT.md`、`BOOTSTRAP.md`)。 +禁用自动创建工作区 bootstrap 文件(`AGENTS.md`、`SOUL.md`、`TOOLS.md`、`IDENTITY.md`、`USER.md`、`HEARTBEAT.md`、`BOOTSTRAP.md`)。 ```json5 { @@ -939,9 +945,9 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 ### `agents.defaults.contextInjection` -控制何时将工作区引导文件注入系统提示词。默认值:`"always"`。 +控制何时将工作区 bootstrap 文件注入 system prompt。默认值:`"always"`。 -- `"continuation-skip"`:安全的续写轮次(在已完成的助手响应之后)会跳过工作区引导重新注入,从而减小提示词大小。心跳运行和压缩后重试仍会重建上下文。 +- `"continuation-skip"`:安全续写轮次(在 assistant 响应完成后)会跳过工作区 bootstrap 的重新注入,从而减少 prompt 大小。心跳运行和压缩后重试仍会重建上下文。 ```json5 { @@ -951,7 +957,7 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 ### `agents.defaults.bootstrapMaxChars` -单个工作区引导文件在截断前允许的最大字符数。默认值:`12000`。 +单个工作区 bootstrap 文件在截断前允许的最大字符数。默认值:`12000`。 ```json5 { @@ -961,7 +967,7 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 ### `agents.defaults.bootstrapTotalMaxChars` -所有工作区引导文件合计注入的最大字符数。默认值:`60000`。 +所有工作区 bootstrap 文件总共注入的最大字符数。默认值:`60000`。 ```json5 { @@ -971,10 +977,11 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 ### `agents.defaults.bootstrapPromptTruncationWarning` -控制在引导上下文被截断时,向智能体可见的警告文本。默认值:`"once"`。 +控制 bootstrap 上下文被截断时,对智能体可见的警告文本。 +默认值:`"once"`。 -- `"off"`:绝不向系统提示词注入警告文本。 -- `"once"`:每个唯一截断签名只注入一次警告(推荐)。 +- `"off"`:绝不将警告文本注入 system prompt。 +- `"once"`:每个唯一的截断签名仅注入一次警告(推荐)。 - `"always"`:只要存在截断,就在每次运行时注入警告。 ```json5 @@ -985,29 +992,33 @@ IRC 由插件支持,配置位于 `channels.irc` 下。 ### 上下文预算归属映射 -OpenClaw 有多个高容量提示词/上下文预算,它们会按子系统有意拆分,而不是全部汇入一个通用旋钮。 +OpenClaw 具有多个高容量 prompt/上下文预算,并且它们会 +按子系统刻意拆分,而不是全部流经一个通用 +调节项。 - `agents.defaults.bootstrapMaxChars` / `agents.defaults.bootstrapTotalMaxChars`: - 常规工作区引导注入。 + 常规工作区 bootstrap 注入。 - `agents.defaults.startupContext.*`: - 单次 `/new` 和 `/reset` 启动前导,包括最近的每日 + 一次性的 `/new` 和 `/reset` 启动前导内容,包括最近的每日 `memory/*.md` 文件。 - `skills.limits.*`: - 注入系统提示词中的紧凑 Skills 列表。 + 注入 system prompt 的紧凑 Skills 列表。 - `agents.defaults.contextLimits.*`: - 有界运行时摘录和注入的运行时所属块。 + 有界的运行时摘录和由运行时拥有的注入块。 - `memory.qmd.limits.*`: - 索引记忆搜索片段和注入大小。 + 已索引的 memory 搜索片段和注入大小控制。 -仅当某个智能体需要不同预算时,才使用匹配的按智能体覆盖: +仅当某个智能体需要不同 +预算时,才使用对应的按智能体覆盖: - `agents.list[].skillsLimits.maxSkillsPromptChars` - `agents.list[].contextLimits.*` #### `agents.defaults.startupContext` -控制在裸 `/new` 和 `/reset` 运行时注入的首轮启动前导。 +控制在裸 `/new` 和 `/reset` +运行时注入的首轮启动前导内容。 ```json5 { @@ -1028,7 +1039,7 @@ OpenClaw 有多个高容量提示词/上下文预算,它们会按子系统有 #### `agents.defaults.contextLimits` -有界运行时上下文表面的共享默认值。 +有界运行时上下文面的共享默认值。 ```json5 { @@ -1045,14 +1056,16 @@ OpenClaw 有多个高容量提示词/上下文预算,它们会按子系统有 } ``` -- `memoryGetMaxChars`:默认的 `memory_get` 摘录上限;在添加截断元数据和续接提示前生效。 -- `memoryGetDefaultLines`:当省略 `lines` 时,默认的 `memory_get` 行窗口。 +- `memoryGetMaxChars`:默认 `memory_get` 摘录上限,超过后才会附加截断 + 元数据和续写提示。 +- `memoryGetDefaultLines`:省略 `lines` 时默认的 `memory_get` 行窗口。 - `toolResultMaxChars`:用于持久化结果和溢出恢复的实时工具结果上限。 -- `postCompactionMaxChars`:压缩后刷新注入期间使用的 `AGENTS.md` 摘录上限。 +- `postCompactionMaxChars`:压缩后刷新注入期间使用的 AGENTS.md 摘录上限。 #### `agents.list[].contextLimits` -共享 `contextLimits` 旋钮的按智能体覆盖。省略的字段会继承自 `agents.defaults.contextLimits`。 +用于共享 `contextLimits` 调节项的按智能体覆盖。省略的字段会继承 +自 `agents.defaults.contextLimits`。 ```json5 { @@ -1078,7 +1091,8 @@ OpenClaw 有多个高容量提示词/上下文预算,它们会按子系统有 #### `skills.limits.maxSkillsPromptChars` -注入系统提示词中的紧凑 Skills 列表的全局上限。这不会影响按需读取 `SKILL.md` 文件。 +注入 system prompt 的紧凑 Skills 列表的全局上限。此项 +不会影响按需读取 `SKILL.md` 文件。 ```json5 { @@ -1092,7 +1106,7 @@ OpenClaw 有多个高容量提示词/上下文预算,它们会按子系统有 #### `agents.list[].skillsLimits.maxSkillsPromptChars` -Skills 提示词预算的按智能体覆盖。 +Skills prompt 预算的按智能体覆盖。 ```json5 { @@ -1111,11 +1125,11 @@ Skills 提示词预算的按智能体覆盖。 ### `agents.defaults.imageMaxDimensionPx` -在调用提供商之前,转录/工具图像块中图像最长边的最大像素尺寸。 +在调用提供商之前,transcript/工具图像块中图像最长边的最大像素尺寸。 默认值:`1200`。 -较低的值通常会降低视觉 token 使用量,以及在以截图为主的运行中的请求载荷大小。 -较高的值会保留更多视觉细节。 +较低的值通常会减少视觉 token 使用量以及以截图为主运行时的请求负载大小。 +较高的值则可保留更多视觉细节。 ```json5 { @@ -1125,7 +1139,7 @@ Skills 提示词预算的按智能体覆盖。 ### `agents.defaults.userTimezone` -系统提示词上下文使用的时区(不是消息时间戳)。会回退到宿主机时区。 +用于 system prompt 上下文的时区(不是消息时间戳)。会回退到主机时区。 ```json5 { @@ -1135,7 +1149,7 @@ Skills 提示词预算的按智能体覆盖。 ### `agents.defaults.timeFormat` -系统提示词中的时间格式。默认值:`auto`(操作系统偏好)。 +system prompt 中的时间格式。默认值:`auto`(操作系统偏好)。 ```json5 { @@ -1173,9 +1187,9 @@ Skills 提示词预算的按智能体覆盖。 primary: "anthropic/claude-opus-4-6", fallbacks: ["openai/gpt-5.4-mini"], }, - params: { cacheRetention: "long" }, // 全局默认提供商参数 + params: { cacheRetention: "long" }, // global default provider params embeddedHarness: { - runtime: "auto", // auto | pi | 已注册的 harness id,例如 codex + runtime: "auto", // auto | pi | registered harness id, e.g. codex fallback: "pi", // pi | none }, pdfMaxBytesMb: 10, @@ -1192,50 +1206,50 @@ Skills 提示词预算的按智能体覆盖。 } ``` -- `model`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)。 - - 字符串形式仅设置主模型。 +- `model`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)两种形式。 + - 字符串形式只设置主模型。 - 对象形式会设置主模型以及按顺序排列的故障切换模型。 -- `imageModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)。 - - 由 `image` 工具路径作为其视觉模型配置使用。 - - 当选定/默认模型无法接受图像输入时,也会用作回退路由。 -- `imageGenerationModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)。 - - 由共享图像生成能力以及未来任何生成图像的工具/插件表面使用。 - - 典型值:原生 Gemini 图像生成使用 `google/gemini-3.1-flash-image-preview`,fal 使用 `fal/fal-ai/flux/dev`,OpenAI Images 使用 `openai/gpt-image-2`。 - - 如果你直接选择某个提供商/模型,也需要配置匹配的提供商认证/API 密钥(例如 `google/*` 对应 `GEMINI_API_KEY` 或 `GOOGLE_API_KEY`,`openai/*` 对应 `OPENAI_API_KEY`,`fal/*` 对应 `FAL_KEY`)。 - - 如果省略,`image_generate` 仍然可以推断出一个带认证的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的图像生成提供商。 -- `musicGenerationModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)。 +- `imageModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)两种形式。 + - 由 `image` 工具路径用作其视觉模型配置。 + - 当所选/默认模型无法接受图像输入时,也用作回退路由。 +- `imageGenerationModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)两种形式。 + - 由共享图像生成能力以及未来任何生成图像的工具/插件面使用。 + - 典型值:`google/gemini-3.1-flash-image-preview`(原生 Gemini 图像生成)、`fal/fal-ai/flux/dev`(用于 fal),或 `openai/gpt-image-2`(用于 OpenAI Images)。 + - 如果你直接选择某个 provider/model,也要配置匹配的提供商认证(例如 `google/*` 对应 `GEMINI_API_KEY` 或 `GOOGLE_API_KEY`,`openai/gpt-image-2` 对应 `OPENAI_API_KEY` 或 OpenAI Codex OAuth,`fal/*` 对应 `FAL_KEY`)。 + - 如果省略,`image_generate` 仍可推断出一个由认证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的图像生成提供商。 +- `musicGenerationModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)两种形式。 - 由共享音乐生成能力和内置 `music_generate` 工具使用。 - 典型值:`google/lyria-3-clip-preview`、`google/lyria-3-pro-preview` 或 `minimax/music-2.5+`。 - - 如果省略,`music_generate` 仍然可以推断出一个带认证的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的音乐生成提供商。 - - 如果你直接选择某个提供商/模型,也需要配置匹配的提供商认证/API 密钥。 -- `videoGenerationModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)。 + - 如果省略,`music_generate` 仍可推断出一个由认证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的音乐生成提供商。 + - 如果你直接选择某个 provider/model,也要配置匹配的提供商认证/API 密钥。 +- `videoGenerationModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)两种形式。 - 由共享视频生成能力和内置 `video_generate` 工具使用。 - 典型值:`qwen/wan2.6-t2v`、`qwen/wan2.6-i2v`、`qwen/wan2.6-r2v`、`qwen/wan2.6-r2v-flash` 或 `qwen/wan2.7-r2v`。 - - 如果省略,`video_generate` 仍然可以推断出一个带认证的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的视频生成提供商。 - - 如果你直接选择某个提供商/模型,也需要配置匹配的提供商认证/API 密钥。 - - 内置的 Qwen 视频生成提供商最多支持 1 个输出视频、1 张输入图片、4 个输入视频、10 秒时长,以及提供商级的 `size`、`aspectRatio`、`resolution`、`audio` 和 `watermark` 选项。 -- `pdfModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)。 + - 如果省略,`video_generate` 仍可推断出一个由认证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的视频生成提供商。 + - 如果你直接选择某个 provider/model,也要配置匹配的提供商认证/API 密钥。 + - 内置的 Qwen 视频生成提供商最多支持 1 个输出视频、1 张输入图像、4 个输入视频、10 秒时长,以及提供商级别的 `size`、`aspectRatio`、`resolution`、`audio` 和 `watermark` 选项。 +- `pdfModel`:接受字符串(`"provider/model"`)或对象(`{ primary, fallbacks }`)两种形式。 - 由 `pdf` 工具用于模型路由。 - - 如果省略,PDF 工具会回退到 `imageModel`,然后回退到解析后的会话/默认模型。 -- `pdfMaxBytesMb`:当调用时未传入 `maxBytesMb`,则作为 `pdf` 工具的默认 PDF 大小限制。 -- `pdfMaxPages`:`pdf` 工具中提取回退模式默认考虑的最大页数。 + - 如果省略,PDF 工具会先回退到 `imageModel`,再回退到已解析的会话/默认模型。 +- `pdfMaxBytesMb`:当调用时未传入 `maxBytesMb`,`pdf` 工具使用的默认 PDF 大小限制。 +- `pdfMaxPages`:`pdf` 工具在提取回退模式下考虑的默认最大页数。 - `verboseDefault`:智能体的默认详细级别。取值:`"off"`、`"on"`、`"full"`。默认值:`"off"`。 -- `elevatedDefault`:智能体的默认高级输出级别。取值:`"off"`、`"on"`、`"ask"`、`"full"`。默认值:`"on"`。 -- `model.primary`:格式为 `provider/model`(例如 `openai/gpt-5.4` 用于 API 密钥访问,或 `openai-codex/gpt-5.5` 用于 Codex OAuth)。如果省略提供商,OpenClaw 会先尝试别名,然后尝试与该精确模型 ID 唯一匹配的已配置提供商,最后才回退到已配置的默认提供商(这是已弃用的兼容行为,因此更推荐显式使用 `provider/model`)。如果该提供商不再公开已配置的默认模型,OpenClaw 会回退到第一个已配置的提供商/模型,而不是暴露一个过时的、已移除提供商的默认值。 -- `models`:为 `/model` 配置的模型目录和允许列表。每个条目可包含 `alias`(快捷方式)和 `params`(提供商特定参数,例如 `temperature`、`maxTokens`、`cacheRetention`、`context1m`)。 - - 安全编辑方式:使用 `openclaw config set agents.defaults.models '' --strict-json --merge` 添加条目。`config set` 会拒绝会移除现有允许列表条目的替换,除非你传入 `--replace`。 - - 按提供商划分的 configure/onboarding 流程会将选定提供商的模型合并到此映射中,并保留已配置的无关提供商。 -- `params`:应用于所有模型的全局默认提供商参数。设置在 `agents.defaults.params`(例如 `{ cacheRetention: "long" }`)。 -- `params` 合并优先级(配置):`agents.defaults.params`(全局基础)会被 `agents.defaults.models["provider/model"].params`(按模型)覆盖,然后 `agents.list[].params`(匹配的智能体 ID)会按键继续覆盖。详见 [Prompt Caching](/zh-CN/reference/prompt-caching)。 -- `embeddedHarness`:默认的低层嵌入式智能体运行时策略。使用 `runtime: "auto"` 可让已注册的插件 harness 认领其支持的模型,使用 `runtime: "pi"` 可强制使用内置 PI harness,或使用已注册 harness ID,例如 `runtime: "codex"`。设置 `fallback: "none"` 可禁用自动 PI 回退。 -- 会修改这些字段的配置写入器(例如 `/models set`、`/models set-image` 以及回退项添加/移除命令)会保存规范对象形式,并尽可能保留现有回退列表。 -- `maxConcurrent`:跨会话的最大并行智能体运行数(每个会话本身仍是串行的)。默认值:4。 +- `elevatedDefault`:智能体的默认提升输出级别。取值:`"off"`、`"on"`、`"ask"`、`"full"`。默认值:`"on"`。 +- `model.primary`:格式为 `provider/model`(例如 `openai/gpt-5.4` 表示 API 密钥访问,或 `openai-codex/gpt-5.5` 表示 Codex OAuth)。如果你省略 provider,OpenClaw 会先尝试别名,然后尝试与该精确模型 ID 唯一匹配的已配置提供商,最后才回退到已配置的默认提供商(这是已弃用的兼容行为,因此建议优先使用显式的 `provider/model`)。如果该提供商不再提供已配置的默认模型,OpenClaw 会回退到第一个已配置的 provider/model,而不是暴露一个已移除提供商的过时默认值。 +- `models`:`/model` 使用的已配置模型目录和允许列表。每个条目都可以包含 `alias`(快捷方式)和 `params`(提供商特定参数,例如 `temperature`、`maxTokens`、`cacheRetention`、`context1m`)。 + - 安全编辑:使用 `openclaw config set agents.defaults.models '' --strict-json --merge` 添加条目。除非你传入 `--replace`,否则 `config set` 会拒绝会移除现有允许列表条目的替换。 + - 按提供商划分的 configure/新手引导流程会将所选提供商模型合并到此映射中,并保留已配置的其他无关提供商。 +- `params`:应用到所有模型的全局默认提供商参数。设置于 `agents.defaults.params`(例如 `{ cacheRetention: "long" }`)。 +- `params` 合并优先级(配置):`agents.defaults.params`(全局基础)会被 `agents.defaults.models["provider/model"].params`(按模型)覆盖,然后再由 `agents.list[].params`(匹配的智能体 ID)按键覆盖。详见 [Prompt Caching](/zh-CN/reference/prompt-caching)。 +- `embeddedHarness`:默认的底层嵌入式智能体运行时策略。使用 `runtime: "auto"` 可让已注册插件 harness 认领受支持模型,使用 `runtime: "pi"` 可强制使用内置 Pi harness,或使用已注册 harness ID,例如 `runtime: "codex"`。设置 `fallback: "none"` 可禁用自动 Pi 回退。 +- 修改这些字段的配置写入器(例如 `/models set`、`/models set-image` 和回退添加/删除命令)会保存规范对象形式,并在可能时保留现有回退列表。 +- `maxConcurrent`:跨会话的最大并行智能体运行数(每个会话本身仍串行)。默认值:4。 ### `agents.defaults.embeddedHarness` -`embeddedHarness` 控制由哪个低层执行器来运行嵌入式智能体轮次。 +`embeddedHarness` 控制哪个底层执行器运行嵌入式智能体轮次。 大多数部署应保留默认值 `{ runtime: "auto", fallback: "pi" }`。 -当某个受信任插件提供原生 harness 时,请使用它,例如内置的 +当受信任的插件提供原生 harness 时可使用它,例如内置的 Codex app-server harness。 ```json5 @@ -1252,14 +1266,14 @@ Codex app-server harness。 } ``` -- `runtime`:`"auto"`、`"pi"` 或已注册的插件 harness ID。内置的 Codex 插件注册为 `codex`。 -- `fallback`:`"pi"` 或 `"none"`。当未选中任何插件 harness 时,`"pi"` 会保留内置 PI harness 作为兼容性回退;`"none"` 则会在插件 harness 选择缺失或不受支持时直接失败,而不是静默使用 PI。选定的插件 harness 失败始终会被直接暴露。 -- 环境变量覆盖:`OPENCLAW_AGENT_RUNTIME=` 会覆盖 `runtime`;`OPENCLAW_AGENT_HARNESS_FALLBACK=none` 会为该进程禁用 PI 回退。 -- 对于仅使用 Codex 的部署,请设置 `model: "openai/gpt-5.5"`、`embeddedHarness.runtime: "codex"` 和 `embeddedHarness.fallback: "none"`。 -- 在首次嵌入式运行后,harness 选择会按 session id 固定。配置/环境变量更改会影响新的或已重置的会话,而不会影响现有转录。带有转录历史但没有已记录固定值的旧会话会被视为已固定到 PI。`/status` 会在 `Fast` 旁边显示非 PI 的 harness ID,例如 `codex`。 -- 这只控制嵌入式聊天 harness。媒体生成、视觉、PDF、音乐、视频和 TTS 仍使用各自的提供商/模型设置。 +- `runtime`:`"auto"`、`"pi"` 或已注册插件 harness ID。内置 Codex 插件注册了 `codex`。 +- `fallback`:`"pi"` 或 `"none"`。`"pi"` 会在未选择任何插件 harness 时保留内置 Pi harness 作为兼容性回退。`"none"` 会让缺失或不受支持的插件 harness 选择直接失败,而不是静默使用 Pi。已选择的插件 harness 若失败,则始终会直接暴露。 +- 环境变量覆盖:`OPENCLAW_AGENT_RUNTIME=` 会覆盖 `runtime`;`OPENCLAW_AGENT_HARNESS_FALLBACK=none` 会为该进程禁用 Pi 回退。 +- 对于仅 Codex 的部署,请设置 `model: "openai/gpt-5.5"`、`embeddedHarness.runtime: "codex"` 和 `embeddedHarness.fallback: "none"`。 +- 在第一次嵌入式运行后,harness 选择会按会话 ID 固定。配置/环境变量的更改只影响新会话或已重置会话,不影响现有 transcript。带有 transcript 历史但没有记录固定值的旧会话会被视为固定到 Pi。`/status` 会在 `Fast` 旁显示非 Pi 的 harness ID,例如 `codex`。 +- 此项仅控制嵌入式聊天 harness。媒体生成、视觉、PDF、音乐、视频和 TTS 仍使用各自的 provider/model 设置。 -**内置别名简写**(仅当该模型位于 `agents.defaults.models` 中时适用): +**内置别名简写**(仅当模型位于 `agents.defaults.models` 中时适用): | 别名 | 模型 | | ------------------- | -------------------------------------------------- | @@ -1275,12 +1289,12 @@ Codex app-server harness。 你配置的别名始终优先于默认值。 Z.AI GLM-4.x 模型会自动启用 thinking 模式,除非你设置 `--thinking off`,或自行定义 `agents.defaults.models["zai/"].params.thinking`。 -Z.AI 模型默认启用 `tool_stream` 以支持工具调用流式传输。将 `agents.defaults.models["zai/"].params.tool_stream` 设为 `false` 可禁用它。 -Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 `adaptive` thinking。 +Z.AI 模型默认启用 `tool_stream` 以支持工具调用流式传输。将 `agents.defaults.models["zai/"].params.tool_stream` 设置为 `false` 可禁用它。 +Anthropic Claude 4.6 模型在未设置显式 thinking 级别时,默认使用 `adaptive` thinking。 ### `agents.defaults.cliBackends` -用于纯文本回退运行(无工具调用)的可选 CLI 后端。当 API 提供商失败时,它可作为备份。 +用于纯文本回退运行(无工具调用)的可选 CLI 后端。在 API 提供商失败时可作为备用方案。 ```json5 { @@ -1308,13 +1322,13 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 } ``` -- CLI 后端以文本为主;工具始终禁用。 -- 当设置了 `sessionArg` 时支持会话。 +- CLI 后端以文本优先;工具始终禁用。 +- 设置了 `sessionArg` 时支持会话。 - 当 `imageArg` 接受文件路径时,支持图像透传。 ### `agents.defaults.systemPromptOverride` -用固定字符串替换整个由 OpenClaw 组装的系统提示词。可在默认级别(`agents.defaults.systemPromptOverride`)或按智能体(`agents.list[].systemPromptOverride`)设置。按智能体的值优先;空值或仅包含空白的值会被忽略。适用于受控提示词实验。 +用固定字符串替换整个由 OpenClaw 组装的 system prompt。可设置在默认级别(`agents.defaults.systemPromptOverride`)或按智能体设置(`agents.list[].systemPromptOverride`)。按智能体的值优先;空值或仅空白字符的值会被忽略。适用于受控 prompt 实验。 ```json5 { @@ -1328,7 +1342,7 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 ### `agents.defaults.promptOverlays` -按模型家族应用的、与提供商无关的提示词叠加层。GPT-5 系列模型 ID 会在各提供商之间接收共享的行为契约;`personality` 仅控制友好交互风格层。 +按模型家族应用的、与提供商无关的 prompt 覆盖层。GPT-5 家族模型 ID 会在各提供商间获得共享行为契约;`personality` 仅控制友好交互风格这一层。 ```json5 { @@ -1345,7 +1359,7 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 ``` - `"friendly"`(默认)和 `"on"` 会启用友好交互风格层。 -- `"off"` 仅禁用友好层;带标签的 GPT-5 行为契约仍保持启用。 +- `"off"` 只会禁用友好层;带标签的 GPT-5 行为契约仍保持启用。 - 当这个共享设置未设置时,仍会读取旧版 `plugins.entries.openai.config.personality`。 ### `agents.defaults.heartbeat` @@ -1357,16 +1371,16 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 agents: { defaults: { heartbeat: { - every: "30m", // 0m 表示禁用 + every: "30m", // 0m disables model: "openai/gpt-5.4-mini", includeReasoning: false, - includeSystemPromptSection: true, // 默认:true;false 会从系统提示词中省略 Heartbeat 部分 - lightContext: false, // 默认:false;true 仅保留工作区引导文件中的 HEARTBEAT.md - isolatedSession: false, // 默认:false;true 会在全新会话中运行每次心跳(无对话历史) + includeSystemPromptSection: true, // default: true; false omits the Heartbeat section from the system prompt + lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files + isolatedSession: false, // default: false; true runs each heartbeat in a fresh session (no conversation history) session: "main", to: "+15555550123", - directPolicy: "allow", // allow(默认)| block - target: "none", // 默认:none | 可选值:last | whatsapp | telegram | discord | ... + directPolicy: "allow", // allow (default) | block + target: "none", // default: none | options: last | whatsapp | telegram | discord | ... prompt: "Read HEARTBEAT.md if it exists...", ackMaxChars: 300, suppressToolErrorWarnings: false, @@ -1378,14 +1392,14 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 ``` - `every`:时长字符串(ms/s/m/h)。默认值:`30m`(API 密钥认证)或 `1h`(OAuth 认证)。设置为 `0m` 可禁用。 -- `includeSystemPromptSection`:为 false 时,会从系统提示词中省略 Heartbeat 部分,并跳过将 `HEARTBEAT.md` 注入引导上下文。默认值:`true`。 -- `suppressToolErrorWarnings`:为 true 时,会在心跳运行期间抑制工具错误警告载荷。 -- `timeoutSeconds`:心跳智能体轮次在被中止前允许的最大秒数。若留空,则使用 `agents.defaults.timeoutSeconds`。 +- `includeSystemPromptSection`:为 false 时,会省略 system prompt 中的 Heartbeat 段,并跳过将 `HEARTBEAT.md` 注入 bootstrap 上下文。默认值:`true`。 +- `suppressToolErrorWarnings`:为 true 时,会在心跳运行期间抑制工具错误警告负载。 +- `timeoutSeconds`:在中止前,单次心跳智能体轮次允许的最长秒数。留空则使用 `agents.defaults.timeoutSeconds`。 - `directPolicy`:直接/私信投递策略。`allow`(默认)允许直接目标投递。`block` 会抑制直接目标投递,并发出 `reason=dm-blocked`。 -- `lightContext`:为 true 时,心跳运行使用轻量引导上下文,并且只保留工作区引导文件中的 `HEARTBEAT.md`。 -- `isolatedSession`:为 true 时,每次心跳都会在一个没有先前对话历史的新会话中运行。与 cron `sessionTarget: "isolated"` 采用相同的隔离模式。可将每次心跳的 token 成本从约 100K 降低到约 2-5K token。 -- 按智能体设置:使用 `agents.list[].heartbeat`。当任何智能体定义了 `heartbeat` 时,**只有这些智能体**会运行心跳。 -- 心跳会运行完整的智能体轮次 —— 更短的间隔会消耗更多 token。 +- `lightContext`:为 true 时,心跳运行会使用轻量 bootstrap 上下文,并且只保留工作区 bootstrap 文件中的 `HEARTBEAT.md`。 +- `isolatedSession`:为 true 时,每次心跳都会在一个全新的会话中运行,不带任何先前对话历史。隔离模式与 cron 的 `sessionTarget: "isolated"` 相同。可将每次心跳的 token 成本从约 100K 降低到约 2-5K token。 +- 按智能体设置:使用 `agents.list[].heartbeat`。当任意智能体定义了 `heartbeat` 时,**只有这些智能体**会运行心跳。 +- 心跳会运行完整的智能体轮次 —— 间隔越短,消耗的 token 越多。 ### `agents.defaults.compaction` @@ -1395,14 +1409,14 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 defaults: { compaction: { mode: "safeguard", // default | safeguard - provider: "my-provider", // 已注册压缩提供商插件的 id(可选) + provider: "my-provider", // id of a registered compaction provider plugin (optional) timeoutSeconds: 900, reserveTokensFloor: 24000, identifierPolicy: "strict", // strict | off | custom - identifierInstructions: "Preserve deployment IDs, ticket IDs, and host:port pairs exactly.", // 当 identifierPolicy=custom 时使用 - postCompactionSections: ["Session Startup", "Red Lines"], // [] 表示禁用重新注入 - model: "openrouter/anthropic/claude-sonnet-4-6", // 仅用于压缩的可选模型覆盖 - notifyUser: true, // 在压缩开始和完成时发送简短通知(默认:false) + identifierInstructions: "Preserve deployment IDs, ticket IDs, and host:port pairs exactly.", // used when identifierPolicy=custom + postCompactionSections: ["Session Startup", "Red Lines"], // [] disables reinjection + model: "openrouter/anthropic/claude-sonnet-4-6", // optional compaction-only model override + notifyUser: true, // send brief notices when compaction starts and completes (default: false) memoryFlush: { enabled: true, softThresholdTokens: 6000, @@ -1415,19 +1429,19 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 } ``` -- `mode`:`default` 或 `safeguard`(用于长历史的分块摘要)。参见 [Compaction](/zh-CN/concepts/compaction)。 -- `provider`:已注册压缩提供商插件的 id。设置后,将调用该提供商的 `summarize()`,而不是使用内置 LLM 摘要。失败时会回退到内置实现。设置提供商会强制使用 `mode: "safeguard"`。参见 [Compaction](/zh-CN/concepts/compaction)。 -- `timeoutSeconds`:OpenClaw 在中止前允许单次压缩操作运行的最大秒数。默认值:`900`。 -- `identifierPolicy`:`strict`(默认)、`off` 或 `custom`。`strict` 会在压缩摘要期间预置内置的不透明标识符保留指导。 +- `mode`:`default` 或 `safeguard`(适用于长历史记录的分块摘要)。参见 [Compaction](/zh-CN/concepts/compaction)。 +- `provider`:已注册 compaction 提供商插件的 ID。设置后,会调用该提供商的 `summarize()`,而不是内置 LLM 摘要。失败时会回退到内置实现。设置提供商会强制使用 `mode: "safeguard"`。参见 [Compaction](/zh-CN/concepts/compaction)。 +- `timeoutSeconds`:OpenClaw 中止单次 compaction 操作前允许的最长秒数。默认值:`900`。 +- `identifierPolicy`:`strict`(默认)、`off` 或 `custom`。`strict` 会在 compaction 摘要期间预置内置的不透明标识符保留指导。 - `identifierInstructions`:当 `identifierPolicy=custom` 时使用的可选自定义标识符保留文本。 -- `postCompactionSections`:压缩后重新注入的可选 `AGENTS.md` H2/H3 章节名称。默认值为 `["Session Startup", "Red Lines"]`;设置为 `[]` 可禁用重新注入。未设置时,或显式设置为这组默认值时,旧版 `Every Session`/`Safety` 标题也会作为旧兼容回退被接受。 -- `model`:仅用于压缩摘要的可选 `provider/model-id` 覆盖。当你希望主会话保持一个模型,而压缩摘要在另一个模型上运行时,请使用它;未设置时,压缩会使用会话的主模型。 -- `notifyUser`:为 `true` 时,会在压缩开始和完成时向用户发送简短通知(例如“正在压缩上下文...”和“压缩完成”)。默认禁用,以保持压缩静默。 -- `memoryFlush`:在自动压缩前执行的静默智能体轮次,用于存储持久记忆。当工作区为只读时会跳过。 +- `postCompactionSections`:compaction 后重新注入的可选 AGENTS.md H2/H3 段名称。默认值为 `["Session Startup", "Red Lines"]`;设置为 `[]` 可禁用重新注入。未设置或显式设置为该默认对时,也接受旧版 `Every Session`/`Safety` 标题作为兼容回退。 +- `model`:仅用于 compaction 摘要的可选 `provider/model-id` 覆盖。当主会话应保留一个模型,而 compaction 摘要应在另一个模型上运行时使用;未设置时,compaction 使用会话的主模型。 +- `notifyUser`:为 `true` 时,会在 compaction 开始和完成时向用户发送简短通知(例如“正在压缩上下文...”和“上下文压缩完成”)。默认禁用,以保持 compaction 静默。 +- `memoryFlush`:在自动 compaction 之前执行的静默智能体轮次,用于存储持久 memory。工作区为只读时会跳过。 ### `agents.defaults.contextPruning` -在将上下文发送给 LLM 之前,从内存中的上下文中修剪**旧工具结果**。**不会**修改磁盘上的会话历史。 +在发送给 LLM 之前,从内存中的上下文里修剪**旧工具结果**。**不会**修改磁盘上的会话历史。 ```json5 { @@ -1435,7 +1449,7 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 defaults: { contextPruning: { mode: "cache-ttl", // off | cache-ttl - ttl: "1h", // 时长(ms/s/m/h),默认单位:分钟 + ttl: "1h", // duration (ms/s/m/h), default unit: minutes keepLastAssistants: 3, softTrimRatio: 0.3, hardClearRatio: 0.5, @@ -1449,25 +1463,25 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 } ``` - + - `mode: "cache-ttl"` 会启用修剪过程。 -- `ttl` 控制多久之后才能再次运行修剪(自上次缓存触达之后)。 -- 修剪会先对过大的工具结果执行软截断,然后在需要时对较旧的工具结果执行硬清除。 +- `ttl` 控制多久之后才能再次运行修剪(自上次缓存触达后计算)。 +- 修剪会先对过大的工具结果执行软修剪,如仍有需要,再对更旧的工具结果执行硬清除。 -**软截断**会保留开头 + 结尾,并在中间插入 `...`。 +**软修剪**会保留开头和结尾,并在中间插入 `...`。 **硬清除**会用占位符替换整个工具结果。 -说明: +注意: -- 图像块永远不会被截断/清除。 -- 比例基于字符数(近似),而不是精确 token 数。 -- 如果助手消息少于 `keepLastAssistants` 条,则会跳过修剪。 +- 图像块永远不会被修剪/清除。 +- 比例基于字符数(近似),不是精确 token 数。 +- 如果 assistant 消息少于 `keepLastAssistants` 条,则跳过修剪。 -有关行为细节,请参见 [会话修剪](/zh-CN/concepts/session-pruning)。 +行为详情请参阅 [Session Pruning](/zh-CN/concepts/session-pruning)。 ### 分块流式传输 @@ -1479,7 +1493,7 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 blockStreamingBreak: "text_end", // text_end | message_end blockStreamingChunk: { minChars: 800, maxChars: 1200 }, blockStreamingCoalesce: { idleMs: 1000 }, - humanDelay: { mode: "natural" }, // off | natural | custom(使用 minMs/maxMs) + humanDelay: { mode: "natural" }, // off | natural | custom (use minMs/maxMs) }, }, } @@ -1487,9 +1501,9 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 - 非 Telegram 渠道需要显式设置 `*.blockStreaming: true` 才会启用分块回复。 - 渠道覆盖:`channels..blockStreamingCoalesce`(以及按账号变体)。Signal/Slack/Discord/Google Chat 默认 `minChars: 1500`。 -- `humanDelay`:分块回复之间的随机暂停。`natural` = 800–2500ms。按智能体覆盖:`agents.list[].humanDelay`。 +- `humanDelay`:分块回复之间的随机暂停。`natural` = 800–2500 ms。按智能体覆盖:`agents.list[].humanDelay`。 -有关行为和分块细节,请参见 [流式传输](/zh-CN/concepts/streaming)。 +行为和分块细节请参阅 [Streaming](/zh-CN/concepts/streaming)。 ### 输入中指示器 @@ -1504,16 +1518,16 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 } ``` -- 默认值:私聊/被提及时为 `instant`,未被提及的群聊为 `message`。 +- 默认值:对私聊/提及使用 `instant`,对未提及的群聊使用 `message`。 - 按会话覆盖:`session.typingMode`、`session.typingIntervalSeconds`。 -参见 [输入中指示器](/zh-CN/concepts/typing-indicators)。 +参见 [Typing Indicators](/zh-CN/concepts/typing-indicators)。 ### `agents.defaults.sandbox` -嵌入式智能体的可选沙箱隔离。完整指南请参见 [沙箱隔离](/zh-CN/gateway/sandboxing)。 +嵌入式智能体的可选沙箱隔离。完整指南请参阅 [Sandboxing](/zh-CN/gateway/sandboxing)。 ```json5 { @@ -1559,7 +1573,7 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 identityFile: "~/.ssh/id_ed25519", certificateFile: "~/.ssh/id_ed25519-cert.pub", knownHostsFile: "~/.ssh/known_hosts", - // 也支持 SecretRef / 内联内容: + // SecretRefs / inline contents also supported: // identityData: { source: "env", provider: "default", id: "SSH_IDENTITY" }, // certificateData: { source: "env", provider: "default", id: "SSH_CERTIFICATE" }, // knownHostsData: { source: "env", provider: "default", id: "SSH_KNOWN_HOSTS" }, @@ -1616,42 +1630,42 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 - `ssh`:通用 SSH 支持的远程运行时 - `openshell`:OpenShell 运行时 -当选择 `backend: "openshell"` 时,运行时特定设置会移动到 +选择 `backend: "openshell"` 时,运行时特定设置会移动到 `plugins.entries.openshell.config`。 **SSH 后端配置:** - `target`:`user@host[:port]` 形式的 SSH 目标 - `command`:SSH 客户端命令(默认:`ssh`) -- `workspaceRoot`:用于按作用域工作区的绝对远程根目录 +- `workspaceRoot`:用于按范围工作区的绝对远程根目录 - `identityFile` / `certificateFile` / `knownHostsFile`:传递给 OpenSSH 的现有本地文件 -- `identityData` / `certificateData` / `knownHostsData`:OpenClaw 会在运行时将其物化为临时文件的内联内容或 SecretRefs -- `strictHostKeyChecking` / `updateHostKeys`:OpenSSH 主机密钥策略旋钮 +- `identityData` / `certificateData` / `knownHostsData`:OpenClaw 在运行时实体化为临时文件的内联内容或 SecretRef +- `strictHostKeyChecking` / `updateHostKeys`:OpenSSH 主机密钥策略调节项 **SSH 认证优先级:** - `identityData` 优先于 `identityFile` - `certificateData` 优先于 `certificateFile` - `knownHostsData` 优先于 `knownHostsFile` -- 由 SecretRef 支持的 `*Data` 值会在沙箱会话启动前从当前生效的 secrets 运行时快照中解析 +- 由 SecretRef 支持的 `*Data` 值会在沙箱会话开始前,从活动 secrets 运行时快照中解析 **SSH 后端行为:** -- 在创建或重建后仅对远程工作区进行一次初始化 -- 然后保持远程 SSH 工作区为规范状态 +- 在创建或重新创建后,只对远程工作区执行一次初始化 +- 随后将远程 SSH 工作区保持为规范副本 - 通过 SSH 路由 `exec`、文件工具和媒体路径 -- 不会自动将远程更改同步回宿主机 +- 不会自动将远程更改同步回主机 - 不支持沙箱浏览器容器 **工作区访问:** -- `none`:位于 `~/.openclaw/sandboxes` 下的按作用域沙箱工作区 -- `ro`:沙箱工作区位于 `/workspace`,智能体工作区以只读方式挂载到 `/agent` +- `none`:位于 `~/.openclaw/sandboxes` 下的按范围沙箱工作区 +- `ro`:沙箱工作区挂载到 `/workspace`,智能体工作区以只读方式挂载到 `/agent` - `rw`:智能体工作区以读写方式挂载到 `/workspace` -**作用域:** +**范围:** -- `session`:按会话划分的容器 + 工作区 +- `session`:每个会话一个容器 + 工作区 - `agent`:每个智能体一个容器 + 工作区(默认) - `shared`:共享容器和工作区(无跨会话隔离) @@ -1668,10 +1682,10 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 from: "openclaw", remoteWorkspaceDir: "/sandbox", remoteAgentWorkspaceDir: "/agent", - gateway: "lab", // 可选 - gatewayEndpoint: "https://lab.example", // 可选 - policy: "strict", // 可选 OpenShell policy id - providers: ["openai"], // 可选 + gateway: "lab", // optional + gatewayEndpoint: "https://lab.example", // optional + policy: "strict", // optional OpenShell policy id + providers: ["openai"], // optional autoProviders: true, timeoutSeconds: 120, }, @@ -1683,30 +1697,30 @@ Anthropic Claude 4.6 模型在未显式设置 thinking 级别时,默认使用 **OpenShell 模式:** -- `mirror`:在 exec 前将本地内容同步到远程,在 exec 后再同步回来;本地工作区保持为规范状态 -- `remote`:在创建沙箱时仅向远程进行一次初始化,然后保持远程工作区为规范状态 +- `mirror`:在 exec 之前将远程端与本地同步,在 exec 之后再同步回本地;本地工作区保持为规范副本 +- `remote`:在创建沙箱时只向远程端初始化一次,之后保持远程工作区为规范副本 -在 `remote` 模式下,在 OpenClaw 之外于宿主机本地进行的编辑,在初始化步骤之后不会自动同步到沙箱中。 -传输方式是通过 SSH 进入 OpenShell 沙箱,但插件负责沙箱生命周期以及可选的镜像同步。 +在 `remote` 模式下,初始化之后,在 OpenClaw 外部于主机本地所做的编辑不会自动同步进沙箱。 +传输通过 SSH 进入 OpenShell 沙箱,但插件负责沙箱生命周期和可选的镜像同步。 -**`setupCommand`** 会在容器创建后运行一次(通过 `sh -lc`)。它需要网络出口、可写根文件系统以及 root 用户。 +**`setupCommand`** 会在容器创建后运行一次(通过 `sh -lc`)。需要网络出口、可写根文件系统以及 root 用户。 **容器默认使用 `network: "none"`** —— 如果智能体需要出站访问,请设置为 `"bridge"`(或自定义 bridge 网络)。 -`"host"` 会被阻止。默认情况下,`"container:"` 也会被阻止,除非你显式设置 -`sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`(破窗应急)。 +`"host"` 被阻止。默认也会阻止 `"container:"`,除非你显式设置 +`sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`(破玻璃模式)。 -**入站附件** 会被暂存到当前工作区中的 `media/inbound/*`。 +**传入附件** 会被暂存到活动工作区中的 `media/inbound/*`。 -**`docker.binds`** 会挂载额外的宿主机目录;全局和按智能体的绑定会合并。 +**`docker.binds`** 会挂载额外的主机目录;全局和按智能体的 binds 会合并。 -**沙箱隔离浏览器**(`sandbox.browser.enabled`):在容器中运行 Chromium + CDP。noVNC URL 会注入系统提示词。它不要求在 `openclaw.json` 中启用 `browser.enabled`。 -noVNC 观察者访问默认使用 VNC 认证,而 OpenClaw 会发出一个短期有效的 token URL(而不是在共享 URL 中暴露密码)。 +**沙箱隔离浏览器**(`sandbox.browser.enabled`):容器中的 Chromium + CDP。noVNC URL 会注入 system prompt。无需在 `openclaw.json` 中启用 `browser.enabled`。 +默认使用 VNC 认证来提供 noVNC 观察者访问,OpenClaw 会发出一个短时有效的 token URL(而不是在共享 URL 中暴露密码)。 -- `allowHostControl: false`(默认)会阻止沙箱隔离会话以宿主机浏览器为目标。 -- `network` 默认为 `openclaw-sandbox-browser`(专用 bridge 网络)。仅当你明确希望拥有全局 bridge 连通性时,才设置为 `bridge`。 -- `cdpSourceRange` 可选地将容器边缘的 CDP 入站限制为某个 CIDR 范围(例如 `172.21.0.1/32`)。 -- `sandbox.browser.binds` 仅将额外的宿主机目录挂载到沙箱浏览器容器中。设置后(包括 `[]`),它会替换浏览器容器的 `docker.binds`。 -- 启动默认值定义在 `scripts/sandbox-browser-entrypoint.sh` 中,并针对容器宿主环境进行了调优: +- `allowHostControl: false`(默认)会阻止沙箱隔离会话以主机浏览器为目标。 +- `network` 默认为 `openclaw-sandbox-browser`(专用 bridge 网络)。只有在你明确需要全局 bridge 连通性时,才设置为 `bridge`。 +- `cdpSourceRange` 可选择在容器边界处将 CDP 入口限制为某个 CIDR 范围(例如 `172.21.0.1/32`)。 +- `sandbox.browser.binds` 仅会将额外主机目录挂载到沙箱隔离浏览器容器中。设置后(包括 `[]`),它会替换浏览器容器的 `docker.binds`。 +- 启动默认值定义在 `scripts/sandbox-browser-entrypoint.sh` 中,并针对容器主机进行了调优: - `--remote-debugging-address=127.0.0.1` - `--remote-debugging-port=` - `--user-data-dir=${HOME}/.chrome` @@ -1726,14 +1740,14 @@ noVNC 观察者访问默认使用 VNC 认证,而 OpenClaw 会发出一个短 - `--disable-extensions`(默认启用) - `--disable-3d-apis`、`--disable-software-rasterizer` 和 `--disable-gpu` 默认启用;如果 WebGL/3D 使用场景需要,可通过 - `OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0` 禁用这些标志。 - - `OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0` 会重新启用扩展,如果你的工作流 - 依赖它们。 + `OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0` 将其禁用。 + - 如果你的工作流依赖扩展,可通过 + `OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0` 重新启用扩展。 - `--renderer-process-limit=2` 可通过 `OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=` 更改;设置为 `0` 则使用 Chromium 的 默认进程限制。 - - 以及当启用 `noSandbox` 时的 `--no-sandbox` 和 `--disable-setuid-sandbox`。 - - 这些默认值是容器镜像基线;如需更改容器默认值,请使用带有自定义 + - 并且在启用 `noSandbox` 时还会加上 `--no-sandbox` 和 `--disable-setuid-sandbox`。 + - 这些默认值属于容器镜像基线;若要更改容器默认值,请使用带有自定义 entrypoint 的自定义浏览器镜像。 @@ -1743,8 +1757,8 @@ noVNC 观察者访问默认使用 VNC 认证,而 OpenClaw 会发出一个短 构建镜像: ```bash -scripts/sandbox-setup.sh # 主沙箱镜像 -scripts/sandbox-browser-setup.sh # 可选浏览器镜像 +scripts/sandbox-setup.sh # main sandbox image +scripts/sandbox-browser-setup.sh # optional browser image ``` ### `agents.list`(按智能体覆盖) @@ -1759,13 +1773,13 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 name: "Main Agent", workspace: "~/.openclaw/workspace", agentDir: "~/.openclaw/agents/main/agent", - model: "anthropic/claude-opus-4-6", // 或 { primary, fallbacks } - thinkingDefault: "high", // 按智能体的默认 thinking 级别覆盖 - reasoningDefault: "on", // 按智能体的默认 reasoning 可见性覆盖 - fastModeDefault: false, // 按智能体的默认快速模式覆盖 + model: "anthropic/claude-opus-4-6", // or { primary, fallbacks } + thinkingDefault: "high", // per-agent thinking level override + reasoningDefault: "on", // per-agent reasoning visibility override + fastModeDefault: false, // per-agent fast mode override embeddedHarness: { runtime: "auto", fallback: "pi" }, - params: { cacheRetention: "none" }, // 按键覆盖匹配的 defaults.models params - skills: ["docs-search"], // 设置时会替换 agents.defaults.skills + params: { cacheRetention: "none" }, // overrides matching defaults.models params by key + skills: ["docs-search"], // replaces agents.defaults.skills when set identity: { name: "Samantha", theme: "helpful sloth", @@ -1796,27 +1810,27 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 } ``` -- `id`:稳定的智能体 id(必需)。 -- `default`:当设置了多个时,以第一个为准(会记录警告)。若未设置,则列表中的第一个条目为默认值。 -- `model`:字符串形式仅覆盖 `primary`;对象形式 `{ primary, fallbacks }` 会同时覆盖两者(`[]` 会禁用全局回退)。仅覆盖 `primary` 的 cron 任务仍会继承默认回退,除非你设置 `fallbacks: []`。 -- `params`:按智能体划分的流参数,会合并到 `agents.defaults.models` 中选定模型条目之上。将其用于智能体专属覆盖,例如 `cacheRetention`、`temperature` 或 `maxTokens`,而无需复制整个模型目录。 -- `skills`:可选的按智能体 Skills 允许列表。若省略,则当 `agents.defaults.skills` 已设置时,该智能体会继承它;显式列表会替换默认值而不是合并,而 `[]` 表示没有 Skills。 -- `thinkingDefault`:可选的按智能体默认 thinking 级别(`off | minimal | low | medium | high | xhigh | adaptive | max`)。当未设置按消息或按会话覆盖时,它会覆盖该智能体的 `agents.defaults.thinkingDefault`。 -- `reasoningDefault`:可选的按智能体默认 reasoning 可见性(`on | off | stream`)。当未设置按消息或按会话 reasoning 覆盖时生效。 -- `fastModeDefault`:可选的按智能体默认快速模式(`true | false`)。当未设置按消息或按会话快速模式覆盖时生效。 -- `embeddedHarness`:可选的按智能体低层 harness 策略覆盖。使用 `{ runtime: "codex", fallback: "none" }` 可让某个智能体仅使用 Codex,而其他智能体继续保留默认的 PI 回退。 -- `runtime`:可选的按智能体运行时描述符。当智能体应默认使用 ACP harness 会话时,使用 `type: "acp"` 以及 `runtime.acp` 默认值(`agent`、`backend`、`mode`、`cwd`)。 +- `id`:稳定的智能体 ID(必填)。 +- `default`:设置多个时,以第一个为准(会记录警告)。如果都未设置,则列表中的第一个条目为默认值。 +- `model`:字符串形式仅覆盖 `primary`;对象形式 `{ primary, fallbacks }` 会同时覆盖两者(`[]` 可禁用全局 fallbacks)。仅覆盖 `primary` 的 cron 任务仍会继承默认 fallbacks,除非你设置 `fallbacks: []`。 +- `params`:按智能体划分的流式参数,会合并到 `agents.defaults.models` 中选定模型条目之上。用于为特定智能体覆盖如 `cacheRetention`、`temperature` 或 `maxTokens` 等参数,而无需复制整个模型目录。 +- `skills`:可选的按智能体 Skills 允许列表。若省略,当设置了 `agents.defaults.skills` 时,智能体会继承该值;显式列表会替换默认值而不是合并,`[]` 表示没有 Skills。 +- `thinkingDefault`:可选的按智能体默认 thinking 级别(`off | minimal | low | medium | high | xhigh | adaptive | max`)。当未设置按消息或按会话覆盖时,它会覆盖此智能体的 `agents.defaults.thinkingDefault`。 +- `reasoningDefault`:可选的按智能体默认 reasoning 可见性(`on | off | stream`)。当未设置按消息或按会话的 reasoning 覆盖时生效。 +- `fastModeDefault`:可选的按智能体 fast mode 默认值(`true | false`)。当未设置按消息或按会话的 fast-mode 覆盖时生效。 +- `embeddedHarness`:可选的按智能体底层 harness 策略覆盖。使用 `{ runtime: "codex", fallback: "none" }` 可让某一个智能体仅使用 Codex,而其他智能体保留默认的 Pi 回退。 +- `runtime`:可选的按智能体运行时描述符。当智能体应默认使用 ACP harness 会话时,可使用 `type: "acp"` 并设置 `runtime.acp` 默认值(`agent`、`backend`、`mode`、`cwd`)。 - `identity.avatar`:工作区相对路径、`http(s)` URL 或 `data:` URI。 - `identity` 会派生默认值:`ackReaction` 来自 `emoji`,`mentionPatterns` 来自 `name`/`emoji`。 -- `subagents.allowAgents`:用于 `sessions_spawn` 的智能体 id 允许列表(`["*"]` = 任意;默认:仅同一智能体)。 -- 沙箱继承保护:如果请求者会话已启用沙箱隔离,`sessions_spawn` 会拒绝那些将以未启用沙箱方式运行的目标。 -- `subagents.requireAgentId`:为 true 时,会阻止省略 `agentId` 的 `sessions_spawn` 调用(强制显式 profile 选择;默认:false)。 +- `subagents.allowAgents`:`sessions_spawn` 可用的智能体 ID 允许列表(`["*"]` = 任意;默认:仅同一智能体)。 +- 沙箱继承保护:如果请求方会话处于沙箱隔离中,`sessions_spawn` 会拒绝将目标运行在无沙箱模式下。 +- `subagents.requireAgentId`:为 true 时,阻止省略 `agentId` 的 `sessions_spawn` 调用(强制显式选择配置文件;默认:false)。 --- ## 多智能体路由 -在一个 Gateway 网关中运行多个相互隔离的智能体。参见 [多智能体](/zh-CN/concepts/multi-agent)。 +在一个 Gateway 网关内运行多个隔离的智能体。参见 [Multi-Agent](/zh-CN/concepts/multi-agent)。 ```json5 { @@ -1835,12 +1849,12 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 ### 绑定匹配字段 -- `type`(可选):普通路由用 `route`(缺失时默认也是 route),持久 ACP 对话绑定用 `acp`。 -- `match.channel`(必需) +- `type`(可选):`route` 表示常规路由(缺失时默认值为 route),`acp` 表示持久 ACP 会话绑定。 +- `match.channel`(必填) - `match.accountId`(可选;`*` = 任意账号;省略 = 默认账号) - `match.peer`(可选;`{ kind: direct|group|channel, id }`) - `match.guildId` / `match.teamId`(可选;渠道特定) -- `acp`(可选;仅用于 `type: "acp"`):`{ mode, label, cwd, backend }` +- `acp`(可选;仅适用于 `type: "acp"`):`{ mode, label, cwd, backend }` **确定性匹配顺序:** @@ -1851,11 +1865,11 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 5. `match.accountId: "*"`(渠道级) 6. 默认智能体 -在每一层内,首个匹配的 `bindings` 条目胜出。 +在同一层级内,第一个匹配的 `bindings` 条目获胜。 -对于 `type: "acp"` 条目,OpenClaw 会按精确对话身份(`match.channel` + 账号 + `match.peer.id`)进行解析,不使用上面的 route 绑定层级顺序。 +对于 `type: "acp"` 条目,OpenClaw 会按精确会话身份(`match.channel` + 账号 + `match.peer.id`)解析,不使用上面的 route 绑定层级顺序。 -### 按智能体访问配置文件 +### 按智能体划分的访问配置 @@ -1950,7 +1964,7 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 -有关优先级细节,请参见 [多智能体沙箱隔离与工具](/zh-CN/tools/multi-agent-sandbox-tools)。 +优先级详情请参阅 [Multi-Agent Sandbox & Tools](/zh-CN/tools/multi-agent-sandbox-tools)。 --- @@ -1976,22 +1990,22 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 }, resetTriggers: ["/new", "/reset"], store: "~/.openclaw/agents/{agentId}/sessions/sessions.json", - parentForkMaxTokens: 100000, // 当父线程超过此 token 数时跳过父线程 fork(0 表示禁用) + parentForkMaxTokens: 100000, // skip parent-thread fork above this token count (0 disables) maintenance: { mode: "warn", // warn | enforce pruneAfter: "30d", maxEntries: 500, rotateBytes: "10mb", - resetArchiveRetention: "30d", // 时长或 false - maxDiskBytes: "500mb", // 可选硬预算 - highWaterBytes: "400mb", // 可选清理目标 + resetArchiveRetention: "30d", // duration or false + maxDiskBytes: "500mb", // optional hard budget + highWaterBytes: "400mb", // optional cleanup target }, threadBindings: { enabled: true, - idleHours: 24, // 默认按小时计的不活动自动取消聚焦(`0` 表示禁用) - maxAgeHours: 0, // 默认按小时计的硬性最大时长(`0` 表示禁用) + idleHours: 24, // default inactivity auto-unfocus in hours (`0` disables) + maxAgeHours: 0, // default hard max age in hours (`0` disables) }, - mainKey: "main", // 旧版字段(运行时始终使用 "main") + mainKey: "main", // legacy (runtime always uses "main") agentToAgent: { maxPingPongTurns: 5 }, sendPolicy: { rules: [{ action: "deny", match: { channel: "discord", chatType: "group" } }], @@ -2004,34 +2018,34 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 - **`scope`**:群聊上下文的基础会话分组策略。 - - `per-sender`(默认):在某个渠道上下文中,每个发送者都会获得一个隔离的会话。 - - `global`:某个渠道上下文中的所有参与者共享同一个会话(仅在确实需要共享上下文时使用)。 -- **`dmScope`**:私信如何分组。 + - `per-sender`(默认):每个发送者在渠道上下文内拥有独立会话。 + - `global`:渠道上下文中的所有参与者共享同一个会话(仅在确实需要共享上下文时使用)。 +- **`dmScope`**:私信的分组方式。 - `main`:所有私信共享主会话。 - - `per-peer`:按发送者 id 跨渠道隔离。 + - `per-peer`:按发送者 ID 跨渠道隔离。 - `per-channel-peer`:按渠道 + 发送者隔离(推荐用于多用户收件箱)。 - `per-account-channel-peer`:按账号 + 渠道 + 发送者隔离(推荐用于多账号)。 -- **`identityLinks`**:将规范 ID 映射到带提供商前缀的对端,以便跨渠道共享会话。 -- **`reset`**:主重置策略。`daily` 会在本地时间 `atHour` 重置;`idle` 会在 `idleMinutes` 后重置。当两者都已配置时,以先到期者为准。 +- **`identityLinks`**:将规范 ID 映射到带提供商前缀的对端,以实现跨渠道会话共享。 +- **`reset`**:主重置策略。`daily` 会在本地时间 `atHour` 重置;`idle` 会在 `idleMinutes` 后重置。若两者都配置,则先到期者生效。 - **`resetByType`**:按类型覆盖(`direct`、`group`、`thread`)。旧版 `dm` 可作为 `direct` 的别名。 -- **`parentForkMaxTokens`**:创建 fork 线程会话时,允许的父会话 `totalTokens` 最大值(默认 `100000`)。 - - 如果父会话 `totalTokens` 高于此值,OpenClaw 会启动一个新的线程会话,而不是继承父会话的转录历史。 - - 设置为 `0` 可禁用此保护,并始终允许父会话 fork。 -- **`mainKey`**:旧版字段。运行时始终对主私聊桶使用 `"main"`。 -- **`agentToAgent.maxPingPongTurns`**:智能体之间交换消息时,最大回传轮数(整数,范围:`0`–`5`)。`0` 会禁用 ping-pong 链式交互。 -- **`sendPolicy`**:可按 `channel`、`chatType`(`direct|group|channel`,旧版 `dm` 为别名)、`keyPrefix` 或 `rawKeyPrefix` 匹配。首个 deny 规则优先。 +- **`parentForkMaxTokens`**:创建分叉线程会话时,允许的父会话 `totalTokens` 最大值(默认 `100000`)。 + - 如果父会话的 `totalTokens` 超过此值,OpenClaw 会启动一个全新的线程会话,而不是继承父 transcript 历史。 + - 设置为 `0` 可禁用此保护,并始终允许父会话分叉。 +- **`mainKey`**:旧版字段。运行时始终对主直接聊天桶使用 `"main"`。 +- **`agentToAgent.maxPingPongTurns`**:智能体之间在 agent-to-agent 交换期间允许的最大往返回复轮次(整数,范围:`0`–`5`)。`0` 会禁用 ping-pong 链式交互。 +- **`sendPolicy`**:按 `channel`、`chatType`(`direct|group|channel`,旧版 `dm` 为别名)、`keyPrefix` 或 `rawKeyPrefix` 进行匹配。第一个 deny 优先生效。 - **`maintenance`**:会话存储清理 + 保留控制。 - `mode`:`warn` 仅发出警告;`enforce` 会执行清理。 - - `pruneAfter`:陈旧条目的保留期限截止时间(默认 `30d`)。 - - `maxEntries`:`sessions.json` 中条目的最大数量(默认 `500`)。 - - `rotateBytes`:当 `sessions.json` 超过此大小时进行轮换(默认 `10mb`)。 - - `resetArchiveRetention`:`*.reset.` 转录归档的保留期限。默认与 `pruneAfter` 相同;设置为 `false` 可禁用。 - - `maxDiskBytes`:可选的会话目录磁盘预算。在 `warn` 模式下会记录警告;在 `enforce` 模式下会优先删除最旧的工件/会话。 - - `highWaterBytes`:预算清理后的可选目标。默认是 `maxDiskBytes` 的 `80%`。 + - `pruneAfter`:陈旧条目的年龄截止时间(默认 `30d`)。 + - `maxEntries`:`sessions.json` 中的最大条目数(默认 `500`)。 + - `rotateBytes`:当 `sessions.json` 超过此大小时轮转(默认 `10mb`)。 + - `resetArchiveRetention`:`*.reset.` transcript 归档的保留时间。默认继承 `pruneAfter`;设置为 `false` 可禁用。 + - `maxDiskBytes`:可选的 sessions 目录磁盘预算。在 `warn` 模式下会记录警告;在 `enforce` 模式下会优先删除最旧的产物/会话。 + - `highWaterBytes`:预算清理后的可选目标值。默认是 `maxDiskBytes` 的 `80%`。 - **`threadBindings`**:线程绑定会话功能的全局默认值。 - `enabled`:主默认开关(提供商可覆盖;Discord 使用 `channels.discord.threadBindings.enabled`) - - `idleHours`:默认按小时计的不活动自动取消聚焦(`0` 表示禁用;提供商可覆盖) - - `maxAgeHours`:默认按小时计的硬性最大时长(`0` 表示禁用;提供商可覆盖) + - `idleHours`:默认不活动自动取消聚焦时长,单位小时(`0` 表示禁用;提供商可覆盖) + - `maxAgeHours`:默认硬性最大存续时间,单位小时(`0` 表示禁用;提供商可覆盖) @@ -2042,7 +2056,7 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 ```json5 { messages: { - responsePrefix: "🦞", // 或 "auto" + responsePrefix: "🦞", // or "auto" ackReaction: "👀", ackReactionScope: "group-mentions", // group-mentions | group-all | direct | all removeAckAfterReply: false, @@ -2057,7 +2071,7 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 }, }, inbound: { - debounceMs: 2000, // 0 表示禁用 + debounceMs: 2000, // 0 disables byChannel: { whatsapp: 5000, slack: 1500, @@ -2071,34 +2085,34 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 按渠道/账号覆盖:`channels..responsePrefix`、`channels..accounts..responsePrefix`。 -解析顺序(越具体越优先):账号 → 渠道 → 全局。`""` 会禁用并停止继续级联。`"auto"` 会派生为 `[{identity.name}]`。 +解析顺序(越具体越优先):账号 → 渠道 → 全局。`""` 会禁用并停止级联。`"auto"` 会派生为 `[{identity.name}]`。 **模板变量:** -| 变量 | 描述 | 示例 | -| ------------------ | -------------------- | --------------------------- | -| `{model}` | 短模型名 | `claude-opus-4-6` | -| `{modelFull}` | 完整模型标识符 | `anthropic/claude-opus-4-6` | -| `{provider}` | 提供商名称 | `anthropic` | -| `{thinkingLevel}` | 当前 thinking 级别 | `high`、`low`、`off` | -| `{identity.name}` | 智能体身份名称 | (与 `"auto"` 相同) | +| 变量 | 说明 | 示例 | +| ----------------- | -------------- | --------------------------- | +| `{model}` | 短模型名 | `claude-opus-4-6` | +| `{modelFull}` | 完整模型标识符 | `anthropic/claude-opus-4-6` | +| `{provider}` | 提供商名称 | `anthropic` | +| `{thinkingLevel}` | 当前 thinking 级别 | `high`、`low`、`off` | +| `{identity.name}` | 智能体身份名称 | (与 `"auto"` 相同) | 变量不区分大小写。`{think}` 是 `{thinkingLevel}` 的别名。 -### 确认回应 +### 确认反应 -- 默认为当前活跃智能体的 `identity.emoji`,否则为 `"👀"`。设置为 `""` 可禁用。 +- 默认使用当前智能体的 `identity.emoji`,否则为 `"👀"`。设置为 `""` 可禁用。 - 按渠道覆盖:`channels..ackReaction`、`channels..accounts..ackReaction`。 - 解析顺序:账号 → 渠道 → `messages.ackReaction` → identity 回退。 -- 范围:`group-mentions`(默认)、`group-all`、`direct`、`all`。 -- `removeAckAfterReply`:在 Slack、Discord 和 Telegram 上于回复后移除确认回应。 -- `messages.statusReactions.enabled`:在 Slack、Discord 和 Telegram 上启用生命周期状态回应。 - 在 Slack 和 Discord 上,未设置时,如果确认回应处于激活状态,则状态回应保持启用。 - 在 Telegram 上,需要显式设置为 `true` 才会启用生命周期状态回应。 +- 作用范围:`group-mentions`(默认)、`group-all`、`direct`、`all`。 +- `removeAckAfterReply`:在 Slack、Discord 和 Telegram 上,回复后移除确认反应。 +- `messages.statusReactions.enabled`:在 Slack、Discord 和 Telegram 上启用生命周期状态反应。 + 在 Slack 和 Discord 上,未设置时若确认反应处于激活状态,则保持状态反应启用。 + 在 Telegram 上,需要显式将其设置为 `true` 才会启用生命周期状态反应。 -### 入站去抖动 +### 传入去抖动 -将来自同一发送者的快速连续纯文本消息合并为单个智能体轮次。媒体/附件会立即触发刷新。控制命令会绕过去抖动。 +将来自同一发送者的快速纯文本消息批处理为一个智能体轮次。媒体/附件会立即冲刷。控制命令会绕过去抖动。 ### TTS(文本转语音) @@ -2141,12 +2155,12 @@ scripts/sandbox-browser-setup.sh # 可选浏览器镜像 } ``` -- `auto` 控制默认自动 TTS 模式:`off`、`always`、`inbound` 或 `tagged`。`/tts on|off` 可覆盖本地偏好,而 `/tts status` 会显示实际生效状态。 +- `auto` 控制默认自动 TTS 模式:`off`、`always`、`inbound` 或 `tagged`。`/tts on|off` 可覆盖本地偏好,`/tts status` 会显示实际生效状态。 - `summaryModel` 会覆盖用于自动摘要的 `agents.defaults.model.primary`。 -- `modelOverrides` 默认启用;`modelOverrides.allowProvider` 默认值为 `false`(需选择性启用)。 +- `modelOverrides` 默认启用;`modelOverrides.allowProvider` 默认为 `false`(需显式选择加入)。 - API 密钥会回退到 `ELEVENLABS_API_KEY`/`XI_API_KEY` 和 `OPENAI_API_KEY`。 -- `openai.baseUrl` 会覆盖 OpenAI TTS 端点。解析顺序是配置,其次是 `OPENAI_TTS_BASE_URL`,最后是 `https://api.openai.com/v1`。 -- 当 `openai.baseUrl` 指向非 OpenAI 端点时,OpenClaw 会将其视为 OpenAI 兼容 TTS 服务器,并放宽模型/语音校验。 +- `openai.baseUrl` 会覆盖 OpenAI TTS 端点。解析顺序为:配置、然后 `OPENAI_TTS_BASE_URL`、最后 `https://api.openai.com/v1`。 +- 当 `openai.baseUrl` 指向非 OpenAI 端点时,OpenClaw 会将其视为兼容 OpenAI 的 TTS 服务器,并放宽模型/语音校验。 --- @@ -2176,13 +2190,13 @@ Talk 模式(macOS/iOS/Android)的默认值。 } ``` -- 当配置了多个 Talk 提供商时,`talk.provider` 必须匹配 `talk.providers` 中的一个键。 -- 旧版扁平 Talk 键(`talk.voiceId`、`talk.voiceAliases`、`talk.modelId`、`talk.outputFormat`、`talk.apiKey`)仅用于兼容,并会自动迁移到 `talk.providers.`。 +- 当配置了多个 Talk 提供商时,`talk.provider` 必须匹配 `talk.providers` 中的某个键。 +- 旧版扁平 Talk 键(`talk.voiceId`、`talk.voiceAliases`、`talk.modelId`、`talk.outputFormat`、`talk.apiKey`)仅用于兼容,会被自动迁移到 `talk.providers.`。 - 语音 ID 会回退到 `ELEVENLABS_VOICE_ID` 或 `SAG_VOICE_ID`。 -- `providers.*.apiKey` 接受纯文本字符串或 SecretRef 对象。 -- 仅当未配置 Talk API 密钥时,才会应用 `ELEVENLABS_API_KEY` 回退。 -- `providers.*.voiceAliases` 允许 Talk 指令使用友好的名称。 -- `silenceTimeoutMs` 控制 Talk 模式在用户静音后等待多久才发送转录。未设置时会保留平台默认暂停窗口(`macOS 和 Android 为 700 ms,iOS 为 900 ms`)。 +- `providers.*.apiKey` 接受明文字符串或 SecretRef 对象。 +- 仅在未配置 Talk API 密钥时,才会应用 `ELEVENLABS_API_KEY` 回退。 +- `providers.*.voiceAliases` 允许 Talk 指令使用友好名称。 +- `silenceTimeoutMs` 控制 Talk 模式在用户静默后等待多久再发送转录。未设置时保留平台默认暂停窗口(`macOS 和 Android 为 700 ms,iOS 为 900 ms`)。 --- @@ -2190,37 +2204,37 @@ Talk 模式(macOS/iOS/Android)的默认值。 ### 工具配置文件 -`tools.profile` 会在 `tools.allow`/`tools.deny` 之前设置基础允许列表: +`tools.profile` 会在 `tools.allow`/`tools.deny` 之前设置一个基础允许列表: -当未设置时,本地新手引导默认将新的本地配置设为 `tools.profile: "coding"`(现有显式配置文件会保留)。 +本地新手引导会在未设置时,将新的本地配置默认设为 `tools.profile: "coding"`(已有的显式 profile 会被保留)。 -| 配置文件 | 包含内容 | -| ----------- | --------------------------------------------------------------------------------------------------------------------------------- | -| `minimal` | 仅 `session_status` | -| `coding` | `group:fs`、`group:runtime`、`group:web`、`group:sessions`、`group:memory`、`cron`、`image`、`image_generate`、`video_generate` | -| `messaging` | `group:messaging`、`sessions_list`、`sessions_history`、`sessions_send`、`session_status` | -| `full` | 无限制(与未设置相同) | +| 配置文件 | 包含内容 | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------- | +| `minimal` | 仅 `session_status` | +| `coding` | `group:fs`、`group:runtime`、`group:web`、`group:sessions`、`group:memory`、`cron`、`image`、`image_generate`、`video_generate` | +| `messaging` | `group:messaging`、`sessions_list`、`sessions_history`、`sessions_send`、`session_status` | +| `full` | 无限制(与未设置相同) | ### 工具组 -| 组 | 工具 | -| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `group:runtime` | `exec`、`process`、`code_execution`(`bash` 可作为 `exec` 的别名) | -| `group:fs` | `read`、`write`、`edit`、`apply_patch` | -| `group:sessions` | `sessions_list`、`sessions_history`、`sessions_send`、`sessions_spawn`、`sessions_yield`、`subagents`、`session_status` | -| `group:memory` | `memory_search`、`memory_get` | -| `group:web` | `web_search`、`x_search`、`web_fetch` | -| `group:ui` | `browser`、`canvas` | -| `group:automation` | `cron`、`gateway` | -| `group:messaging` | `message` | -| `group:nodes` | `nodes` | -| `group:agents` | `agents_list` | -| `group:media` | `image`、`image_generate`、`video_generate`、`tts` | -| `group:openclaw` | 所有内置工具(不包括提供商插件) | +| 组 | 工具 | +| ------------------ | --------------------------------------------------------------------------------------------------------------------- | +| `group:runtime` | `exec`、`process`、`code_execution`(`bash` 可作为 `exec` 的别名) | +| `group:fs` | `read`、`write`、`edit`、`apply_patch` | +| `group:sessions` | `sessions_list`、`sessions_history`、`sessions_send`、`sessions_spawn`、`sessions_yield`、`subagents`、`session_status` | +| `group:memory` | `memory_search`、`memory_get` | +| `group:web` | `web_search`、`x_search`、`web_fetch` | +| `group:ui` | `browser`、`canvas` | +| `group:automation` | `cron`、`gateway` | +| `group:messaging` | `message` | +| `group:nodes` | `nodes` | +| `group:agents` | `agents_list` | +| `group:media` | `image`、`image_generate`、`video_generate`、`tts` | +| `group:openclaw` | 所有内置工具(不包括 provider 插件) | ### `tools.allow` / `tools.deny` -全局工具允许/拒绝策略(deny 优先)。不区分大小写,并支持 `*` 通配符。即使 Docker 沙箱隔离关闭时也会应用。 +全局工具允许/拒绝策略(拒绝优先)。不区分大小写,支持 `*` 通配符。即使 Docker 沙箱已关闭,也会应用。 ```json5 { @@ -2230,7 +2244,7 @@ Talk 模式(macOS/iOS/Android)的默认值。 ### `tools.byProvider` -进一步限制特定提供商或模型可用的工具。顺序:基础配置文件 → 提供商配置文件 → allow/deny。 +进一步限制特定 provider 或模型可用的工具。顺序:基础 profile → provider profile → allow/deny。 ```json5 { @@ -2246,7 +2260,7 @@ Talk 模式(macOS/iOS/Android)的默认值。 ### `tools.elevated` -控制沙箱之外的高级 exec 访问: +控制沙箱外部的提升 exec 访问: ```json5 { @@ -2263,8 +2277,8 @@ Talk 模式(macOS/iOS/Android)的默认值。 ``` - 按智能体覆盖(`agents.list[].tools.elevated`)只能进一步收紧限制。 -- `/elevated on|off|ask|full` 会按会话存储状态;内联指令仅对单条消息生效。 -- 高级 `exec` 会绕过沙箱隔离,并使用已配置的逃逸路径(默认为 `gateway`,或当 exec 目标为 `node` 时使用 `node`)。 +- `/elevated on|off|ask|full` 会按会话存储状态;内联指令只对单条消息生效。 +- 提升后的 `exec` 会绕过沙箱隔离,并使用已配置的逃逸路径(默认是 `gateway`,当 exec 目标是 `node` 时则为 `node`)。 ### `tools.exec` @@ -2288,8 +2302,8 @@ Talk 模式(macOS/iOS/Android)的默认值。 ### `tools.loopDetection` -工具循环安全检查默认**禁用**。设置 `enabled: true` 可启用检测。 -设置可在 `tools.loopDetection` 中全局定义,并在 `agents.list[].tools.loopDetection` 中按智能体覆盖。 +工具循环安全检查默认**关闭**。设置 `enabled: true` 可启用检测。 +设置可以在全局 `tools.loopDetection` 中定义,也可以在按智能体的 `agents.list[].tools.loopDetection` 中覆盖。 ```json5 { @@ -2310,14 +2324,14 @@ Talk 模式(macOS/iOS/Android)的默认值。 } ``` -- `historySize`:为循环分析保留的最大工具调用历史记录。 -- `warningThreshold`:对重复无进展模式发出警告的阈值。 -- `criticalThreshold`:阻止严重循环的更高重复阈值。 -- `globalCircuitBreakerThreshold`:对任何无进展运行执行硬停止的阈值。 +- `historySize`:为循环分析保留的最大工具调用历史数。 +- `warningThreshold`:触发警告的重复无进展模式阈值。 +- `criticalThreshold`:用于阻止严重循环的更高重复阈值。 +- `globalCircuitBreakerThreshold`:针对任意无进展运行的硬停止阈值。 - `detectors.genericRepeat`:对重复的同工具/同参数调用发出警告。 - `detectors.knownPollNoProgress`:对已知轮询工具(`process.poll`、`command_status` 等)的无进展情况发出警告/阻止。 -- `detectors.pingPong`:对交替出现的无进展双模式发出警告/阻止。 -- 如果 `warningThreshold >= criticalThreshold` 或 `criticalThreshold >= globalCircuitBreakerThreshold`,验证将失败。 +- `detectors.pingPong`:对交替出现的无进展配对模式发出警告/阻止。 +- 如果 `warningThreshold >= criticalThreshold` 或 `criticalThreshold >= globalCircuitBreakerThreshold`,验证会失败。 ### `tools.web` @@ -2327,14 +2341,14 @@ Talk 模式(macOS/iOS/Android)的默认值。 web: { search: { enabled: true, - apiKey: "brave_api_key", // 或 BRAVE_API_KEY 环境变量 + apiKey: "brave_api_key", // or BRAVE_API_KEY env maxResults: 5, timeoutSeconds: 30, cacheTtlMinutes: 15, }, fetch: { enabled: true, - provider: "firecrawl", // 可选;省略则自动检测 + provider: "firecrawl", // optional; omit for auto-detect maxChars: 50000, maxCharsCap: 50000, maxResponseBytes: 2000000, @@ -2351,7 +2365,7 @@ Talk 模式(macOS/iOS/Android)的默认值。 ### `tools.media` -配置入站媒体理解(图像/音频/视频): +配置传入媒体理解(图像/音频/视频): ```json5 { @@ -2359,7 +2373,7 @@ Talk 模式(macOS/iOS/Android)的默认值。 media: { concurrency: 2, asyncCompletion: { - directSend: false, // 选择性启用:将完成的异步音乐/视频直接发送到渠道 + directSend: false, // opt-in: send finished async music/video directly to the channel }, audio: { enabled: true, @@ -2385,10 +2399,10 @@ Talk 模式(macOS/iOS/Android)的默认值。 -**提供商条目**(`type: "provider"` 或省略): +**Provider 条目**(`type: "provider"` 或省略): -- `provider`:API 提供商 id(`openai`、`anthropic`、`google`/`gemini`、`groq` 等) -- `model`:模型 id 覆盖 +- `provider`:API 提供商 ID(`openai`、`anthropic`、`google`/`gemini`、`groq` 等) +- `model`:模型 ID 覆盖 - `profile` / `preferredProfile`:`auth-profiles.json` 配置文件选择 **CLI 条目**(`type: "cli"`): @@ -2398,7 +2412,7 @@ Talk 模式(macOS/iOS/Android)的默认值。 **通用字段:** -- `capabilities`:可选列表(`image`、`audio`、`video`)。默认值:`openai`/`anthropic`/`minimax` → 图像,`google` → 图像+音频+视频,`groq` → 音频。 +- `capabilities`:可选列表(`image`、`audio`、`video`)。默认值:`openai`/`anthropic`/`minimax` → image,`google` → image+audio+video,`groq` → audio。 - `prompt`、`maxChars`、`maxBytes`、`timeoutSeconds`、`language`:按条目覆盖。 - 失败时会回退到下一个条目。 @@ -2406,9 +2420,9 @@ Talk 模式(macOS/iOS/Android)的默认值。 **异步完成字段:** -- `asyncCompletion.directSend`:为 `true` 时,已完成的异步 `music_generate` - 和 `video_generate` 任务会优先尝试直接投递到渠道。默认值:`false` - (旧版请求者会话唤醒/模型投递路径)。 +- `asyncCompletion.directSend`:当为 `true` 时,已完成的异步 `music_generate` + 和 `video_generate` 任务会先尝试直接投递到渠道。默认值:`false` + (旧版请求方会话唤醒/模型投递路径)。 @@ -2429,7 +2443,7 @@ Talk 模式(macOS/iOS/Android)的默认值。 控制会话工具(`sessions_list`、`sessions_history`、`sessions_send`)可以定位哪些会话。 -默认值:`tree`(当前会话 + 由其生成的会话,例如子智能体)。 +默认值:`tree`(当前会话 + 由它派生的会话,例如子智能体)。 ```json5 { @@ -2445,10 +2459,10 @@ Talk 模式(macOS/iOS/Android)的默认值。 说明: - `self`:仅当前会话键。 -- `tree`:当前会话 + 由当前会话生成的会话(子智能体)。 -- `agent`:属于当前智能体 id 的任意会话(如果你在同一个智能体 id 下按发送者运行会话,可能包含其他用户)。 -- `all`:任意会话。跨智能体定位仍需要 `tools.agentToAgent`。 -- 沙箱限制:当当前会话已启用沙箱隔离,且 `agents.defaults.sandbox.sessionToolsVisibility="spawned"` 时,即使 `tools.sessions.visibility="all"`,可见性也会被强制为 `tree`。 +- `tree`:当前会话 + 由当前会话派生的会话(子智能体)。 +- `agent`:属于当前智能体 ID 的任意会话(如果你在同一个智能体 ID 下运行按发送者划分的会话,则可能包含其他用户)。 +- `all`:任意会话。跨智能体定位仍然需要 `tools.agentToAgent`。 +- 沙箱限制:当当前会话处于沙箱隔离中且 `agents.defaults.sandbox.sessionToolsVisibility="spawned"` 时,即使 `tools.sessions.visibility="all"`,可见性也会被强制为 `tree`。 ### `tools.sessions_spawn` @@ -2459,11 +2473,11 @@ Talk 模式(macOS/iOS/Android)的默认值。 tools: { sessions_spawn: { attachments: { - enabled: false, // 选择性启用:设置为 true 以允许内联文件附件 - maxTotalBytes: 5242880, // 所有文件总计 5 MB + enabled: false, // opt-in: set true to allow inline file attachments + maxTotalBytes: 5242880, // 5 MB total across all files maxFiles: 50, - maxFileBytes: 1048576, // 每个文件 1 MB - retainOnSessionKeep: false, // 当 cleanup="keep" 时保留附件 + maxFileBytes: 1048576, // 1 MB per file + retainOnSessionKeep: false, // keep attachments when cleanup="keep" }, }, }, @@ -2472,24 +2486,24 @@ Talk 模式(macOS/iOS/Android)的默认值。 说明: -- 仅 `runtime: "subagent"` 支持附件。ACP 运行时会拒绝它们。 -- 文件会以 `.openclaw/attachments//` 的形式物化到子工作区中,并附带一个 `.manifest.json`。 -- 附件内容会自动从转录持久化中脱敏。 +- 附件仅支持 `runtime: "subagent"`。ACP 运行时会拒绝它们。 +- 文件会实体化到子工作区中的 `.openclaw/attachments//`,并附带一个 `.manifest.json`。 +- 附件内容会自动从 transcript 持久化中脱敏。 - Base64 输入会使用严格的字母表/填充检查以及解码前大小保护进行验证。 -- 文件权限为目录 `0700`、文件 `0600`。 -- 清理遵循 `cleanup` 策略:`delete` 始终会删除附件;只有在 `retainOnSessionKeep: true` 时,`keep` 才会保留它们。 +- 目录权限为 `0700`,文件权限为 `0600`。 +- 清理由 `cleanup` 策略控制:`delete` 总会删除附件;`keep` 仅在 `retainOnSessionKeep: true` 时保留它们。 ### `tools.experimental` -实验性内置工具标志。默认关闭,除非适用了严格智能体式 GPT-5 自动启用规则。 +实验性内置工具标志。默认关闭,除非适用了 strict-agentic GPT-5 自动启用规则。 ```json5 { tools: { experimental: { - planTool: true, // 启用实验性的 update_plan + planTool: true, // enable experimental update_plan }, }, } @@ -2497,9 +2511,9 @@ Talk 模式(macOS/iOS/Android)的默认值。 说明: -- `planTool`:为非平凡多步骤工作跟踪启用结构化 `update_plan` 工具。 -- 默认值:`false`,除非 `agents.defaults.embeddedPi.executionContract`(或按智能体覆盖)被设置为 OpenAI 或 OpenAI Codex GPT-5 系列运行的 `"strict-agentic"`。设置为 `true` 可在该范围外强制启用此工具,设置为 `false` 则即使对 strict-agentic GPT-5 运行也会保持关闭。 -- 启用后,系统提示词还会添加使用指导,以便模型仅在实质性工作中使用它,并始终最多只保留一个 `in_progress` 步骤。 +- `planTool`:为非平凡的多步骤工作跟踪启用结构化 `update_plan` 工具。 +- 默认值:`false`,除非 `agents.defaults.embeddedPi.executionContract`(或按智能体覆盖)被设置为 `"strict-agentic"`,且当前运行是 OpenAI 或 OpenAI Codex 的 GPT-5 家族模型。设置为 `true` 可在该范围之外强制启用该工具,设置为 `false` 则即使在 strict-agentic GPT-5 运行中也保持关闭。 +- 启用后,system prompt 还会添加使用指导,以便模型仅在重要工作中使用它,并且最多只保留一个 `in_progress` 步骤。 ### `agents.defaults.subagents` @@ -2519,21 +2533,21 @@ Talk 模式(macOS/iOS/Android)的默认值。 } ``` -- `model`:已生成子智能体的默认模型。如果省略,子智能体会继承调用方的模型。 -- `allowAgents`:当请求方智能体未设置自己的 `subagents.allowAgents` 时,`sessions_spawn` 允许的目标智能体 id 默认允许列表(`["*"]` = 任意;默认:仅同一智能体)。 -- `runTimeoutSeconds`:当工具调用省略 `runTimeoutSeconds` 时,`sessions_spawn` 使用的默认超时时间(秒)。`0` 表示无超时。 -- 按子智能体的工具策略:`tools.subagents.tools.allow` / `tools.subagents.tools.deny`。 +- `model`:派生子智能体的默认模型。如果省略,子智能体会继承调用方的模型。 +- `allowAgents`:当请求方智能体未设置自己的 `subagents.allowAgents` 时,`sessions_spawn` 使用的目标智能体 ID 默认允许列表(`["*"]` = 任意;默认:仅同一智能体)。 +- `runTimeoutSeconds`:当工具调用省略 `runTimeoutSeconds` 时,`sessions_spawn` 使用的默认超时(秒)。`0` 表示无超时。 +- 按子智能体划分的工具策略:`tools.subagents.tools.allow` / `tools.subagents.tools.deny`。 --- ## 自定义提供商和 base URL -OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 `~/.openclaw/agents//agent/models.json` 添加自定义提供商。 +OpenClaw 使用内置模型目录。通过配置中的 `models.providers` 或 `~/.openclaw/agents//agent/models.json` 添加自定义提供商。 ```json5 { models: { - mode: "merge", // merge(默认)| replace + mode: "merge", // merge (default) | replace providers: { "custom-proxy": { baseUrl: "http://localhost:4000/v1", @@ -2558,50 +2572,50 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 ``` - 对于自定义认证需求,请使用 `authHeader: true` + `headers`。 -- 使用 `OPENCLAW_AGENT_DIR` 覆盖智能体配置根目录(或使用 `PI_CODING_AGENT_DIR`,这是旧版环境变量别名)。 -- 对于匹配的提供商 ID,合并优先级如下: +- 使用 `OPENCLAW_AGENT_DIR` 覆盖智能体配置根目录(或使用其旧版环境变量别名 `PI_CODING_AGENT_DIR`)。 +- 对于匹配的 provider ID,合并优先级如下: - 非空的智能体 `models.json` `baseUrl` 值优先。 - - 非空的智能体 `apiKey` 值仅在该提供商在当前配置/auth-profile 上下文中**不是** SecretRef 管理时优先。 - - 由 SecretRef 管理的提供商 `apiKey` 值会从源标记刷新(环境引用为 `ENV_VAR_NAME`,文件/exec 引用为 `secretref-managed`),而不是持久化已解析的密钥。 - - 由 SecretRef 管理的提供商 header 值会从源标记刷新(环境引用为 `secretref-env:ENV_VAR_NAME`,文件/exec 引用为 `secretref-managed`)。 - - 空或缺失的智能体 `apiKey`/`baseUrl` 会回退到配置中的 `models.providers`。 - - 对于匹配模型的 `contextWindow`/`maxTokens`,会在显式配置值和隐式目录值之间采用较高者。 - - 对于匹配模型的 `contextTokens`,若存在显式运行时上限,则会保留;当你想限制实际上下文而不修改原生模型元数据时,请使用它。 - - 当你希望配置完全重写 `models.json` 时,请使用 `models.mode: "replace"`。 - - 标记持久化以源为准:标记来自当前生效的源配置快照(解析前),而不是来自已解析的运行时密钥值。 + - 非空的智能体 `apiKey` 值仅在该提供商在当前 config/auth-profile 上下文中不是由 SecretRef 管理时优先。 + - 由 SecretRef 管理的提供商 `apiKey` 值会根据来源标记刷新(环境变量引用使用 `ENV_VAR_NAME`,文件/exec 引用使用 `secretref-managed`),而不是持久化已解析的 secret。 + - 由 SecretRef 管理的提供商 header 值会根据来源标记刷新(环境变量引用使用 `secretref-env:ENV_VAR_NAME`,文件/exec 引用使用 `secretref-managed`)。 + - 空的或缺失的智能体 `apiKey`/`baseUrl` 会回退到配置中的 `models.providers`。 + - 匹配模型的 `contextWindow`/`maxTokens` 会在显式配置值和隐式目录值之间取较高者。 + - 匹配模型的 `contextTokens` 会在存在时保留显式运行时上限;当你希望限制实际上下文而不更改模型原生元数据时,请使用它。 + - 当你希望让配置完全重写 `models.json` 时,请使用 `models.mode: "replace"`。 + - 标记持久化以来源为准:标记从活动来源配置快照(解析前)写入,而不是从已解析的运行时 secret 值写入。 -### 提供商字段详情 +### Provider 字段详情 - `models.mode`:提供商目录行为(`merge` 或 `replace`)。 -- `models.providers`:按提供商 id 为键的自定义提供商映射。 - - 安全编辑方式:对增量更新,请使用 `openclaw config set models.providers. '' --strict-json --merge` 或 `openclaw config set models.providers..models '' --strict-json --merge`。`config set` 会拒绝破坏性替换,除非你传入 `--replace`。 +- `models.providers`:以 provider ID 为键的自定义提供商映射。 + - 安全编辑:使用 `openclaw config set models.providers. '' --strict-json --merge` 或 `openclaw config set models.providers..models '' --strict-json --merge` 进行增量更新。除非你传入 `--replace`,否则 `config set` 会拒绝破坏性替换。 - `models.providers.*.api`:请求适配器(`openai-completions`、`openai-responses`、`anthropic-messages`、`google-generative-ai` 等)。 - `models.providers.*.apiKey`:提供商凭证(优先使用 SecretRef/环境变量替换)。 - `models.providers.*.auth`:认证策略(`api-key`、`token`、`oauth`、`aws-sdk`)。 -- `models.providers.*.injectNumCtxForOpenAICompat`:对于 Ollama + `openai-completions`,向请求中注入 `options.num_ctx`(默认:`true`)。 +- `models.providers.*.injectNumCtxForOpenAICompat`:对于 Ollama + `openai-completions`,将 `options.num_ctx` 注入请求(默认:`true`)。 - `models.providers.*.authHeader`:在需要时强制通过 `Authorization` header 传输凭证。 - `models.providers.*.baseUrl`:上游 API base URL。 - `models.providers.*.headers`:用于代理/租户路由的额外静态 headers。 - `models.providers.*.request`:模型提供商 HTTP 请求的传输覆盖。 - `request.headers`:额外 headers(与提供商默认值合并)。值接受 SecretRef。 - - `request.auth`:认证策略覆盖。模式:`"provider-default"`(使用提供商内置认证)、`"authorization-bearer"`(配合 `token`)、`"header"`(配合 `headerName`、`value` 和可选 `prefix`)。 - - `request.proxy`:HTTP 代理覆盖。模式:`"env-proxy"`(使用 `HTTP_PROXY`/`HTTPS_PROXY` 环境变量)、`"explicit-proxy"`(配合 `url`)。两种模式都接受可选的 `tls` 子对象。 - - `request.tls`:直连时的 TLS 覆盖。字段:`ca`、`cert`、`key`、`passphrase`(全部接受 SecretRef)、`serverName`、`insecureSkipVerify`。 - - `request.allowPrivateNetwork`:为 `true` 时,当 DNS 解析到私有、CGNAT 或类似范围时,允许通过提供商 HTTP 获取保护访问 `baseUrl` 的 HTTPS(这是对受信任的自托管 OpenAI 兼容端点的 operator 选择性启用)。WebSocket 使用相同的 `request` 来处理 headers/TLS,但不使用该 fetch SSRF 保护。默认值为 `false`。 -- `models.providers.*.models`:显式的提供商模型目录条目。 -- `models.providers.*.models.*.contextWindow`:原生模型上下文窗口元数据。 + - `request.auth`:认证策略覆盖。模式:`"provider-default"`(使用提供商内置认证)、`"authorization-bearer"`(搭配 `token`)、`"header"`(搭配 `headerName`、`value` 和可选 `prefix`)。 + - `request.proxy`:HTTP 代理覆盖。模式:`"env-proxy"`(使用 `HTTP_PROXY`/`HTTPS_PROXY` 环境变量)、`"explicit-proxy"`(搭配 `url`)。两种模式都接受可选的 `tls` 子对象。 + - `request.tls`:直连时的 TLS 覆盖。字段:`ca`、`cert`、`key`、`passphrase`(均接受 SecretRef)、`serverName`、`insecureSkipVerify`。 + - `request.allowPrivateNetwork`:为 `true` 时,当 DNS 解析到私有、CGNAT 或类似地址范围时,允许通过 provider HTTP 获取保护对 `baseUrl` 执行 HTTPS 访问(适用于受信任、自托管、兼容 OpenAI 端点的 operator 选择加入)。WebSocket 会对 headers/TLS 使用相同的 `request`,但不会使用该获取 SSRF 防护。默认值 `false`。 +- `models.providers.*.models`:显式提供商模型目录条目。 +- `models.providers.*.models.*.contextWindow`:模型原生上下文窗口元数据。 - `models.providers.*.models.*.contextTokens`:可选的运行时上下文上限。当你希望实际上下文预算小于模型原生 `contextWindow` 时,请使用它。 -- `models.providers.*.models.*.compat.supportsDeveloperRole`:可选的兼容性提示。对于 `api: "openai-completions"` 且存在非空的非原生 `baseUrl`(主机不是 `api.openai.com`),OpenClaw 会在运行时将其强制设为 `false`。空或省略的 `baseUrl` 会保留默认 OpenAI 行为。 -- `models.providers.*.models.*.compat.requiresStringContent`:面向仅支持字符串内容的 OpenAI 兼容聊天端点的可选兼容性提示。为 `true` 时,OpenClaw 会在发送请求前,将纯文本 `messages[].content` 数组压平成普通字符串。 -- `plugins.entries.amazon-bedrock.config.discovery`:Bedrock 自动发现设置根。 +- `models.providers.*.models.*.compat.supportsDeveloperRole`:可选兼容性提示。对于 `api: "openai-completions"` 且存在非空、非原生 `baseUrl`(host 不是 `api.openai.com`)的情况,OpenClaw 会在运行时强制将其设为 `false`。空的/省略的 `baseUrl` 会保留默认 OpenAI 行为。 +- `models.providers.*.models.*.compat.requiresStringContent`:用于仅接受字符串的兼容 OpenAI 聊天端点的可选兼容性提示。为 `true` 时,OpenClaw 会在发送请求前,将纯文本 `messages[].content` 数组展平成普通字符串。 +- `plugins.entries.amazon-bedrock.config.discovery`:Bedrock 自动发现设置根路径。 - `plugins.entries.amazon-bedrock.config.discovery.enabled`:开启/关闭隐式发现。 - `plugins.entries.amazon-bedrock.config.discovery.region`:用于发现的 AWS 区域。 - `plugins.entries.amazon-bedrock.config.discovery.providerFilter`:用于定向发现的可选 provider-id 过滤器。 - `plugins.entries.amazon-bedrock.config.discovery.refreshInterval`:发现刷新轮询间隔。 -- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`:已发现模型的回退上下文窗口。 -- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`:已发现模型的回退最大输出 token 数。 +- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`:已发现模型的后备上下文窗口。 +- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`:已发现模型的后备最大输出 token 数。 -### 提供商示例 +### Provider 示例 @@ -2637,7 +2651,7 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 } ``` -对 Cerebras 使用 `cerebras/zai-glm-4.7`;对 Z.AI 直连使用 `zai/glm-4.7`。 +Cerebras 请使用 `cerebras/zai-glm-4.7`;Z.AI 直连请使用 `zai/glm-4.7`。 @@ -2654,7 +2668,7 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 } ``` -设置 `OPENCODE_API_KEY`(或 `OPENCODE_ZEN_API_KEY`)。对 Zen 目录使用 `opencode/...` 引用,对 Go 目录使用 `opencode-go/...` 引用。快捷方式:`openclaw onboard --auth-choice opencode-zen` 或 `openclaw onboard --auth-choice opencode-go`。 +设置 `OPENCODE_API_KEY`(或 `OPENCODE_ZEN_API_KEY`)。Zen 目录使用 `opencode/...` 引用,Go 目录使用 `opencode-go/...` 引用。快捷方式:`openclaw onboard --auth-choice opencode-zen` 或 `openclaw onboard --auth-choice opencode-go`。 @@ -2671,11 +2685,11 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 } ``` -设置 `ZAI_API_KEY`。`z.ai/*` 和 `z-ai/*` 都是可接受的别名。快捷方式:`openclaw onboard --auth-choice zai-api-key`。 +设置 `ZAI_API_KEY`。`z.ai/*` 和 `z-ai/*` 都是接受的别名。快捷方式:`openclaw onboard --auth-choice zai-api-key`。 - 通用端点:`https://api.z.ai/api/paas/v4` -- 编码端点(默认):`https://api.z.ai/api/coding/paas/v4` -- 对于通用端点,请定义带有 base URL 覆盖的自定义提供商。 +- Coding 端点(默认):`https://api.z.ai/api/coding/paas/v4` +- 如需使用通用端点,请定义一个带有 base URL 覆盖的自定义提供商。 @@ -2714,11 +2728,11 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 } ``` -对于中国端点:`baseUrl: "https://api.moonshot.cn/v1"` 或 `openclaw onboard --auth-choice moonshot-api-key-cn`。 +中国区端点:`baseUrl: "https://api.moonshot.cn/v1"` 或 `openclaw onboard --auth-choice moonshot-api-key-cn`。 原生 Moonshot 端点会在共享的 -`openai-completions` 传输上声明流式用量兼容性,而 OpenClaw 会根据端点能力 -而不只是内置提供商 id 来处理这一点。 +`openai-completions` 传输上声明流式 usage 兼容性,OpenClaw 会根据端点能力 +而不仅仅是内置 provider ID 来决定该行为。 @@ -2736,11 +2750,11 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 } ``` -兼容 Anthropic 的内置提供商。快捷方式:`openclaw onboard --auth-choice kimi-code-api-key`。 +兼容 Anthropic,内置 provider。快捷方式:`openclaw onboard --auth-choice kimi-code-api-key`。 - + ```json5 { @@ -2775,7 +2789,7 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或 } ``` -Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷方式:`openclaw onboard --auth-choice synthetic-api-key`。 +base URL 不应包含 `/v1`(Anthropic 客户端会自行追加)。快捷方式:`openclaw onboard --auth-choice synthetic-api-key`。 @@ -2819,16 +2833,15 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 `openclaw onboard --auth-choice minimax-global-api` 或 `openclaw onboard --auth-choice minimax-cn-api`。 模型目录默认仅包含 M2.7。 -在 Anthropic 兼容的流式传输路径上,除非你显式设置 `thinking`,否则 OpenClaw -默认会禁用 MiniMax thinking。`/fast on` 或 -`params.fastMode: true` 会将 `MiniMax-M2.7` 重写为 +在兼容 Anthropic 的流式传输路径上,除非你显式设置 `thinking`,否则 OpenClaw 默认会禁用 MiniMax thinking。 +`/fast on` 或 `params.fastMode: true` 会将 `MiniMax-M2.7` 重写为 `MiniMax-M2.7-highspeed`。 -参见 [本地模型](/zh-CN/gateway/local-models)。简而言之:在强劲硬件上通过 LM Studio Responses API 运行大型本地模型;同时保持托管模型合并,以便回退。 +请参阅 [Local Models](/zh-CN/gateway/local-models)。简而言之:在性能充足的硬件上通过 LM Studio Responses API 运行大型本地模型;同时保留已合并的托管模型作为回退。 @@ -2849,7 +2862,7 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 }, entries: { "image-lab": { - apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // 或纯文本字符串 + apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // or plaintext string env: { GEMINI_API_KEY: "GEMINI_KEY_HERE" }, }, peekaboo: { enabled: true }, @@ -2859,13 +2872,13 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 } ``` -- `allowBundled`:仅针对内置 Skills 的可选允许列表(受管/工作区 Skills 不受影响)。 -- `load.extraDirs`:额外的共享 Skills 根目录(优先级最低)。 +- `allowBundled`:仅对内置 Skills 生效的可选允许列表(托管/工作区 Skills 不受影响)。 +- `load.extraDirs`:额外的共享 Skills 根目录(最低优先级)。 - `install.preferBrew`:为 true 时,如果 `brew` 可用,则优先使用 Homebrew 安装器,然后才回退到其他安装器类型。 - `install.nodeManager`:用于 `metadata.openclaw.install` - 规范的 node 安装器偏好(`npm` | `pnpm` | `yarn` | `bun`)。 -- `entries..enabled: false`:即使 Skill 已内置/已安装,也会禁用它。 -- `entries..apiKey`:为声明了主环境变量的 Skills 提供的便捷字段(纯文本字符串或 SecretRef 对象)。 + 规范的 Node 安装器偏好(`npm` | `pnpm` | `yarn` | `bun`)。 +- `entries..enabled: false`:即使某个 Skill 已内置/已安装,也会禁用它。 +- `entries..apiKey`:为声明了主环境变量的 Skills 提供的便捷字段(明文字符串或 SecretRef 对象)。 --- @@ -2894,42 +2907,42 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 ``` - 从 `~/.openclaw/extensions`、`/.openclaw/extensions` 以及 `plugins.load.paths` 加载。 -- 设备发现支持原生 OpenClaw 插件,以及兼容的 Codex bundles 和 Claude bundles,包括无 manifest 的 Claude 默认布局 bundles。 +- 发现机制接受原生 OpenClaw 插件,以及兼容的 Codex bundle 和 Claude bundle,包括无 manifest 的 Claude 默认布局 bundle。 - **配置更改需要重启 Gateway 网关。** -- `allow`:可选允许列表(仅加载列出的插件)。`deny` 优先。 +- `allow`:可选允许列表(仅加载列出的插件)。`deny` 优先生效。 - `plugins.entries..apiKey`:插件级 API 密钥便捷字段(当插件支持时)。 - `plugins.entries..env`:插件作用域环境变量映射。 -- `plugins.entries..hooks.allowPromptInjection`:为 `false` 时,核心会阻止 `before_prompt_build`,并忽略旧版 `before_agent_start` 中会修改提示词的字段,同时保留旧版 `modelOverride` 和 `providerOverride`。适用于原生插件 hooks 和受支持的 bundle 提供的 hook 目录。 -- `plugins.entries..subagent.allowModelOverride`:显式信任此插件,使其可以为后台子智能体运行请求按次生效的 `provider` 和 `model` 覆盖。 -- `plugins.entries..subagent.allowedModels`:适用于受信任子智能体覆盖的可选规范 `provider/model` 目标允许列表。仅当你明确希望允许任意模型时,才使用 `"*"`。 -- `plugins.entries..config`:插件定义的配置对象(可在原生 OpenClaw 插件 schema 可用时进行验证)。 -- `plugins.entries.firecrawl.config.webFetch`:Firecrawl Web 抓取提供商设置。 +- `plugins.entries..hooks.allowPromptInjection`:为 `false` 时,核心会阻止 `before_prompt_build`,并忽略旧版 `before_agent_start` 中会修改 prompt 的字段,同时保留旧版 `modelOverride` 和 `providerOverride`。适用于原生插件 hooks 以及受支持的 bundle 提供的 hook 目录。 +- `plugins.entries..subagent.allowModelOverride`:显式信任该插件可为后台子智能体运行请求按次 `provider` 和 `model` 覆盖。 +- `plugins.entries..subagent.allowedModels`:受信任子智能体覆盖的可选规范 `provider/model` 目标允许列表。仅当你确实希望允许任意模型时才使用 `"*"`。 +- `plugins.entries..config`:插件定义的配置对象(在可用时由原生 OpenClaw 插件 schema 进行验证)。 +- `plugins.entries.firecrawl.config.webFetch`:Firecrawl web-fetch 提供商设置。 - `apiKey`:Firecrawl API 密钥(接受 SecretRef)。会回退到 `plugins.entries.firecrawl.config.webSearch.apiKey`、旧版 `tools.web.fetch.firecrawl.apiKey`,或 `FIRECRAWL_API_KEY` 环境变量。 - `baseUrl`:Firecrawl API base URL(默认:`https://api.firecrawl.dev`)。 - `onlyMainContent`:仅提取页面主体内容(默认:`true`)。 - - `maxAgeMs`:最大缓存时长(毫秒)(默认:`172800000` / 2 天)。 - - `timeoutSeconds`:抓取请求超时时间(秒)(默认:`60`)。 -- `plugins.entries.xai.config.xSearch`:xAI X 搜索(Grok Web 搜索)设置。 - - `enabled`:启用 X 搜索提供商。 + - `maxAgeMs`:缓存最大存活时间(毫秒)(默认:`172800000` / 2 天)。 + - `timeoutSeconds`:抓取请求超时(秒)(默认:`60`)。 +- `plugins.entries.xai.config.xSearch`:xAI X Search(Grok web 搜索)设置。 + - `enabled`:启用 X Search 提供商。 - `model`:用于搜索的 Grok 模型(例如 `"grok-4-1-fast"`)。 -- `plugins.entries.memory-core.config.dreaming`:记忆 Dreaming 设置。阶段和阈值请参见 [Dreaming](/zh-CN/concepts/dreaming)。 +- `plugins.entries.memory-core.config.dreaming`:memory Dreaming 设置。阶段和阈值请参阅 [Dreaming](/zh-CN/concepts/dreaming)。 - `enabled`:Dreaming 主开关(默认 `false`)。 - `frequency`:每次完整 Dreaming 扫描的 cron 频率(默认 `"0 3 * * *"`)。 - - 阶段策略和阈值是实现细节(不是面向用户的配置键)。 -- 完整记忆配置位于 [记忆配置参考](/zh-CN/reference/memory-config): + - 阶段策略和阈值属于实现细节(不是面向用户的配置键)。 +- 完整的 memory 配置位于 [Memory configuration reference](/zh-CN/reference/memory-config): - `agents.defaults.memorySearch.*` - `memory.backend` - `memory.citations` - `memory.qmd.*` - `plugins.entries.memory-core.config.dreaming` -- 已启用的 Claude bundle 插件也可以从 `settings.json` 提供嵌入式 Pi 默认值;OpenClaw 会将这些值作为经过清理的智能体设置应用,而不是作为原始 OpenClaw 配置补丁。 -- `plugins.slots.memory`:选择当前激活的记忆插件 id,或使用 `"none"` 禁用记忆插件。 -- `plugins.slots.contextEngine`:选择当前激活的上下文引擎插件 id;默认值为 `"legacy"`,除非你安装并选择了其他引擎。 +- 已启用的 Claude bundle 插件也可以通过 `settings.json` 提供嵌入式 Pi 默认值;OpenClaw 会将其作为已净化的智能体设置来应用,而不是作为原始 OpenClaw 配置补丁。 +- `plugins.slots.memory`:选择活动 memory 插件 ID,或使用 `"none"` 禁用 memory 插件。 +- `plugins.slots.contextEngine`:选择活动上下文引擎插件 ID;默认值是 `"legacy"`,除非你安装并选择了其他引擎。 - `plugins.installs`:由 CLI 管理的安装元数据,供 `openclaw plugins update` 使用。 - 包括 `source`、`spec`、`sourcePath`、`installPath`、`version`、`resolvedName`、`resolvedVersion`、`resolvedSpec`、`integrity`、`shasum`、`resolvedAt`、`installedAt`。 - - 请将 `plugins.installs.*` 视为受管状态;优先使用 CLI 命令,而不是手动编辑。 + - 将 `plugins.installs.*` 视为受管状态;优先使用 CLI 命令,而不是手动编辑。 -参见 [插件](/zh-CN/tools/plugin)。 +请参阅 [Plugins](/zh-CN/tools/plugin)。 --- @@ -2942,8 +2955,8 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 evaluateEnabled: true, defaultProfile: "user", ssrfPolicy: { - // dangerouslyAllowPrivateNetwork: true, // 仅对受信任的私有网络访问选择性启用 - // allowPrivateNetwork: true, // 旧版别名 + // dangerouslyAllowPrivateNetwork: true, // opt in only for trusted private-network access + // allowPrivateNetwork: true, // legacy alias // hostnameAllowlist: ["*.example.com", "example.com"], // allowedHostnames: ["localhost"], }, @@ -2970,22 +2983,29 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 ``` - `evaluateEnabled: false` 会禁用 `act:evaluate` 和 `wait --fn`。 -- 未设置时,`ssrfPolicy.dangerouslyAllowPrivateNetwork` 为禁用状态,因此浏览器导航默认保持严格。 -- 仅当你明确受信任私有网络浏览器导航时,才设置 `ssrfPolicy.dangerouslyAllowPrivateNetwork: true`。 -- 在严格模式下,远程 CDP profile 端点(`profiles.*.cdpUrl`)在可达性/发现检查期间也会受到相同的私有网络阻止。 +- `ssrfPolicy.dangerouslyAllowPrivateNetwork` 在未设置时为禁用,因此浏览器导航默认保持严格模式。 +- 仅当你明确信任私有网络浏览器导航时,才设置 `ssrfPolicy.dangerouslyAllowPrivateNetwork: true`。 +- 在严格模式下,远程 CDP 配置文件端点(`profiles.*.cdpUrl`)在可达性/发现检查期间也会受到相同的私有网络阻止规则约束。 - `ssrfPolicy.allowPrivateNetwork` 仍作为旧版别名受支持。 -- 在严格模式下,请使用 `ssrfPolicy.hostnameAllowlist` 和 `ssrfPolicy.allowedHostnames` 进行显式例外配置。 -- 远程 profiles 仅支持附加(start/stop/reset 被禁用)。 +- 在严格模式下,使用 `ssrfPolicy.hostnameAllowlist` 和 `ssrfPolicy.allowedHostnames` 进行显式例外配置。 +- 远程配置文件为仅附加模式(禁用 start/stop/reset)。 - `profiles.*.cdpUrl` 接受 `http://`、`https://`、`ws://` 和 `wss://`。 - 当你希望 OpenClaw 自动发现 `/json/version` 时,请使用 HTTP(S);当提供商直接给出 DevTools WebSocket URL 时,请使用 WS(S)。 -- `existing-session` profiles 使用 Chrome MCP 而不是 CDP,并且可以附加到选定宿主机上,或通过已连接的浏览器节点附加。 -- `existing-session` profiles 可设置 `userDataDir`,以指定某个基于 Chromium 的浏览器 profile,例如 Brave 或 Edge。 -- `existing-session` profiles 保留当前 Chrome MCP 路由限制: - 使用快照/ref 驱动的操作而不是 CSS 选择器定位、单文件上传 hooks、不支持对话框超时覆盖、不支持 `wait --load networkidle`,也不支持 `responsebody`、PDF 导出、下载拦截或批量操作。 -- 本地受管 `openclaw` profiles 会自动分配 `cdpPort` 和 `cdpUrl`;仅当使用远程 CDP 时才显式设置 `cdpUrl`。 -- 自动检测顺序:默认浏览器(如果基于 Chromium)→ Chrome → Brave → Edge → Chromium → Chrome Canary。 -- 控制服务:仅限 loopback(端口由 `gateway.port` 推导,默认 `18791`)。 -- `extraArgs` 会向本地 Chromium 启动追加额外标志(例如 `--disable-gpu`、窗口尺寸或调试标志)。 + 当你希望 OpenClaw 发现 `/json/version` 时,请使用 HTTP(S); + 当提供商直接给出 DevTools WebSocket URL 时,请使用 WS(S)。 +- `existing-session` 配置文件使用 Chrome MCP 而不是 CDP,并且可在 + 选定主机上或通过已连接浏览器节点进行附加。 +- `existing-session` 配置文件可以设置 `userDataDir`,以定位特定的 + Chromium 系浏览器配置文件,例如 Brave 或 Edge。 +- `existing-session` 配置文件保留当前 Chrome MCP 路由限制: + 使用 snapshot/ref 驱动的操作而非 CSS 选择器定位、单文件上传 + hooks、无对话框超时覆盖、无 `wait --load networkidle`,以及无 + `responsebody`、PDF 导出、下载拦截或批量操作。 +- 本地受管的 `openclaw` 配置文件会自动分配 `cdpPort` 和 `cdpUrl`;只有 + 远程 CDP 时才需显式设置 `cdpUrl`。 +- 自动检测顺序:默认浏览器(若基于 Chromium)→ Chrome → Brave → Edge → Chromium → Chrome Canary。 +- Control 服务:仅限 loopback(端口从 `gateway.port` 推导,默认 `18791`)。 +- `extraArgs` 会向本地 Chromium 启动附加额外启动参数(例如 + `--disable-gpu`、窗口尺寸或调试标志)。 --- @@ -2997,14 +3017,14 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 seamColor: "#FF4500", assistant: { name: "OpenClaw", - avatar: "CB", // emoji、短文本、图片 URL 或 data URI + avatar: "CB", // emoji, short text, image URL, or data URI }, }, } ``` -- `seamColor`:原生应用 UI 外观的强调色(Talk 模式气泡色调等)。 -- `assistant`:Control UI 身份覆盖。会回退到当前活跃智能体身份。 +- `seamColor`:原生应用 UI 外观的强调色(Talk Mode 气泡色调等)。 +- `assistant`:Control UI 身份覆盖。未设置时回退到活动智能体身份。 --- @@ -3019,8 +3039,8 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 auth: { mode: "token", // none | token | password | trusted-proxy token: "your-token", - // password: "your-password", // 或 OPENCLAW_GATEWAY_PASSWORD - // trustedProxy: { userHeader: "x-forwarded-user" }, // 用于 mode=trusted-proxy;参见 /gateway/trusted-proxy-auth + // password: "your-password", // or OPENCLAW_GATEWAY_PASSWORD + // trustedProxy: { userHeader: "x-forwarded-user" }, // for mode=trusted-proxy; see /gateway/trusted-proxy-auth allowTailscale: true, rateLimit: { maxAttempts: 10, @@ -3038,9 +3058,9 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 basePath: "/openclaw", // root: "dist/control-ui", // embedSandbox: "scripts", // strict | scripts | trusted - // allowExternalEmbedUrls: false, // 危险:允许绝对外部 http(s) 嵌入 URL - // allowedOrigins: ["https://control.example.com"], // 非 loopback Control UI 必需 - // dangerouslyAllowHostHeaderOriginFallback: false, // 危险的 Host header 来源回退模式 + // allowExternalEmbedUrls: false, // dangerous: allow absolute external http(s) embed URLs + // allowedOrigins: ["https://control.example.com"], // required for non-loopback Control UI + // dangerouslyAllowHostHeaderOriginFallback: false, // dangerous Host-header origin fallback mode // allowInsecureAuth: false, // dangerouslyDisableDeviceAuth: false, }, @@ -3051,12 +3071,12 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 // password: "your-password", }, trustedProxies: ["10.0.0.1"], - // 可选。默认 false。 + // Optional. Default false. allowRealIpFallback: false, tools: { - // 对 /tools/invoke HTTP 的额外 deny + // Additional /tools/invoke HTTP denies deny: ["browser"], - // 从默认 HTTP deny 列表中移除工具 + // Remove tools from the default HTTP deny list allow: ["gateway"], }, push: { @@ -3076,46 +3096,46 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 - `mode`:`local`(运行 Gateway 网关)或 `remote`(连接到远程 Gateway 网关)。除非为 `local`,否则 Gateway 网关会拒绝启动。 - `port`:用于 WS + HTTP 的单一复用端口。优先级:`--port` > `OPENCLAW_GATEWAY_PORT` > `gateway.port` > `18789`。 - `bind`:`auto`、`loopback`(默认)、`lan`(`0.0.0.0`)、`tailnet`(仅 Tailscale IP)或 `custom`。 -- **旧版 bind 别名**:在 `gateway.bind` 中使用 bind 模式值(`auto`、`loopback`、`lan`、`tailnet`、`custom`),不要使用主机别名(`0.0.0.0`、`127.0.0.1`、`localhost`、`::`、`::1`)。 -- **Docker 说明**:默认的 `loopback` bind 会在容器内监听 `127.0.0.1`。在 Docker bridge 网络(`-p 18789:18789`)下,流量会到达 `eth0`,因此 Gateway 网关将不可访问。请使用 `--network host`,或设置 `bind: "lan"`(或使用 `bind: "custom"` 并配合 `customBindHost: "0.0.0.0"`)以监听所有接口。 -- **认证**:默认必须启用。非 loopback bind 需要 Gateway 网关认证。实际中这意味着共享 token/password,或使用带有 `gateway.auth.mode: "trusted-proxy"` 的身份感知型反向代理。新手引导向导默认会生成一个 token。 -- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`(包括 SecretRefs),请显式设置 `gateway.auth.mode` 为 `token` 或 `password`。当两者都已配置而 mode 未设置时,启动以及服务安装/修复流程都会失败。 -- `gateway.auth.mode: "none"`:显式无认证模式。仅用于受信任的本地 local loopback 设置;新手引导提示中不会提供此选项。 -- `gateway.auth.mode: "trusted-proxy"`:将认证委托给身份感知型反向代理,并信任来自 `gateway.trustedProxies` 的身份 headers(参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth))。该模式要求**非 loopback** 的代理来源;同一宿主机上的 loopback 反向代理不满足 trusted-proxy 认证要求。 -- `gateway.auth.allowTailscale`:为 `true` 时,Tailscale Serve 身份 headers 可满足 Control UI/WebSocket 认证(通过 `tailscale whois` 验证)。HTTP API 端点**不会**使用该 Tailscale header 认证;它们仍遵循 Gateway 网关的普通 HTTP 认证模式。此无 token 流程假定 Gateway 网关宿主机是受信任的。当 `tailscale.mode = "serve"` 时,默认值为 `true`。 -- `gateway.auth.rateLimit`:可选的认证失败限流器。按客户端 IP 和认证范围生效(共享密钥与设备 token 分开跟踪)。被阻止的尝试会返回 `429` + `Retry-After`。 - - 在异步 Tailscale Serve Control UI 路径上,同一 `{scope, clientIp}` 的失败尝试会在写入失败记录前被串行化。因此,同一客户端的并发错误尝试可能会在第二个请求时触发限流器,而不是两个都竞争着作为普通不匹配通过。 - - `gateway.auth.rateLimit.exemptLoopback` 默认值为 `true`;当你明确希望连 localhost 流量也被限流时(用于测试设置或严格代理部署),请设置为 `false`。 -- 来自浏览器来源的 WS 认证尝试始终会启用限流,并关闭 loopback 豁免(作为防御性加强,防止基于浏览器的 localhost 暴力破解)。 -- 在 loopback 上,这些源自浏览器的锁定会按标准化后的 `Origin` - 值进行隔离,因此来自一个 localhost origin 的重复失败不会自动 - 锁定另一个 origin。 -- `tailscale.mode`:`serve`(仅 tailnet,loopback bind)或 `funnel`(公网,需要认证)。 -- `controlUi.allowedOrigins`:用于 Gateway 网关 WebSocket 连接的显式浏览器 origin 允许列表。当预期浏览器客户端来自非 loopback origin 时为必需。 -- `controlUi.dangerouslyAllowHostHeaderOriginFallback`:危险模式,为那些有意依赖 Host header origin 策略的部署启用 Host header origin 回退。 +- **旧版 bind 别名**:在 `gateway.bind` 中使用 bind 模式值(`auto`、`loopback`、`lan`、`tailnet`、`custom`),不要使用 host 别名(`0.0.0.0`、`127.0.0.1`、`localhost`、`::`、`::1`)。 +- **Docker 说明**:默认的 `loopback` 绑定会在容器内监听 `127.0.0.1`。使用 Docker bridge 网络(`-p 18789:18789`)时,流量会到达 `eth0`,因此无法访问 Gateway 网关。请使用 `--network host`,或设置 `bind: "lan"`(或 `bind: "custom"` 并搭配 `customBindHost: "0.0.0.0"`)以监听所有接口。 +- **认证**:默认必须启用。非 loopback 绑定需要 Gateway 网关认证。实际使用中,这意味着需要共享 token/password,或使用配置了 `gateway.auth.mode: "trusted-proxy"` 的身份感知反向代理。新手引导默认会生成一个 token。 +- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`(包括 SecretRef),请显式将 `gateway.auth.mode` 设置为 `token` 或 `password`。若两者都已配置且 mode 未设置,启动以及服务安装/修复流程都会失败。 +- `gateway.auth.mode: "none"`:显式无认证模式。仅适用于受信任的本地 local loopback 设置;新手引导提示中不会提供此选项。 +- `gateway.auth.mode: "trusted-proxy"`:将认证委托给身份感知反向代理,并信任来自 `gateway.trustedProxies` 的身份 headers(参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth))。该模式要求**非 loopback** 的代理来源;同主机 loopback 反向代理不满足 trusted-proxy 认证要求。 +- `gateway.auth.allowTailscale`:为 `true` 时,Tailscale Serve 身份 headers 可满足 Control UI/WebSocket 认证(通过 `tailscale whois` 验证)。HTTP API 端点**不会**使用该 Tailscale header 认证;它们仍遵循 Gateway 网关的常规 HTTP 认证模式。当 `tailscale.mode = "serve"` 时,默认值为 `true`。 +- `gateway.auth.rateLimit`:可选的认证失败限流器。按客户端 IP 和认证作用域生效(共享 secret 和设备 token 会分别跟踪)。被阻止的尝试会返回 `429` + `Retry-After`。 + - 在异步 Tailscale Serve Control UI 路径上,对于同一个 `{scope, clientIp}`,失败尝试会在写入失败记录前被串行化。因此,同一客户端的并发错误尝试可能会在第二个请求时触发限流,而不是两个请求都作为普通不匹配同时穿过。 + - `gateway.auth.rateLimit.exemptLoopback` 默认为 `true`;如果你确实希望 localhost 流量也被限速(用于测试设置或严格代理部署),请将其设为 `false`。 +- 浏览器来源的 WS 认证尝试始终会被限速,并且禁用 loopback 豁免(作为对基于浏览器的 localhost 暴力破解的纵深防御)。 +- 在 loopback 上,这些浏览器来源的锁定会按规范化后的 `Origin` + 值隔离,因此某个 localhost origin 的重复失败不会自动 + 锁定另一个不同的 origin。 +- `tailscale.mode`:`serve`(仅 tailnet,loopback 绑定)或 `funnel`(公开,需要认证)。 +- `controlUi.allowedOrigins`:Gateway 网关 WebSocket 连接的显式浏览器 origin 允许列表。当浏览器客户端预期来自非 loopback origin 时,这是必需的。 +- `controlUi.dangerouslyAllowHostHeaderOriginFallback`:危险模式,为有意依赖 Host header origin 策略的部署启用 Host header origin 回退。 - `remote.transport`:`ssh`(默认)或 `direct`(ws/wss)。对于 `direct`,`remote.url` 必须是 `ws://` 或 `wss://`。 -- `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`:客户端侧的破窗应急覆盖,允许对受信任私有网络 IP 使用明文 `ws://`;默认情况下,明文连接仍然只允许 loopback。 +- `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`:客户端侧破玻璃覆盖,允许对受信任的私有网络 IP 使用明文 `ws://`;默认情况下,明文仍仅限 loopback。 - `gateway.remote.token` / `.password` 是远程客户端凭证字段。它们本身不会配置 Gateway 网关认证。 -- `gateway.push.apns.relay.baseUrl`:外部 APNs relay 的基础 HTTPS URL,官方/TestFlight iOS 构建在将基于 relay 的注册发布到 Gateway 网关后会使用它。该 URL 必须与编译进 iOS 构建中的 relay URL 一致。 -- `gateway.push.apns.relay.timeoutMs`:Gateway 网关到 relay 的发送超时时间(毫秒)。默认值为 `10000`。 -- 基于 relay 的注册会委托给某个特定的 Gateway 网关身份。已配对的 iOS 应用会获取 `gateway.identity.get`,在 relay 注册中包含该身份,并将按注册范围的发送授权转发给 Gateway 网关。其他 Gateway 网关无法复用该已存储注册。 -- `OPENCLAW_APNS_RELAY_BASE_URL` / `OPENCLAW_APNS_RELAY_TIMEOUT_MS`:上述 relay 配置的临时环境变量覆盖。 -- `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true`:仅用于开发环境的应急开关,允许使用 loopback HTTP relay URL。生产 relay URL 应保持为 HTTPS。 -- `gateway.channelHealthCheckMinutes`:渠道健康监视器间隔(分钟)。设置为 `0` 可全局禁用健康监视器重启。默认值:`5`。 -- `gateway.channelStaleEventThresholdMinutes`:陈旧 socket 阈值(分钟)。请保持其大于或等于 `gateway.channelHealthCheckMinutes`。默认值:`30`。 -- `gateway.channelMaxRestartsPerHour`:每个渠道/账号在滚动一小时内允许的最大健康监视器重启次数。默认值:`10`。 -- `channels..healthMonitor.enabled`:按渠道选择性禁用健康监视器重启,同时保持全局监视器启用。 -- `channels..accounts..healthMonitor.enabled`:多账号渠道的按账号覆盖。设置后优先于渠道级覆盖。 -- 仅当 `gateway.auth.*` 未设置时,本地 Gateway 网关调用路径才可使用 `gateway.remote.*` 作为回退。 -- 如果 `gateway.auth.token` / `gateway.auth.password` 通过 SecretRef 显式配置但未解析,则解析会以关闭为默认(不会使用远程回退来掩盖)。 -- `trustedProxies`:负责终止 TLS 或注入转发客户端 headers 的反向代理 IP。只列出你控制的代理。loopback 条目对于同宿主代理/本地检测设置(例如 Tailscale Serve 或本地反向代理)仍然有效,但它们**不会**使 loopback 请求符合 `gateway.auth.mode: "trusted-proxy"`。 -- `allowRealIpFallback`:为 `true` 时,如果缺少 `X-Forwarded-For`,Gateway 网关会接受 `X-Real-IP`。默认值为 `false`,以保持默认拒绝行为。 +- `gateway.push.apns.relay.baseUrl`:外部 APNs relay 的 base HTTPS URL,官方/TestFlight iOS 构建在向 Gateway 网关发布基于 relay 的注册信息后会使用它。该 URL 必须与编译进 iOS 构建中的 relay URL 一致。 +- `gateway.push.apns.relay.timeoutMs`:Gateway 网关到 relay 的发送超时(毫秒)。默认值为 `10000`。 +- 基于 relay 的注册会委托给特定的 Gateway 网关身份。已配对的 iOS 应用会获取 `gateway.identity.get`,在 relay 注册中包含该身份,并将一个按注册划分的发送授权转发给 Gateway 网关。其他 Gateway 网关无法复用该已存储注册。 +- `OPENCLAW_APNS_RELAY_BASE_URL` / `OPENCLAW_APNS_RELAY_TIMEOUT_MS`:对上述 relay 配置的临时环境变量覆盖。 +- `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true`:仅开发使用的逃逸开关,用于 loopback HTTP relay URL。生产 relay URL 应保持为 HTTPS。 +- `gateway.channelHealthCheckMinutes`:渠道健康监视器间隔(分钟)。设为 `0` 可在全局禁用健康监视器重启。默认值:`5`。 +- `gateway.channelStaleEventThresholdMinutes`:陈旧 socket 阈值(分钟)。该值应大于或等于 `gateway.channelHealthCheckMinutes`。默认值:`30`。 +- `gateway.channelMaxRestartsPerHour`:滚动一小时内,每个渠道/账号允许的最大健康监视器重启次数。默认值:`10`。 +- `channels..healthMonitor.enabled`:按渠道选择退出健康监视器重启,同时保持全局监视器启用。 +- `channels..accounts..healthMonitor.enabled`:多账号渠道的按账号覆盖。设置后,其优先级高于渠道级覆盖。 +- 仅当 `gateway.auth.*` 未设置时,本地 Gateway 网关调用路径才可将 `gateway.remote.*` 作为回退。 +- 如果 `gateway.auth.token` / `gateway.auth.password` 明确通过 SecretRef 配置但未解析,则解析会失败关闭(不会由远程回退掩盖)。 +- `trustedProxies`:终止 TLS 或注入转发客户端 headers 的反向代理 IP。仅列出你控制的代理。loopback 条目对于同主机代理/本地检测设置(例如 Tailscale Serve 或本地反向代理)仍然有效,但它们**不会**让 loopback 请求符合 `gateway.auth.mode: "trusted-proxy"` 的条件。 +- `allowRealIpFallback`:为 `true` 时,当缺少 `X-Forwarded-For` 时,Gateway 网关会接受 `X-Real-IP`。默认值 `false`,以保持失败关闭行为。 - `gateway.tools.deny`:对 HTTP `POST /tools/invoke` 额外阻止的工具名称(扩展默认 deny 列表)。 - `gateway.tools.allow`:从默认 HTTP deny 列表中移除工具名称。 -### OpenAI 兼容端点 +### OpenAI-compatible 端点 - Chat Completions:默认禁用。使用 `gateway.http.endpoints.chatCompletions.enabled: true` 启用。 - Responses API:`gateway.http.endpoints.responses.enabled`。 @@ -3123,14 +3143,14 @@ Base URL 不应包含 `/v1`(Anthropic 客户端会自行追加它)。快捷 - `gateway.http.endpoints.responses.maxUrlParts` - `gateway.http.endpoints.responses.files.urlAllowlist` - `gateway.http.endpoints.responses.images.urlAllowlist` - 空允许列表会被视为未设置;如需禁用 URL 获取,请使用 `gateway.http.endpoints.responses.files.allowUrl=false` + 空的 allowlist 会被视为未设置;如需禁用 URL 抓取,请使用 `gateway.http.endpoints.responses.files.allowUrl=false` 和/或 `gateway.http.endpoints.responses.images.allowUrl=false`。 - 可选的响应加固 header: - `gateway.http.securityHeaders.strictTransportSecurity`(仅对你控制的 HTTPS origin 设置;参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth#tls-termination-and-hsts)) ### 多实例隔离 -在一台宿主机上通过唯一端口和状态目录运行多个 Gateway 网关: +在同一台主机上使用唯一端口和状态目录运行多个 Gateway 网关: ```bash OPENCLAW_CONFIG_PATH=~/.openclaw/a.json \ @@ -3140,7 +3160,7 @@ openclaw gateway --port 19001 便捷标志:`--dev`(使用 `~/.openclaw-dev` + 端口 `19001`)、`--profile `(使用 `~/.openclaw-`)。 -参见 [多个 Gateway 网关](/zh-CN/gateway/multiple-gateways)。 +参见 [Multiple Gateways](/zh-CN/gateway/multiple-gateways)。 ### `gateway.tls` @@ -3158,10 +3178,10 @@ openclaw gateway --port 19001 } ``` -- `enabled`:在 Gateway 网关监听器上启用 TLS 终止(HTTPS/WSS)(默认:`false`)。 -- `autoGenerate`:在未配置显式文件时自动生成本地自签名证书/密钥对;仅用于本地/开发。 +- `enabled`:在 Gateway 网关监听器处启用 TLS 终止(HTTPS/WSS)(默认:`false`)。 +- `autoGenerate`:当未配置显式文件时自动生成本地自签名证书/密钥对;仅用于本地/开发环境。 - `certPath`:TLS 证书文件的文件系统路径。 -- `keyPath`:TLS 私钥文件的文件系统路径;请限制权限。 +- `keyPath`:TLS 私钥文件的文件系统路径;请限制其访问权限。 - `caPath`:用于客户端验证或自定义信任链的可选 CA bundle 路径。 ### `gateway.reload` @@ -3178,13 +3198,13 @@ openclaw gateway --port 19001 } ``` -- `mode`:控制配置编辑如何在运行时应用。 +- `mode`:控制如何在运行时应用配置编辑。 - `"off"`:忽略实时编辑;更改需要显式重启。 - - `"restart"`:配置更改时始终重启 Gateway 网关进程。 - - `"hot"`:在进程内应用更改,而不重启。 - - `"hybrid"`(默认):先尝试热重载;如有必要则回退为重启。 -- `debounceMs`:在应用配置更改前的去抖动窗口(毫秒)(非负整数)。 -- `deferralTimeoutMs`:在强制重启前等待正在进行的操作完成的最大时间(毫秒)(默认:`300000` = 5 分钟)。 + - `"restart"`:配置变更时始终重启 Gateway 网关进程。 + - `"hot"`:在进程内应用更改而不重启。 + - `"hybrid"`(默认):先尝试热重载;如有需要则回退到重启。 +- `debounceMs`:应用配置更改前的去抖窗口(毫秒)(非负整数)。 +- `deferralTimeoutMs`:在强制重启前,等待进行中操作完成的最长时间(毫秒)(默认:`300000` = 5 分钟)。 --- @@ -3221,47 +3241,47 @@ openclaw gateway --port 19001 } ``` -认证方式:`Authorization: Bearer ` 或 `x-openclaw-token: `。 -查询字符串中的 hook token 会被拒绝。 +认证:`Authorization: Bearer ` 或 `x-openclaw-token: `。 +拒绝使用查询字符串中的 hook token。 验证和安全说明: -- `hooks.enabled=true` 要求提供非空的 `hooks.token`。 -- `hooks.token` 必须与 `gateway.auth.token` **不同**;复用 Gateway 网关 token 会被拒绝。 +- `hooks.enabled=true` 需要非空的 `hooks.token`。 +- `hooks.token` 必须与 `gateway.auth.token` **不同**;重复使用 Gateway 网关 token 会被拒绝。 - `hooks.path` 不能是 `/`;请使用专用子路径,例如 `/hooks`。 - 如果 `hooks.allowRequestSessionKey=true`,请约束 `hooks.allowedSessionKeyPrefixes`(例如 `["hook:"]`)。 -- 如果某个 mapping 或 preset 使用模板化的 `sessionKey`,请设置 `hooks.allowedSessionKeyPrefixes` 和 `hooks.allowRequestSessionKey=true`。静态 mapping key 不需要该选择性启用。 +- 如果某个映射或预设使用模板化 `sessionKey`,请设置 `hooks.allowedSessionKeyPrefixes` 和 `hooks.allowRequestSessionKey=true`。静态映射键不需要该选择加入。 **端点:** - `POST /hooks/wake` → `{ text, mode?: "now"|"next-heartbeat" }` - `POST /hooks/agent` → `{ message, name?, agentId?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }` - - 仅当 `hooks.allowRequestSessionKey=true`(默认:`false`)时,才会接受请求载荷中的 `sessionKey`。 + - 仅当 `hooks.allowRequestSessionKey=true`(默认:`false`)时,才接受请求负载中的 `sessionKey`。 - `POST /hooks/` → 通过 `hooks.mappings` 解析 - - 模板渲染后的 mapping `sessionKey` 值会被视为外部提供,因此也要求 `hooks.allowRequestSessionKey=true`。 + - 模板渲染后的映射 `sessionKey` 值会被视为外部提供,因此也要求 `hooks.allowRequestSessionKey=true`。 - + - `match.path` 会匹配 `/hooks` 之后的子路径(例如 `/hooks/gmail` → `gmail`)。 -- `match.source` 会匹配通用路径中的某个载荷字段。 -- 像 `{{messages[0].subject}}` 这样的模板会从载荷中读取。 -- `transform` 可以指向一个返回 hook action 的 JS/TS 模块。 - - `transform.module` 必须是相对路径,并且保持在 `hooks.transformsDir` 内(绝对路径和路径穿越会被拒绝)。 +- `match.source` 会匹配通用路径中的某个负载字段。 +- `{{messages[0].subject}}` 之类的模板会从负载中读取。 +- `transform` 可指向一个返回 hook 动作的 JS/TS 模块。 + - `transform.module` 必须是相对路径,并保持在 `hooks.transformsDir` 内(绝对路径和路径穿越都会被拒绝)。 - `agentId` 会路由到特定智能体;未知 ID 会回退到默认值。 - `allowedAgentIds`:限制显式路由(`*` 或省略 = 允许全部,`[]` = 全部拒绝)。 -- `defaultSessionKey`:hook 智能体运行在未显式提供 `sessionKey` 时使用的可选固定会话键。 -- `allowRequestSessionKey`:允许 `/hooks/agent` 调用方以及模板驱动 mapping session key 设置 `sessionKey`(默认:`false`)。 -- `allowedSessionKeyPrefixes`:对显式 `sessionKey` 值(请求 + mapping)的可选前缀允许列表,例如 `["hook:"]`。当任何 mapping 或 preset 使用模板化 `sessionKey` 时,它就变为必需。 +- `defaultSessionKey`:对未显式提供 `sessionKey` 的 hook 智能体运行,使用的可选固定会话键。 +- `allowRequestSessionKey`:允许 `/hooks/agent` 调用方以及模板驱动的映射会话键设置 `sessionKey`(默认:`false`)。 +- `allowedSessionKeyPrefixes`:用于显式 `sessionKey` 值(请求 + 映射)的可选前缀允许列表,例如 `["hook:"]`。当任意映射或预设使用模板化 `sessionKey` 时,它就成为必填项。 - `deliver: true` 会将最终回复发送到某个渠道;`channel` 默认值为 `last`。 -- `model` 会覆盖本次 hook 运行使用的 LLM(如果设置了模型目录,则该模型必须在允许范围内)。 +- `model` 会覆盖本次 hook 运行的 LLM(如果设置了模型目录,则该模型必须被允许)。 ### Gmail 集成 -- 内置 Gmail preset 使用 `sessionKey: "hook:gmail:{{messages[0].id}}"`。 +- 内置 Gmail 预设使用 `sessionKey: "hook:gmail:{{messages[0].id}}"`。 - 如果你保留这种按消息路由方式,请设置 `hooks.allowRequestSessionKey: true`,并约束 `hooks.allowedSessionKeyPrefixes` 以匹配 Gmail 命名空间,例如 `["hook:", "hook:gmail:"]`。 -- 如果你需要 `hooks.allowRequestSessionKey: false`,请使用静态 `sessionKey` 覆盖 preset,而不是使用模板化默认值。 +- 如果你需要 `hooks.allowRequestSessionKey: false`,请使用静态 `sessionKey` 覆盖该预设,而不是使用模板化默认值。 ```json5 { @@ -3284,8 +3304,8 @@ openclaw gateway --port 19001 } ``` -- 配置后,Gateway 网关会在启动时自动启动 `gog gmail watch serve`。设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可禁用。 -- 不要在 Gateway 网关旁边单独运行另一个 `gog gmail watch serve`。 +- 配置后,Gateway 网关会在启动时自动启动 `gog gmail watch serve`。如需禁用,请设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1`。 +- 不要在 Gateway 网关旁边再单独运行一个 `gog gmail watch serve`。 --- @@ -3296,23 +3316,23 @@ openclaw gateway --port 19001 canvasHost: { root: "~/.openclaw/workspace/canvas", liveReload: true, - // enabled: false, // 或 OPENCLAW_SKIP_CANVAS_HOST=1 + // enabled: false, // or OPENCLAW_SKIP_CANVAS_HOST=1 }, } ``` -- 会在 Gateway 网关端口下通过 HTTP 提供可由智能体编辑的 HTML/CSS/JS 和 A2UI: +- 通过 Gateway 网关端口下的 HTTP 提供由智能体可编辑的 HTML/CSS/JS 和 A2UI: - `http://:/__openclaw__/canvas/` - `http://:/__openclaw__/a2ui/` - 仅限本地:保持 `gateway.bind: "loopback"`(默认)。 -- 对于非 loopback bind:canvas 路由与其他 Gateway 网关 HTTP 表面一样,需要 Gateway 网关认证(token/password/trusted-proxy)。 -- Node WebViews 通常不会发送认证 headers;当某个节点完成配对并连接后,Gateway 网关会为 canvas/A2UI 访问公布按节点作用域的 capability URL。 -- Capability URL 会绑定到当前活跃的节点 WS 会话,并且很快过期。不使用基于 IP 的回退。 -- 会将 live-reload 客户端注入到所提供的 HTML 中。 -- 为空时会自动创建起始 `index.html`。 -- 还会在 `/__openclaw__/a2ui/` 下提供 A2UI。 +- 非 loopback 绑定:canvas 路由与其他 Gateway 网关 HTTP 面一样,需要 Gateway 网关认证(token/password/trusted-proxy)。 +- Node WebViews 通常不会发送认证 headers;在节点完成配对并连接后,Gateway 网关会为 canvas/A2UI 访问通告按节点划分的 capability URL。 +- capability URL 绑定到当前活动的节点 WS 会话,并会很快过期。不使用基于 IP 的回退。 +- 会向提供的 HTML 中注入 live-reload 客户端。 +- 当目录为空时,会自动创建初始 `index.html`。 +- 也会在 `/__openclaw__/a2ui/` 下提供 A2UI。 - 更改需要重启 Gateway 网关。 -- 对于大型目录或 `EMFILE` 错误,请禁用 live reload。 +- 对于大型目录或出现 `EMFILE` 错误时,请禁用 live reload。 --- @@ -3330,11 +3350,11 @@ openclaw gateway --port 19001 } ``` -- `minimal`(默认):在 TXT 记录中省略 `cliPath` + `sshPort`。 +- `minimal`(默认):从 TXT 记录中省略 `cliPath` + `sshPort`。 - `full`:包含 `cliPath` + `sshPort`。 -- 主机名默认为 `openclaw`。可使用 `OPENCLAW_MDNS_HOSTNAME` 覆盖。 +- 主机名默认为 `openclaw`。可通过 `OPENCLAW_MDNS_HOSTNAME` 覆盖。 -### 广域(DNS-SD) +### 广域网(DNS-SD) ```json5 { @@ -3344,7 +3364,7 @@ openclaw gateway --port 19001 } ``` -会在 `~/.openclaw/dns/` 下写入一个单播 DNS-SD 区域。对于跨网络设备发现,请配合 DNS 服务器(推荐 CoreDNS)+ Tailscale split DNS 使用。 +会在 `~/.openclaw/dns/` 下写入单播 DNS-SD 区域。若需跨网络设备发现,请搭配 DNS 服务器(推荐 CoreDNS)+ Tailscale split DNS。 设置:`openclaw dns setup --apply`。 @@ -3369,14 +3389,14 @@ openclaw gateway --port 19001 } ``` -- 只有当进程环境中缺少某个键时,才会应用内联环境变量。 +- 仅当进程环境中缺少该键时,才会应用内联环境变量。 - `.env` 文件:当前工作目录 `.env` + `~/.openclaw/.env`(两者都不会覆盖现有变量)。 -- `shellEnv`:从你的登录 shell profile 中导入缺失的预期键名。 -- 完整优先级请参见 [环境变量](/zh-CN/help/environment)。 +- `shellEnv`:从你的登录 shell 配置文件中导入缺失的预期键名。 +- 完整优先级请参阅 [Environment](/zh-CN/help/environment)。 ### 环境变量替换 -可在任意配置字符串中使用 `${VAR_NAME}` 引用环境变量: +在任何配置字符串中都可以通过 `${VAR_NAME}` 引用环境变量: ```json5 { @@ -3387,19 +3407,19 @@ openclaw gateway --port 19001 ``` - 仅匹配大写名称:`[A-Z_][A-Z0-9_]*`。 -- 缺失/为空的变量会在加载配置时抛出错误。 +- 缺失/空变量会在配置加载时抛出错误。 - 使用 `$${VAR}` 可转义为字面量 `${VAR}`。 - 可与 `$include` 一起使用。 --- -## 密钥 +## Secrets -Secret refs 是增量能力:纯文本值仍然可用。 +SecretRef 是增量式的:明文值仍然可用。 ### `SecretRef` -使用一种对象结构: +使用以下对象形态: ```json5 { source: "env" | "file" | "exec", provider: "default", id: "..." } @@ -3409,23 +3429,23 @@ Secret refs 是增量能力:纯文本值仍然可用。 - `provider` 模式:`^[a-z][a-z0-9_-]{0,63}$` - `source: "env"` 的 id 模式:`^[A-Z][A-Z0-9_]{0,127}$` -- `source: "file"` 的 id:绝对 JSON pointer(例如 `"/providers/openai/apiKey"`) +- `source: "file"` 的 id:绝对 JSON 指针(例如 `"/providers/openai/apiKey"`) - `source: "exec"` 的 id 模式:`^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$` - `source: "exec"` 的 id 不能包含以斜杠分隔的 `.` 或 `..` 路径段(例如 `a/../b` 会被拒绝) -### 支持的凭证表面 +### 支持的凭证面 - 规范矩阵:[SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface) - `secrets apply` 以受支持的 `openclaw.json` 凭证路径为目标。 -- `auth-profiles.json` refs 被纳入运行时解析和审计覆盖范围。 +- `auth-profiles.json` 引用也包含在运行时解析和审计覆盖中。 -### 密钥提供商配置 +### Secret providers 配置 ```json5 { secrets: { providers: { - default: { source: "env" }, // 可选的显式环境提供商 + default: { source: "env" }, // optional explicit env provider filemain: { source: "file", path: "~/.openclaw/secrets.json", @@ -3449,18 +3469,18 @@ Secret refs 是增量能力:纯文本值仍然可用。 说明: -- `file` 提供商支持 `mode: "json"` 和 `mode: "singleValue"`(在 singleValue 模式下,`id` 必须为 `"value"`)。 -- 当 Windows ACL 验证不可用时,文件和 exec 提供商路径会以关闭为默认。仅对那些无法验证但受信任的路径设置 `allowInsecurePath: true`。 -- `exec` 提供商要求使用绝对 `command` 路径,并通过 stdin/stdout 使用协议载荷。 -- 默认情况下,符号链接命令路径会被拒绝。设置 `allowSymlinkCommand: true` 可在验证已解析目标路径的同时允许符号链接路径。 -- 如果配置了 `trustedDirs`,则受信任目录检查会应用到已解析目标路径。 -- `exec` 子进程环境默认最小化;请使用 `passEnv` 显式传递所需变量。 -- Secret refs 会在激活时解析到内存快照中,之后请求路径只会读取该快照。 -- 激活期间会应用活动表面过滤:已启用表面上的未解析 refs 会导致启动/重载失败,而非活动表面会被跳过并附带诊断信息。 +- `file` provider 支持 `mode: "json"` 和 `mode: "singleValue"`(在 singleValue 模式下,`id` 必须为 `"value"`)。 +- 当无法验证 Windows ACL 时,file 和 exec provider 路径会以失败关闭方式处理。仅对无法验证但受信任的路径设置 `allowInsecurePath: true`。 +- `exec` provider 要求绝对 `command` 路径,并通过 stdin/stdout 使用协议负载。 +- 默认会拒绝符号链接命令路径。设置 `allowSymlinkCommand: true` 可允许符号链接路径,同时验证解析后的目标路径。 +- 如果配置了 `trustedDirs`,则受信任目录检查会应用于解析后的目标路径。 +- `exec` 子进程环境默认保持最小化;请使用 `passEnv` 显式传递所需变量。 +- Secret 引用会在激活时解析到内存快照中,此后请求路径只读取该快照。 +- 激活期间会应用活动面过滤:启用面上的未解析引用会导致启动/重载失败,而非活动面会被跳过并附带诊断信息。 --- -## 认证存储 +## 凭证存储 ```json5 { @@ -3478,13 +3498,13 @@ Secret refs 是增量能力:纯文本值仍然可用。 } ``` -- 按智能体的配置文件保存在 `/auth-profiles.json`。 -- `auth-profiles.json` 支持静态凭证模式的值级 refs(`api_key` 使用 `keyRef`,`token` 使用 `tokenRef`)。 -- OAuth 模式的配置文件(`auth.profiles..mode = "oauth"`)不支持由 SecretRef 支持的 auth-profile 凭证。 -- 静态运行时凭证来自内存中的已解析快照;发现旧版静态 `auth.json` 条目时会将其清除。 -- 旧版 OAuth 从 `~/.openclaw/credentials/oauth.json` 导入。 +- 按智能体划分的 profiles 存储在 `/auth-profiles.json`。 +- `auth-profiles.json` 支持静态凭证模式的值级引用(`api_key` 使用 `keyRef`,`token` 使用 `tokenRef`)。 +- OAuth 模式的 profiles(`auth.profiles..mode = "oauth"`)不支持以 SecretRef 为后备的 auth-profile 凭证。 +- 静态运行时凭证来自内存中已解析的快照;发现旧版静态 `auth.json` 条目时会将其清理。 +- 旧版 OAuth 会从 `~/.openclaw/credentials/oauth.json` 导入。 - 参见 [OAuth](/zh-CN/concepts/oauth)。 -- 密钥运行时行为以及 `audit/configure/apply` 工具:参见 [Secrets Management](/zh-CN/gateway/secrets)。 +- Secrets 运行时行为以及 `audit/configure/apply` 工具:参见 [Secrets Management](/zh-CN/gateway/secrets)。 ### `auth.cooldowns` @@ -3506,20 +3526,20 @@ Secret refs 是增量能力:纯文本值仍然可用。 } ``` -- `billingBackoffHours`:当配置文件因真实 - 账单/余额不足错误而失败时,按小时计的基础退避时间(默认:`5`)。显式账单文本 - 即使出现在 `401`/`403` 响应中,仍可能归入此路径,但提供商特定文本 - 匹配器仍仅限于拥有它们的提供商(例如 OpenRouter 的 - `Key limit exceeded`)。可重试的 HTTP `402` 用量窗口或 - 组织/工作区支出限制消息则仍归入 `rate_limit` 路径。 -- `billingBackoffHoursByProvider`:可选的按提供商覆盖账单退避时长(小时)。 -- `billingMaxHours`:账单退避指数增长的小时上限(默认:`24`)。 +- `billingBackoffHours`:当某个 profile 因真实的 + 计费/余额不足错误而失败时使用的基础退避时间(小时)(默认:`5`)。即使在 `401`/`403` 响应下,显式的计费文本 + 也仍可能落入此路径,但提供商特定的文本 + 匹配器仍仅作用于拥有它们的提供商(例如 OpenRouter 的 + `Key limit exceeded`)。可重试的 HTTP `402` 使用窗口或 + 组织/工作区支出上限消息则仍归入 `rate_limit` 路径。 +- `billingBackoffHoursByProvider`:可选的按提供商覆盖计费退避小时数。 +- `billingMaxHours`:计费退避指数增长的上限小时数(默认:`24`)。 - `authPermanentBackoffMinutes`:高置信度 `auth_permanent` 失败的基础退避时间(分钟)(默认:`10`)。 -- `authPermanentMaxMinutes`:`auth_permanent` 退避增长的分钟上限(默认:`60`)。 -- `failureWindowHours`:用于退避计数器的滚动窗口(小时)(默认:`24`)。 -- `overloadedProfileRotations`:对于过载错误,在切换到模型回退之前,同一提供商 auth-profile 允许的最大轮换次数(默认:`1`)。像 `ModelNotReadyException` 这样的提供商忙碌形态会归入此处。 -- `overloadedBackoffMs`:在重试过载提供商/profile 轮换之前的固定延迟(默认:`0`)。 -- `rateLimitedProfileRotations`:对于速率限制错误,在切换到模型回退之前,同一提供商 auth-profile 允许的最大轮换次数(默认:`1`)。该速率限制桶还包括诸如 `Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded` 和 `resource exhausted` 之类的提供商形态文本。 +- `authPermanentMaxMinutes`:`auth_permanent` 退避增长的上限分钟数(默认:`60`)。 +- `failureWindowHours`:用于退避计数器的滚动时间窗口(小时)(默认:`24`)。 +- `overloadedProfileRotations`:对于过载错误,在切换到模型回退前,允许的同提供商 auth-profile 轮换最大次数(默认:`1`)。诸如 `ModelNotReadyException` 之类的 provider 忙碌形态会落入此路径。 +- `overloadedBackoffMs`:在重试过载的 provider/profile 轮换前的固定延迟(毫秒)(默认:`0`)。 +- `rateLimitedProfileRotations`:对于速率限制错误,在切换到模型回退前,允许的同提供商 auth-profile 轮换最大次数(默认:`1`)。该 rate-limit 桶包括提供商形态的文本,例如 `Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded` 和 `resource exhausted`。 --- @@ -3540,8 +3560,8 @@ Secret refs 是增量能力:纯文本值仍然可用。 - 默认日志文件:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`。 - 设置 `logging.file` 可使用稳定路径。 -- 当使用 `--verbose` 时,`consoleLevel` 会提升为 `debug`。 -- `maxFileBytes`:在抑制写入前允许的最大日志文件大小(字节)(正整数;默认:`524288000` = 500 MB)。生产部署请使用外部日志轮换。 +- 传入 `--verbose` 时,`consoleLevel` 会提升为 `debug`。 +- `maxFileBytes`:在抑制写入前允许的最大日志文件大小(字节)(正整数;默认:`524288000` = 500 MB)。生产部署请使用外部日志轮转。 --- @@ -3579,19 +3599,19 @@ Secret refs 是增量能力:纯文本值仍然可用。 ``` - `enabled`:插桩输出的总开关(默认:`true`)。 -- `flags`:用于启用定向日志输出的标志字符串数组(支持通配符,例如 `"telegram.*"` 或 `"*"`)。 -- `stuckSessionWarnMs`:当某个会话保持在处理中状态时,用于发出卡住会话警告的时长阈值(毫秒)。 -- `otel.enabled`:启用 OpenTelemetry 导出管道(默认:`false`)。 -- `otel.endpoint`:用于 OTel 导出的 collector URL。 +- `flags`:启用定向日志输出的标志字符串数组(支持通配符,如 `"telegram.*"` 或 `"*"`)。 +- `stuckSessionWarnMs`:当会话仍处于处理中状态时,发出卡住会话警告的年龄阈值(毫秒)。 +- `otel.enabled`:启用 OpenTelemetry 导出管线(默认:`false`)。 +- `otel.endpoint`:OTel 导出的 collector URL。 - `otel.protocol`:`"http/protobuf"`(默认)或 `"grpc"`。 -- `otel.headers`:随 OTel 导出请求一起发送的额外 HTTP/gRPC 元数据 headers。 -- `otel.serviceName`:资源属性的服务名称。 -- `otel.traces` / `otel.metrics` / `otel.logs`:启用 trace、metrics 或 logs 导出。 +- `otel.headers`:随 OTel 导出请求发送的额外 HTTP/gRPC 元数据 headers。 +- `otel.serviceName`:资源属性中的服务名。 +- `otel.traces` / `otel.metrics` / `otel.logs`:启用 trace、metrics 或日志导出。 - `otel.sampleRate`:trace 采样率 `0`–`1`。 -- `otel.flushIntervalMs`:定期刷新遥测数据的间隔(毫秒)。 -- `cacheTrace.enabled`:为嵌入式运行记录缓存跟踪快照(默认:`false`)。 -- `cacheTrace.filePath`:缓存跟踪 JSONL 的输出路径(默认:`$OPENCLAW_STATE_DIR/logs/cache-trace.jsonl`)。 -- `cacheTrace.includeMessages` / `includePrompt` / `includeSystem`:控制缓存跟踪输出中包含的内容(默认全部为 `true`)。 +- `otel.flushIntervalMs`:周期性遥测冲刷间隔(毫秒)。 +- `cacheTrace.enabled`:为嵌入式运行记录缓存追踪快照(默认:`false`)。 +- `cacheTrace.filePath`:缓存追踪 JSONL 的输出路径(默认:`$OPENCLAW_STATE_DIR/logs/cache-trace.jsonl`)。 +- `cacheTrace.includeMessages` / `includePrompt` / `includeSystem`:控制缓存追踪输出中包含的内容(默认均为 `true`)。 --- @@ -3613,12 +3633,12 @@ Secret refs 是增量能力:纯文本值仍然可用。 } ``` -- `channel`:用于 npm/git 安装的发布渠道 —— `"stable"`、`"beta"` 或 `"dev"`。 +- `channel`:npm/git 安装的发布渠道 —— `"stable"`、`"beta"` 或 `"dev"`。 - `checkOnStart`:Gateway 网关启动时检查 npm 更新(默认:`true`)。 - `auto.enabled`:为包安装启用后台自动更新(默认:`false`)。 -- `auto.stableDelayHours`:稳定渠道自动应用前的最小延迟(小时)(默认:`6`;最大:`168`)。 -- `auto.stableJitterHours`:稳定渠道发布扩散窗口的额外时长(小时)(默认:`12`;最大:`168`)。 -- `auto.betaCheckIntervalHours`:beta 渠道检查的执行频率(小时)(默认:`1`;最大:`24`)。 +- `auto.stableDelayHours`:stable 渠道自动应用前的最短延迟(小时)(默认:`6`;最大:`168`)。 +- `auto.stableJitterHours`:stable 渠道额外的发布扩散窗口(小时)(默认:`12`;最大:`168`)。 +- `auto.betaCheckIntervalHours`:beta 渠道检查运行频率(小时)(默认:`1`;最大:`24`)。 --- @@ -3651,22 +3671,22 @@ Secret refs 是增量能力:纯文本值仍然可用。 } ``` -- `enabled`:ACP 功能总开关(默认:`false`)。 +- `enabled`:全局 ACP 功能开关(默认:`false`)。 - `dispatch.enabled`:ACP 会话轮次分发的独立开关(默认:`true`)。设置为 `false` 可在保留 ACP 命令可用的同时阻止执行。 -- `backend`:默认 ACP 运行时 backend id(必须匹配某个已注册的 ACP 运行时插件)。 -- `defaultAgent`:当生成操作未指定显式目标时,使用的回退 ACP 目标智能体 id。 -- `allowedAgents`:允许用于 ACP 运行时会话的智能体 id 允许列表;为空表示不额外限制。 -- `maxConcurrentSessions`:同时活跃的 ACP 会话最大数量。 -- `stream.coalesceIdleMs`:流式文本的空闲合并刷新窗口(毫秒)。 -- `stream.maxChunkChars`:在拆分流式分块投影前允许的最大块大小。 -- `stream.repeatSuppression`:按轮次抑制重复状态/工具行(默认:`true`)。 -- `stream.deliveryMode`:`"live"` 逐步流式传输;`"final_only"` 则缓冲到轮次终止事件后再输出。 -- `stream.hiddenBoundarySeparator`:在隐藏工具事件之后、可见文本之前插入的分隔符(默认:`"paragraph"`)。 -- `stream.maxOutputChars`:每个 ACP 轮次投影的助手输出最大字符数。 -- `stream.maxSessionUpdateChars`:投影的 ACP 状态/更新行的最大字符数。 -- `stream.tagVisibility`:记录 tag 名称到布尔可见性覆盖的映射,用于流式事件。 -- `runtime.ttlMinutes`:ACP 会话 worker 在可被清理前的空闲 TTL(分钟)。 -- `runtime.installCommand`:在引导 ACP 运行时环境时执行的可选安装命令。 +- `backend`:默认 ACP 运行时后端 ID(必须匹配已注册的 ACP 运行时插件)。 +- `defaultAgent`:当生成操作未指定显式目标时,后备使用的 ACP 目标智能体 ID。 +- `allowedAgents`:允许用于 ACP 运行时会话的智能体 ID 列表;为空表示无额外限制。 +- `maxConcurrentSessions`:同时处于活动状态的 ACP 会话最大数量。 +- `stream.coalesceIdleMs`:流式文本的空闲冲刷窗口(毫秒)。 +- `stream.maxChunkChars`:流式块投影在拆分前允许的最大分块大小。 +- `stream.repeatSuppression`:按轮次抑制重复的状态/工具行(默认:`true`)。 +- `stream.deliveryMode`:`"live"` 表示增量流式传输;`"final_only"` 表示缓冲到轮次终止事件后再输出。 +- `stream.hiddenBoundarySeparator`:隐藏工具事件之后、可见文本之前使用的分隔符(默认:`"paragraph"`)。 +- `stream.maxOutputChars`:每个 ACP 轮次投影的 assistant 输出最大字符数。 +- `stream.maxSessionUpdateChars`:投影的 ACP 状态/更新行最大字符数。 +- `stream.tagVisibility`:标签名称到布尔可见性覆盖的映射,用于流式事件。 +- `runtime.ttlMinutes`:ACP 会话工作进程在符合清理条件前的空闲 TTL(分钟)。 +- `runtime.installCommand`:引导 ACP 运行时环境时运行的可选安装命令。 --- @@ -3683,10 +3703,10 @@ Secret refs 是增量能力:纯文本值仍然可用。 ``` - `cli.banner.taglineMode` 控制 banner 标语样式: - - `"random"`(默认):轮换的有趣/季节性标语。 - - `"default"`:固定的中性标语(`All your chats, one OpenClaw.`)。 + - `"random"`(默认):轮换显示有趣/季节性标语。 + - `"default"`:固定中性标语(`All your chats, one OpenClaw.`)。 - `"off"`:不显示标语文本(仍会显示 banner 标题/版本)。 -- 如需隐藏整个 banner(而不仅是标语),请设置环境变量 `OPENCLAW_HIDE_BANNER=1`。 +- 若要隐藏整个 banner(而不仅是标语),请设置环境变量 `OPENCLAW_HIDE_BANNER=1`。 --- @@ -3710,13 +3730,13 @@ Secret refs 是增量能力:纯文本值仍然可用。 ## 身份 -请参见 [智能体默认值](#agent-defaults) 下 `agents.list` 的身份字段。 +请参阅 [Agent defaults](#agent-defaults) 下 `agents.list` 的身份字段。 --- -## Bridge(旧版,已移除) +## Bridge protocol(旧版节点,历史参考) -当前构建已不再包含 TCP bridge。节点通过 Gateway 网关 WebSocket 连接。`bridge.*` 键已不再属于配置 schema 的一部分(在移除前,验证会失败;`openclaw doctor --fix` 可移除未知键)。 +当前构建已不再包含 TCP bridge。节点通过 Gateway 网关 WebSocket 连接。`bridge.*` 键已不再属于配置 schema 的一部分(在移除前验证会失败;`openclaw doctor --fix` 可清除未知键)。 @@ -3745,22 +3765,22 @@ Secret refs 是增量能力:纯文本值仍然可用。 cron: { enabled: true, maxConcurrentRuns: 2, - webhook: "https://example.invalid/legacy", // 已弃用:用于已存储 notify:true 作业的回退 - webhookToken: "replace-with-dedicated-token", // 可选:用于出站 webhook 认证的 bearer token - sessionRetention: "24h", // 时长字符串或 false + webhook: "https://example.invalid/legacy", // deprecated fallback for stored notify:true jobs + webhookToken: "replace-with-dedicated-token", // optional bearer token for outbound webhook auth + sessionRetention: "24h", // duration string or false runLog: { - maxBytes: "2mb", // 默认 2_000_000 字节 - keepLines: 2000, // 默认 2000 + maxBytes: "2mb", // default 2_000_000 bytes + keepLines: 2000, // default 2000 }, }, } ``` -- `sessionRetention`:已完成的隔离 cron 运行会话在从 `sessions.json` 中修剪前保留多久。也控制已归档、已删除的 cron 转录的清理。默认值:`24h`;设置为 `false` 可禁用。 -- `runLog.maxBytes`:每个运行日志文件(`cron/runs/.jsonl`)在触发修剪前的最大大小。默认值:`2_000_000` 字节。 -- `runLog.keepLines`:当触发运行日志修剪时保留的最新行数。默认值:`2000`。 -- `webhookToken`:用于 cron webhook POST 投递(`delivery.mode = "webhook"`)的 bearer token;若省略,则不会发送认证 header。 -- `webhook`:已弃用的旧版回退 webhook URL(http/https),仅用于仍具有 `notify: true` 的已存储作业。 +- `sessionRetention`:在从 `sessions.json` 中清理之前,保留已完成隔离 cron 运行会话的时长。也控制已归档且被删除的 cron transcript 的清理。默认值:`24h`;设置为 `false` 可禁用。 +- `runLog.maxBytes`:每个运行日志文件(`cron/runs/.jsonl`)在修剪前的最大大小。默认值:`2_000_000` 字节。 +- `runLog.keepLines`:触发运行日志修剪时保留的最新行数。默认值:`2000`。 +- `webhookToken`:用于 cron webhook POST 投递(`delivery.mode = "webhook"`)的 bearer token;若省略,则不发送认证 header。 +- `webhook`:已弃用的旧版后备 webhook URL(http/https),仅用于仍保留 `notify: true` 的已存储任务。 ### `cron.retry` @@ -3776,11 +3796,11 @@ Secret refs 是增量能力:纯文本值仍然可用。 } ``` -- `maxAttempts`:一次性作业在瞬时错误上的最大重试次数(默认:`3`;范围:`0`–`10`)。 +- `maxAttempts`:发生瞬时错误时,对一次性任务进行的最大重试次数(默认:`3`;范围:`0`–`10`)。 - `backoffMs`:每次重试尝试的退避延迟数组(毫秒)(默认:`[30000, 60000, 300000]`;1–10 个条目)。 -- `retryOn`:触发重试的错误类型 —— `"rate_limit"`、`"overloaded"`、`"network"`、`"timeout"`、`"server_error"`。省略时会重试所有瞬时类型。 +- `retryOn`:触发重试的错误类型 —— `"rate_limit"`、`"overloaded"`、`"network"`、`"timeout"`、`"server_error"`。省略则会对所有瞬时类型进行重试。 -仅适用于一次性 cron 作业。周期性作业使用独立的失败处理机制。 +仅适用于一次性 cron 任务。周期性任务使用单独的失败处理逻辑。 ### `cron.failureAlert` @@ -3798,11 +3818,11 @@ Secret refs 是增量能力:纯文本值仍然可用。 } ``` -- `enabled`:启用 cron 作业失败告警(默认:`false`)。 -- `after`:触发告警前允许的连续失败次数(正整数,最小值:`1`)。 -- `cooldownMs`:同一作业重复告警之间的最小间隔(毫秒)(非负整数)。 -- `mode`:投递模式 —— `"announce"` 通过渠道消息发送;`"webhook"` 则 POST 到已配置的 webhook。 -- `accountId`:用于限定告警投递范围的可选账号或渠道 id。 +- `enabled`:为 cron 任务启用失败警报(默认:`false`)。 +- `after`:连续失败多少次后触发警报(正整数,最小值:`1`)。 +- `cooldownMs`:同一任务重复发出警报之间的最小间隔(毫秒)(非负整数)。 +- `mode`:投递模式 —— `"announce"` 通过渠道消息发送;`"webhook"` 向已配置 webhook 发起 POST。 +- `accountId`:用于限定警报投递范围的可选账号或渠道 ID。 ### `cron.failureDestination` @@ -3819,16 +3839,16 @@ Secret refs 是增量能力:纯文本值仍然可用。 } ``` -- 所有作业共享的 cron 失败通知默认目标。 -- `mode`:`"announce"` 或 `"webhook"`;当存在足够目标数据时,默认值为 `"announce"`。 -- `channel`:announce 投递的渠道覆盖。`"last"` 会复用上次已知的投递渠道。 -- `to`:显式的 announce 目标或 webhook URL。webhook 模式下必需。 +- 所有任务共用的 cron 失败通知默认目标。 +- `mode`:`"announce"` 或 `"webhook"`;当存在足够的目标数据时,默认值为 `"announce"`。 +- `channel`:用于 announce 投递的渠道覆盖。`"last"` 会复用上次已知的投递渠道。 +- `to`:显式的 announce 目标或 webhook URL。webhook 模式下必填。 - `accountId`:可选的投递账号覆盖。 -- 按作业的 `delivery.failureDestination` 会覆盖该全局默认值。 -- 当既未设置全局也未设置按作业失败目标时,那些已经通过 `announce` 投递的作业在失败时会回退到其主 announce 目标。 -- `delivery.failureDestination` 仅支持 `sessionTarget="isolated"` 的作业,除非该作业的主 `delivery.mode` 是 `"webhook"`。 +- 按任务的 `delivery.failureDestination` 会覆盖该全局默认值。 +- 当全局和按任务的失败目标都未设置时,已经通过 `announce` 投递的任务在失败时会回退到其主要 announce 目标。 +- `delivery.failureDestination` 仅支持 `sessionTarget="isolated"` 的任务,除非该任务的主要 `delivery.mode` 是 `"webhook"`。 -参见 [Cron Jobs](/zh-CN/automation/cron-jobs)。隔离的 cron 执行会作为[后台任务](/zh-CN/automation/tasks)进行跟踪。 +请参阅 [Cron Jobs](/zh-CN/automation/cron-jobs)。隔离的 cron 执行会作为 [background tasks](/zh-CN/automation/tasks) 进行跟踪。 --- @@ -3836,32 +3856,32 @@ Secret refs 是增量能力:纯文本值仍然可用。 在 `tools.media.models[].args` 中展开的模板占位符: -| 变量 | 描述 | -| ------------------ | -------------------------------------- | -| `{{Body}}` | 完整入站消息正文 | -| `{{RawBody}}` | 原始正文(无历史/发送者包装) | -| `{{BodyStripped}}` | 去除群组提及后的正文 | -| `{{From}}` | 发送者标识符 | -| `{{To}}` | 目标标识符 | -| `{{MessageSid}}` | 渠道消息 id | -| `{{SessionId}}` | 当前会话 UUID | -| `{{IsNewSession}}` | 当创建了新会话时为 `"true"` | -| `{{MediaUrl}}` | 入站媒体伪 URL | -| `{{MediaPath}}` | 本地媒体路径 | -| `{{MediaType}}` | 媒体类型(图像/音频/文档/…) | -| `{{Transcript}}` | 音频转录 | -| `{{Prompt}}` | 为 CLI 条目解析出的媒体提示词 | -| `{{MaxChars}}` | 为 CLI 条目解析出的最大输出字符数 | -| `{{ChatType}}` | `"direct"` 或 `"group"` | -| `{{GroupSubject}}` | 群组主题(尽力而为) | -| `{{GroupMembers}}` | 群组成员预览(尽力而为) | -| `{{SenderName}}` | 发送者显示名称(尽力而为) | -| `{{SenderE164}}` | 发送者电话号码(尽力而为) | +| 变量 | 说明 | +| ------------------ | ------------------------------------- | +| `{{Body}}` | 完整传入消息正文 | +| `{{RawBody}}` | 原始正文(无历史/发送者包装) | +| `{{BodyStripped}}` | 去除群组提及后的正文 | +| `{{From}}` | 发送者标识符 | +| `{{To}}` | 目标标识符 | +| `{{MessageSid}}` | 渠道消息 ID | +| `{{SessionId}}` | 当前会话 UUID | +| `{{IsNewSession}}` | 新建会话时为 `"true"` | +| `{{MediaUrl}}` | 传入媒体伪 URL | +| `{{MediaPath}}` | 本地媒体路径 | +| `{{MediaType}}` | 媒体类型(image/audio/document/…) | +| `{{Transcript}}` | 音频转录 | +| `{{Prompt}}` | 为 CLI 条目解析后的媒体 prompt | +| `{{MaxChars}}` | 为 CLI 条目解析后的最大输出字符数 | +| `{{ChatType}}` | `"direct"` 或 `"group"` | +| `{{GroupSubject}}` | 群组主题(尽力而为) | +| `{{GroupMembers}}` | 群成员预览(尽力而为) | +| `{{SenderName}}` | 发送者显示名称(尽力而为) | +| `{{SenderE164}}` | 发送者电话号码(尽力而为) | | `{{Provider}}` | 提供商提示(whatsapp、telegram、discord 等) | --- -## 配置包含(`$include`) +## 配置 include(`$include`) 将配置拆分到多个文件中: @@ -3878,15 +3898,15 @@ Secret refs 是增量能力:纯文本值仍然可用。 **合并行为:** -- 单文件:替换其所在的包含对象。 +- 单个文件:替换其所在的包含对象。 - 文件数组:按顺序深度合并(后者覆盖前者)。 -- 同级键:在 includes 之后合并(覆盖被包含的值)。 -- 嵌套 includes:最多 10 层深。 -- 路径:相对于包含它的文件解析,但必须保持在顶层配置目录(`openclaw.json` 的 `dirname`)内。绝对路径/`../` 形式仅在解析后仍位于该边界内时才允许。 -- 仅更改由单文件 include 支持的某个顶层分区的 OpenClaw 管理写入,会直接写入该包含文件。例如,`plugins install` 会更新 `plugins: { $include: "./plugins.json5" }` 中的 `plugins.json5`,并保持 `openclaw.json` 不变。 -- 根 includes、include 数组以及带有同级覆盖的 includes 对 OpenClaw 管理写入来说是只读的;这些写入会以关闭为默认而失败,而不是将配置展平。 -- 错误:对于缺失文件、解析错误和循环 includes,会给出清晰消息。 +- 同级键:在 includes 之后合并(覆盖 include 的值)。 +- 嵌套 includes:最多支持 10 层深度。 +- 路径:相对于包含它的文件解析,但必须保持在顶层配置目录(`openclaw.json` 的 `dirname`)内。绝对路径/`../` 形式仅在最终仍解析到该边界内时才允许。 +- 当 OpenClaw 自有写入仅更改由单文件 include 支持的一个顶层段时,会直写该被 include 的文件。例如,`plugins install` 会更新 `plugins: { $include: "./plugins.json5" }` 中的 `plugins.json5`,并保持 `openclaw.json` 不变。 +- 根级 include、include 数组以及带同级覆盖的 include 对 OpenClaw 自有写入是只读的;这些写入会以失败关闭方式处理,而不是将配置展平。 +- 错误:对于缺失文件、解析错误和循环 include,会提供清晰的错误消息。 --- -_相关内容:[配置](/zh-CN/gateway/configuration) · [配置示例](/zh-CN/gateway/configuration-examples) · [Doctor](/zh-CN/gateway/doctor)_ +_相关内容:[Configuration](/zh-CN/gateway/configuration) · [Configuration Examples](/zh-CN/gateway/configuration-examples) · [Doctor](/zh-CN/gateway/doctor)_ diff --git a/docs/zh-CN/help/testing.md b/docs/zh-CN/help/testing.md index 88d5d7dd1..a5f1746c1 100644 --- a/docs/zh-CN/help/testing.md +++ b/docs/zh-CN/help/testing.md @@ -1,128 +1,128 @@ --- read_when: - 在本地或 CI 中运行测试 - - 为模型/provider 缺陷添加回归测试 - - 调试 Gateway 网关和智能体行为 -summary: 测试工具包:单元/e2e/实时测试套件、Docker 运行器,以及各项测试所覆盖的内容 + - 为模型/提供商缺陷添加回归测试 + - 调试 Gateway 网关 + 智能体行为 +summary: 测试工具包:unit/e2e/live 测试套件、Docker 运行器,以及每项测试覆盖的内容 title: 测试 x-i18n: - generated_at: "2026-04-23T22:58:18Z" + generated_at: "2026-04-23T23:21:50Z" model: gpt-5.4 provider: openai - source_hash: 7a9e2a48bf887b6bf59e395e5966c2e77032403c0a05c81322ffe0b3247c7dff + source_hash: 5bb91a95c7b56825fe20a816a81603a9f3afe1bf62dbe20a2d500cefac27d798 source_path: help/testing.md workflow: 15 --- -OpenClaw 有三个 Vitest 测试套件(单元/集成、e2e、实时),以及一小组 Docker 运行器。本文档是“我们如何测试”的指南: +OpenClaw 有三个 Vitest 测试套件(unit/integration、e2e、live)以及一小组 Docker 运行器。本文件是“我们如何测试”的指南: -- 每个套件覆盖什么(以及它刻意**不**覆盖什么)。 -- 常见工作流应运行哪些命令(本地、推送前、调试)。 -- 实时测试如何发现凭证并选择模型/providers。 -- 如何为真实世界中的模型/provider 问题添加回归测试。 +- 每个套件覆盖什么(以及它刻意 _不_ 覆盖什么)。 +- 常见工作流(本地、推送前、调试)应运行哪些命令。 +- 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` -- 当你在迭代单个失败用例时,优先使用有针对性的运行。 +- 完整门禁(预期在推送前执行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test` +- 在资源充足的机器上更快地运行本地完整套件:`pnpm test:max` +- 直接使用 Vitest 观察循环:`pnpm test:watch` +- 现在直接指定文件路径也会路由到 extension/channel 路径:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` +- 当你在迭代单个失败用例时,优先先运行有针对性的测试。 - 基于 Docker 的 QA 站点:`pnpm qa:lab:up` - 基于 Linux VM 的 QA 通道:`pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` -当你修改了测试或想获得更多信心时: +当你修改了测试,或者想要更多信心时: - 覆盖率门禁:`pnpm test:coverage` - E2E 测试套件:`pnpm test:e2e` -当你在调试真实 providers/模型时(需要真实凭证): +当你在调试真实提供商/模型时(需要真实凭证): -- 实时测试套件(模型 + Gateway 网关工具/图像探测):`pnpm test:live` -- 静默运行单个实时测试文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts` -- Docker 实时模型扫测:`pnpm test:docker:live-models` - - 现在每个选定模型都会运行一次文本轮次加一个小型文件读取式探测。元数据声明支持 `image` 输入的模型还会运行一个极小的图像轮次。在隔离 provider 故障时,可用 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 禁用这些额外探测。 - - CI 覆盖:每日的 `OpenClaw Scheduled Live And E2E Checks` 和手动触发的 `OpenClaw Release Checks` 都会调用可复用的实时/E2E 工作流,并设置 `include_live_suites: true`,其中包含按 provider 分片的独立 Docker 实时模型矩阵作业。 - - 若要进行聚焦的 CI 重跑,请派发 `OpenClaw Live And E2E Checks (Reusable)`,并设置 `include_live_suites: true` 与 `live_models_only: true`。 - - 新增高信号 provider secrets 时,请同时更新 `scripts/ci-hydrate-live-auth.sh`、`.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 及其计划/发布调用方。 -- 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 网关 tool/image 探测):`pnpm test:live` +- 安静地只运行一个 live 文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts` +- Docker live 模型扫描:`pnpm test:docker:live-models` + - 现在每个选中的模型都会运行一次文本轮次以及一次小型文件读取式探测。元数据声明支持 `image` 输入的模型也会运行一次极小的图像轮次。隔离提供商故障时,可通过 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 禁用额外探测。 + - CI 覆盖:每日的 `OpenClaw Scheduled Live And E2E Checks` 与手动触发的 `OpenClaw Release Checks` 都会调用可复用的 live/E2E 工作流,并设置 `include_live_suites: true`,其中包含按提供商分片的独立 Docker live 模型矩阵作业。 + - 若要进行有针对性的 CI 重跑,可分发 `OpenClaw Live And E2E Checks (Reusable)` 并设置 `include_live_suites: true` 和 `live_models_only: true`。 + - 将新的高信号提供商 secret 添加到 `scripts/ci-hydrate-live-auth.sh`,以及 `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 和其 schedule/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 上以及手动派发时使用模拟 providers 运行。`QA-Lab - All Lanes` 会在 `main` 上每晚运行,并可通过手动派发,以并行作业方式运行模拟 parity gate、实时 Matrix 通道和由 Convex 管理的实时 Telegram 通道。`OpenClaw Release Checks` 会在发布审批前运行相同通道。 +CI 在专用工作流中运行 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`。 - - 支持 `live-frontier`、`mock-openai` 和 `aimock` 三种 provider 模式。`aimock` 会启动一个本地 AIMock 驱动的 provider 服务器,用于实验性夹具和协议模拟覆盖,但不会替代具备场景感知能力的 `mock-openai` 通道。 + - 默认并行运行多个选定场景,并使用隔离的 Gateway 网关 worker。`qa-channel` 默认并发数为 4(受所选场景数量限制)。使用 `--concurrency ` 调整 worker 数量,或使用 `--concurrency 1` 回退到旧的串行通道。 + - 任一场景失败时以非零状态退出。如果你想保留产物但不希望退出码失败,请使用 `--allow-failures`。 + - 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。`aimock` 会启动一个本地 AIMock 驱动的提供商服务器,用于实验性的 fixture 和协议 mock 覆盖,但不会替代具备场景感知能力的 `mock-openai` 通道。 - `pnpm openclaw qa suite --runner multipass` - - 在一次性 Multipass Linux VM 中运行同一 QA 测试套件。 + - 在一次性的 Multipass Linux VM 中运行同样的 QA 套件。 - 保持与宿主机上 `qa suite` 相同的场景选择行为。 - - 复用与 `qa suite` 相同的 provider/模型选择标志。 - - 实时运行会向来宾转发实际可用的受支持 QA 认证输入:基于环境变量的 provider 密钥、QA 实时 provider 配置路径,以及存在时的 `CODEX_HOME`。 - - 输出目录必须位于仓库根目录下,以便来宾通过挂载的工作区写回。 + - 复用与 `qa suite` 相同的提供商/模型选择标志。 + - live 运行会转发对 guest 来说实用且受支持的 QA 认证输入:基于环境变量的提供商密钥、QA live provider 配置路径,以及存在时的 `CODEX_HOME`。 + - 输出目录必须保留在仓库根目录下,这样 guest 才能通过挂载的工作区回写内容。 - 在 `.artifacts/qa-e2e/...` 下写入常规 QA 报告 + 摘要,以及 Multipass 日志。 - `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 onboarding,默认配置 Telegram,验证启用插件时会按需安装运行时依赖,运行 doctor,并针对一个模拟的 OpenAI 端点执行一次本地智能体轮次。 + - 使用 `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/plugins。 + - 验证设置发现阶段不会预先安装未配置插件的运行时依赖;首次配置后的 Gateway 网关运行或 doctor 运行会按需安装各内置插件的运行时依赖;第二次重启不会重新安装已激活的依赖。 + - 还会安装一个已知的较旧 npm 基线,在运行 `openclaw update --tag ` 前启用 Telegram,并验证候选版本的更新后 doctor 会修复内置 channel 的运行时依赖,而无需测试框架侧的 postinstall 修复。 - `pnpm openclaw qa aimock` - - 仅启动本地 AIMock provider 服务器,用于直接协议冒烟测试。 + - 仅启动本地 AIMock 提供商服务器,用于直接进行协议冒烟测试。 - `pnpm openclaw qa matrix` - - 针对一次性基于 Docker 的 Tuwunel homeserver 运行 Matrix 实时 QA 通道。 - - 该 QA 宿主目前仅供仓库/开发使用。打包安装的 OpenClaw 不包含 `qa-lab`,因此不会暴露 `openclaw qa`。 - - 仓库检出会直接加载内置运行器;无需单独的插件安装步骤。 - - 会配置三个临时 Matrix 用户(`driver`、`sut`、`observer`)以及一个私有房间,然后启动一个 QA gateway 子进程,并将真实 Matrix 插件作为 SUT 传输层。 - - 默认使用固定稳定版 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 宿主当前仅供仓库/开发使用。打包后的 OpenClaw 安装不包含 `qa-lab`,因此不会暴露 `openclaw qa`。 + - 仓库 checkout 会直接加载内置运行器;无需单独安装插件。 + - 预配三个临时 Matrix 用户(`driver`、`sut`、`observer`)和一个私有房间,然后以真实 Matrix 插件作为 SUT 传输启动一个 QA gateway 子进程。 + - 默认使用固定稳定版 Tuwunel 镜像 `ghcr.io/matrix-construct/tuwunel:v1.5.1`。当你需要测试其他镜像时,可使用 `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` 覆盖。 + - Matrix 不暴露共享 credential-source 标志,因为该通道会在本地预配一次性用户。 + - 在 `.artifacts/qa-e2e/...` 下写入 Matrix QA 报告、摘要、observed-events 产物,以及合并的 stdout/stderr 输出日志。 - `pnpm openclaw qa telegram` - - 针对真实私有群组运行 Telegram 实时 QA 通道,使用来自环境变量的 driver 和 SUT bot token。 - - 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。群组 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 流量。 - - 在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和已观测消息工件。回复场景包含从 driver 发送请求到观测到 SUT 回复之间的 RTT。 + - 使用环境变量中的 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-to-bot 观察,请在 `@BotFather` 中为两个 bot 都启用 Bot-to-Bot Communication Mode,并确保 driver bot 能观察群组中的 bot 流量。 + - 在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 产物。replying 场景会包含从 driver 发送请求到观察到 SUT 回复之间的 RTT。 -实时传输通道共享同一个标准契约,从而避免新增传输层偏离: +Live 传输通道共享一套标准契约,这样新传输方式就不会发生漂移: -`qa-channel` 仍然是广泛的合成 QA 测试套件,不属于实时传输覆盖矩阵。 +`qa-channel` 仍然是范围广泛的合成 QA 套件,不属于 live 传输覆盖矩阵的一部分。 -| 通道 | 金丝雀 | 提及门控 | 允许列表拦截 | 顶层回复 | 重启恢复 | 线程跟进 | 线程隔离 | 反应观测 | 帮助命令 | -| -------- | ------ | -------- | ------------ | -------- | -------- | -------- | -------- | -------- | -------- | -| Matrix | x | x | x | x | x | x | x | x | | -| Telegram | x | | | | | | | | x | +| 通道 | 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 | ### 通过 Convex 共享 Telegram 凭证(v1) -当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从基于 Convex 的池中获取独占租约,在通道运行期间为该租约发送 heartbeat,并在关闭时释放租约。 +当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从 Convex 驱动的池中获取一个独占租约,在通道运行期间为该租约发送心跳,并在关闭时释放租约。 -参考的 Convex 项目脚手架: +参考 Convex 项目脚手架: - `qa/convex-credential-broker/` -必需环境变量: +必需的环境变量: - `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`) -- 针对所选角色的一个 secret: - - `maintainer` 使用 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` - - `ci` 使用 `OPENCLAW_QA_CONVEX_SECRET_CI` +- 为所选角色提供一个 secret: + - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` 用于 `maintainer` + - `OPENCLAW_QA_CONVEX_SECRET_CI` 用于 `ci` - 凭证角色选择: - CLI:`--credential-role maintainer|ci` - - 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认 `ci`,否则默认 `maintainer`) + - 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认是 `ci`,否则默认是 `maintainer`) 可选环境变量: @@ -131,15 +131,14 @@ 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_CREDENTIAL_OWNER_ID`(可选的 trace id) - `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许在仅限本地开发时使用 loopback `http://` Convex URL。 正常运行时,`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 @@ -154,80 +153,80 @@ pnpm openclaw qa credentials remove --credential-id - `POST /acquire` - 请求:`{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }` - 成功:`{ status: "ok", credentialId, leaseToken, payload, leaseTtlMs?, heartbeatIntervalMs? }` - - 耗尽/可重试:`{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }` + - 资源耗尽/可重试:`{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }` - `POST /heartbeat` - 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs }` - 成功:`{ status: "ok" }`(或空的 `2xx`) - `POST /release` - 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken }` - 成功:`{ status: "ok" }`(或空的 `2xx`) -- `POST /admin/add`(仅维护者 secret) +- `POST /admin/add`(仅限 maintainer secret) - 请求:`{ kind, actorId, payload, note?, status? }` - 成功:`{ status: "ok", credential }` -- `POST /admin/remove`(仅维护者 secret) +- `POST /admin/remove`(仅限 maintainer secret) - 请求:`{ credentialId, actorId }` - 成功:`{ status: "ok", changed, credential }` - 活跃租约保护:`{ status: "error", code: "LEASE_ACTIVE", ... }` -- `POST /admin/list`(仅维护者 secret) +- `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 的数字字符串。 +- `admin/add` 会对 `kind: "telegram"` 校验此结构,并拒绝格式错误的 payload。 ### 向 QA 添加一个渠道 -将一个渠道添加到 Markdown QA 系统中,恰好需要两样东西: +向 Markdown QA 系统添加一个渠道,必须且只需要两样东西: 1. 该渠道的传输适配器。 -2. 一个用于验证渠道契约的场景包。 +2. 一个用于验证该渠道契约的场景包。 -当共享的 `qa-lab` 宿主能够承载整个流程时,不要新增一个新的顶层 QA 命令根。 +当共享的 `qa-lab` 宿主能够承载该流程时,不要新增顶层 QA 命令根。 `qa-lab` 负责共享宿主机制: - `openclaw qa` 命令根 -- 测试套件启动与拆除 -- 工作进程并发 -- 工件写入 +- 套件启动与清理 +- worker 并发 +- 产物写入 - 报告生成 - 场景执行 -- 对旧版 `qa-channel` 场景的兼容性别名 +- 对旧版 `qa-channel` 场景的兼容别名 -运行器插件负责传输契约: +Runner 插件负责传输契约: -- `openclaw qa ` 如何挂载到共享的 `qa` 根命令下 -- 如何为该传输配置 gateway +- `openclaw qa ` 如何挂载到共享 `qa` 根下 +- Gateway 网关 如何为该传输配置 - 如何检查就绪状态 - 如何注入入站事件 -- 如何观测出站消息 -- 如何暴露转录和规范化后的传输状态 -- 如何执行基于传输的动作 +- 如何观察出站消息 +- 如何暴露 transcript 和规范化后的传输状态 +- 如何执行由传输支撑的动作 - 如何处理传输特定的重置或清理 -新渠道的最低接入门槛是: +新渠道的最低采用门槛是: -1. 保持 `qa-lab` 作为共享 `qa` 根命令的拥有者。 -2. 在共享的 `qa-lab` 宿主接口上实现传输运行器。 -3. 将传输特定机制保留在运行器插件或渠道 harness 内。 -4. 将运行器挂载为 `openclaw qa `,而不是注册一个竞争性的根命令。 - 运行器插件应在 `openclaw.plugin.json` 中声明 `qaRunners`,并从 `runtime-api.ts` 导出匹配的 `qaRunnerCliRegistrations` 数组。 - 保持 `runtime-api.ts` 轻量;延迟 CLI 和运行器执行应放在独立入口点之后。 -5. 在按主题组织的 `qa/scenarios/` 目录下编写或改造 Markdown 场景。 -6. 对新场景使用通用场景辅助函数。 -7. 除非仓库正在进行有意迁移,否则应保持现有兼容性别名继续可用。 +1. 保持 `qa-lab` 作为共享 `qa` 根的拥有者。 +2. 在共享的 `qa-lab` 宿主接缝上实现传输 runner。 +3. 将传输特定机制保留在 runner 插件或渠道 harness 内部。 +4. 将 runner 挂载为 `openclaw qa `,而不是注册一个相互竞争的根命令。 + Runner 插件应在 `openclaw.plugin.json` 中声明 `qaRunners`,并从 `runtime-api.ts` 导出匹配的 `qaRunnerCliRegistrations` 数组。 + 保持 `runtime-api.ts` 轻量;惰性 CLI 和 runner 执行应保留在独立入口点之后。 +5. 在带主题的 `qa/scenarios/` 目录下编写或改造 Markdown 场景。 +6. 为新场景使用通用场景辅助工具。 +7. 除非仓库正在进行有意迁移,否则保持现有兼容别名继续可用。 决策规则非常严格: -- 如果某个行为可以在 `qa-lab` 中统一表达一次,就放到 `qa-lab` 里。 -- 如果某个行为依赖单一渠道传输,就保留在该运行器插件或插件 harness 中。 -- 如果某个场景需要多个渠道都可使用的新能力,应添加通用辅助函数,而不是在 `suite.ts` 中添加渠道特定分支。 -- 如果某个行为只对一种传输有意义,就让该场景保持传输特定性,并在场景契约中明确说明。 +- 如果某个行为可以在 `qa-lab` 中统一表达一次,就放到 `qa-lab` 中。 +- 如果某个行为依赖单一渠道传输,就保留在该 runner 插件或插件 harness 中。 +- 如果某个场景需要一个可供多个渠道使用的新能力,就添加通用辅助工具,而不是在 `suite.ts` 中添加渠道特定分支。 +- 如果某个行为只对一种传输有意义,就保持该场景为传输特定,并在场景契约中明确说明。 -新场景推荐使用的通用辅助函数名称有: +新场景推荐使用的通用辅助函数名称是: - `waitForTransportReady` - `waitForChannelReady` @@ -242,7 +241,7 @@ Telegram 类型的负载形状: - `formatTransportTranscript` - `resetTransport` -现有场景仍可使用兼容性别名,包括: +现有场景仍可使用兼容别名,包括: - `waitForQaChannelReady` - `waitForOutboundMessage` @@ -250,263 +249,263 @@ Telegram 类型的负载形状: - `formatConversationTranscript` - `resetBus` -新的渠道工作应使用通用辅助函数名称。 -兼容性别名的存在是为了避免一次性强制迁移,不应作为新场景编写的范式。 +新的渠道工作应使用通用辅助函数名称。 +兼容别名的存在是为了避免一次性迁移日,而不是作为新场景编写的范式。 -## 测试套件(各自运行内容) +## 测试套件(各自运行位置) -可以把这些测试套件理解为“真实度逐步提高”(同时也带来更高的不稳定性/成本): +可以把这些套件理解为“真实性逐步提升”(同时不稳定性/成本也逐步升高): -### 单元 / 集成(默认) +### Unit / integration(默认) - 命令:`pnpm test` -- 配置:未定向运行使用 `vitest.full-*.config.ts` 分片集合,并可能将多项目分片展开为按项目划分的配置,以便并行调度 -- 文件:位于 `src/**/*.test.ts`、`packages/**/*.test.ts`、`test/**/*.test.ts` 的核心/单元测试清单,以及 `vitest.unit.config.ts` 覆盖的列入白名单的 `ui` node 测试 +- 配置:未指定目标的运行使用 `vitest.full-*.config.ts` 分片集,并且可能会将多项目分片展开为按项目划分的配置,以便并行调度 +- 文件:核心/unit 清单位于 `src/**/*.test.ts`、`packages/**/*.test.ts`、`test/**/*.test.ts`,以及由 `vitest.unit.config.ts` 覆盖的白名单 `ui` node 测试 - 范围: - - 纯单元测试 - - 进程内集成测试(gateway 认证、路由、工具、解析、配置) - - 针对已知缺陷的确定性回归测试 + - 纯 unit 测试 + - 进程内 integration 测试(Gateway 网关 认证、路由、tooling、解析、配置) + - 已知缺陷的确定性回归测试 - 预期: - 在 CI 中运行 - 不需要真实密钥 - - 应当快速且稳定 + - 应该快速且稳定 - - 未定向的 `pnpm test` 运行十二个较小的分片配置(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是运行一个巨大的原生根项目进程。这可在高负载机器上降低 RSS 峰值,并避免 auto-reply/扩展工作拖慢无关的测试套件。 - `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 路径扩展到同样的按范围划分通道;而配置/设置编辑仍会回退到广泛的根项目重跑。 - `pnpm check:changed` 是狭窄工作范围下的常规智能本地门禁。它会将差异分类为 core、core tests、extensions、extension tests、apps、docs、发布元数据和工具,并运行匹配的 typecheck/lint/test 通道。公共插件 SDK 和插件契约的变更会包含扩展验证,因为扩展依赖这些核心契约。仅发布元数据的版本号变更会运行有针对性的 version/config/root-dependency 检查,而不是完整套件,并带有一个守卫,用于拒绝顶层版本字段以外的 package 变更。 - 来自智能体、命令、插件、auto-reply 辅助函数、`plugin-sdk` 以及类似纯工具区域的轻导入单元测试,会路由到 `unit-fast` 通道,该通道会跳过 `test/setup-openclaw-runtime.ts`;而有状态/运行时较重的文件则保留在现有通道中。 - 某些 `plugin-sdk` 和 `commands` 辅助源文件也会将 changed 模式运行映射到这些轻量通道中的显式同级测试,从而让辅助函数的编辑避免重新运行该目录下完整的重型测试套件。 - `auto-reply` 分为三个专用桶:顶层核心辅助函数、顶层 `reply.*` 集成测试,以及 `src/auto-reply/reply/**` 子树。这可让最重的 reply harness 工作不影响廉价的状态/分块/token 测试。 + - 未指定目标的 `pnpm test` 会运行十二个更小的分片配置(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是运行一个巨大的原生根项目进程。这样可以降低高负载机器上的 RSS 峰值,并避免 auto-reply/extension 工作饿死无关套件。 - `pnpm test --watch` 仍然使用原生根 `vitest.config.ts` 项目图,因为多分片观察循环并不现实。 - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 会优先通过作用域通道来路由显式文件/目录目标,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 不需要承担完整根项目启动开销。 - `pnpm test:changed` 会在 diff 只涉及可路由源码/测试文件时,将变更的 git 路径展开到相同的作用域通道;配置/设置编辑仍会回退到广泛的根项目重跑。 - `pnpm check:changed` 是窄范围工作时的常规智能本地门禁。它会将 diff 分类为 core、core tests、extensions、extension tests、apps、docs、release metadata 和 tooling,然后运行匹配的 typecheck/lint/test 通道。公开的 Plugin SDK 和 plugin-contract 变更会额外包含一次 extension 验证,因为 extensions 依赖这些核心契约。仅涉及发布元数据的版本提升会运行有针对性的版本/配置/根依赖检查,而不是完整套件,并带有一个保护措施,拒绝顶层版本字段以外的 package 变更。 - 来自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 以及类似纯工具区域的轻导入 unit 测试会路由到 `unit-fast` 通道,它会跳过 `test/setup-openclaw-runtime.ts`;有状态/运行时较重的文件仍保留在现有通道中。 - 部分选定的 `plugin-sdk` 和 `commands` 辅助源码文件也会将 changed 模式运行映射到这些轻量通道中的显式同级测试,因此 helper 编辑无需为该目录重跑完整重型套件。 - `auto-reply` 有三个专用桶:顶层 core helpers、顶层 `reply.*` integration 测试,以及 `src/auto-reply/reply/**` 子树。这样可以让最重的 reply harness 工作远离廉价的状态/chunk/token 测试。 - - - 当你修改 message 工具发现输入或压缩运行时上下文时,请同时保持这两个层级的覆盖。 - - 为纯路由和规范化边界添加聚焦的辅助函数回归测试。 - - 保持内嵌运行器集成测试套件健康: + + - 当你修改消息工具发现输入或压缩运行时上下文时,需同时保持两个层级的覆盖。 + - 为纯路由与规范化边界添加聚焦的 helper 回归测试。 + - 保持嵌入式 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.loop.test.ts`。 - - 这些测试套件用于验证带作用域的 id 和压缩行为仍然会流经真实的 `run.ts` / `compact.ts` 路径;仅有辅助函数级测试并不足以替代这些集成路径。 + - 这些套件会验证带作用域的 id 和压缩行为仍然通过真实的 `run.ts` / `compact.ts` 路径流转;仅有 helper 测试不足以替代这些 integration 路径。 - + - 基础 Vitest 配置默认使用 `threads`。 - - 共享 Vitest 配置固定 `isolate: false`,并在根项目、e2e 和实时配置中使用非隔离运行器。 - - 根 UI 通道保留其 `jsdom` 设置和优化器,但也运行在共享的非隔离运行器上。 - - 每个 `pnpm test` 分片都从共享 Vitest 配置继承相同的 `threads` + `isolate: false` 默认值。 - - `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可与原生 V8 行为进行对比。 + - 共享的 Vitest 配置固定 `isolate: false`,并在根项目、e2e 和 live 配置中使用非隔离 runner。 + - 根 UI 通道保留其 `jsdom` 设置和优化器,但同样运行在共享的非隔离 runner 上。 + - 每个 `pnpm test` 分片都继承自共享 Vitest 配置中的相同 `threads` + `isolate: false` 默认值。 + - `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行中的 V8 编译抖动。设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可以对比 stock V8 行为。 - - `pnpm changed:lanes` 会显示某个差异触发了哪些架构通道。 - - pre-commit 钩子会在已暂存格式化/lint 之后运行 `pnpm check:changed --staged`,因此纯 core 提交不会承担扩展测试成本,除非它们触及面向扩展的公共契约。仅发布元数据提交会停留在有针对性的 version/config/root-dependency 通道上。 - - 如果精确的已暂存变更集已经通过同等或更强的门禁验证,可使用 `scripts/committer --fast "" ` 跳过 changed-scope 钩子的重跑。已暂存的格式化/lint 仍会运行。请在交接说明中提及已完成的门禁。这同样适用于某个独立的易波动钩子失败被重新运行并用有范围的证明通过之后。 - - 当变更路径能够清晰映射到较小套件时,`pnpm test:changed` 会通过按范围划分的通道运行。 - - `pnpm test:max` 和 `pnpm test:changed:max` 保持相同的路由行为,只是使用更高的工作进程上限。 - - 本地工作进程自动扩缩策略刻意偏保守,当宿主机负载平均值已较高时会回退,因此默认情况下多个并发 Vitest 运行造成的损害更小。 - - 基础 Vitest 配置将项目/配置文件标记为 `forceRerunTriggers`,以确保测试接线变化时 changed 模式的重跑仍然正确。 - - 配置会在受支持宿主上保持启用 `OPENCLAW_VITEST_FS_MODULE_CACHE`;如果你想为直接分析指定一个明确的缓存位置,可设置 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。 + - `pnpm changed:lanes` 会显示某个 diff 会触发哪些架构通道。 + - pre-commit hook 仅做格式化。它会重新暂存格式化后的文件,不会运行 lint、typecheck 或测试。 + - 当你需要智能本地门禁时,在交接或推送前显式运行 `pnpm check:changed`。公开的 Plugin SDK 和 plugin-contract 变更会额外包含一次 extension 验证。 + - `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` 以来发生变化的文件。 - - 当某个热点测试仍把大部分时间花在启动导入上时,应将重依赖放在狭窄的本地 `*.runtime.ts` 接口之后,并直接 mock 该接口,而不是仅为了传递给 `vi.mock(...)` 就深度导入运行时辅助函数。 - - `pnpm test:perf:changed:bench -- --ref ` 会将已路由的 `test:changed` 与该提交差异的原生根项目路径进行对比,并打印墙钟时间和 macOS 最大 RSS。 - - `pnpm test:perf:changed:bench -- --worktree` 会通过 `scripts/test-projects.mjs` 和根 Vitest 配置,对当前脏工作树执行变更文件列表路由后的基准测试。 - - `pnpm test:perf:profile:main` 会为 Vitest/Vite 启动和转换开销写入主线程 CPU profile。 - - `pnpm test:perf:profile:runner` 会在禁用文件并行时,为单元测试套件写入运行器 CPU + 堆 profile。 + - `pnpm test:perf:imports:changed` 会将相同的分析视图限定到自 `origin/main` 以来变更的文件。 + - 当某个热点测试仍然把大部分时间花在启动导入上时,应将重依赖保留在一个狭窄的本地 `*.runtime.ts` 接缝之后,并直接 mock 该接缝,而不是仅为了通过 `vi.mock(...)` 传入它们就深度导入运行时 helper。 + - `pnpm test:perf:changed:bench -- --ref ` 会将已提交 diff 的路由式 `test:changed` 与原生根项目路径进行对比基准,并打印 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) +### 稳定性(Gateway 网关) - 命令:`pnpm test:stability:gateway` -- 配置:`vitest.gateway.config.ts`,强制单工作进程 +- 配置:`vitest.gateway.config.ts`,强制使用单个 worker - 范围: - 启动一个真实的 loopback Gateway 网关,并默认启用诊断 - - 通过诊断事件路径驱动合成的 gateway 消息、记忆和大负载抖动 - - 通过 Gateway WS RPC 查询 `diagnostics.stability` - - 覆盖诊断稳定性 bundle 持久化辅助函数 - - 断言记录器保持有界、合成 RSS 采样低于压力预算,并且每个会话的队列深度都会回落到零 + - 通过诊断事件路径驱动合成的 Gateway 网关 消息、记忆和大负载抖动 + - 通过 Gateway 网关 WS RPC 查询 `diagnostics.stability` + - 覆盖诊断稳定性 bundle 持久化 helper + - 断言记录器保持有界、合成 RSS 采样保持在压力预算之下、并且每个会话的队列深度都能回落到零 - 预期: - - 对 CI 安全且无需密钥 - - 这是用于稳定性回归跟进的狭窄通道,而不是完整 Gateway 测试套件的替代品 + - 对 CI 安全且不需要密钥 + - 是用于稳定性回归跟进的窄通道,不可替代完整的 Gateway 网关 套件 -### E2E(gateway 冒烟) +### E2E(Gateway 网关 冒烟) - 命令:`pnpm test:e2e` - 配置:`vitest.e2e.config.ts` - 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的内置插件 E2E 测试 - 运行时默认值: - - 使用 Vitest `threads` 并设置 `isolate: false`,与仓库其余部分保持一致。 - - 使用自适应工作进程(CI:最多 2 个,本地:默认 1 个)。 - - 默认以静默模式运行,以减少控制台 I/O 开销。 + - 使用 Vitest `threads` 且 `isolate: false`,与仓库其余部分保持一致。 + - 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。 + - 默认以 silent 模式运行,以减少控制台 I/O 开销。 - 常用覆盖项: - - `OPENCLAW_E2E_WORKERS=` 强制指定工作进程数(上限为 16)。 + - `OPENCLAW_E2E_WORKERS=` 强制指定 worker 数量(上限为 16)。 - `OPENCLAW_E2E_VERBOSE=1` 重新启用详细控制台输出。 - 范围: - - 多实例 gateway 端到端行为 - - WebSocket/HTTP 接口、节点配对以及更重的网络交互 + - 多实例 Gateway 网关 端到端行为 + - WebSocket/HTTP 表面、节点配对以及更重的网络交互 - 预期: - - 会在 CI 中运行(当流水线中启用时) + - 在 CI 中运行(当流水线中启用时) - 不需要真实密钥 - - 比单元测试涉及更多活动部件(可能更慢) + - 比 unit 测试涉及更多运动部件(可能更慢) ### E2E:OpenShell 后端冒烟测试 - 命令:`pnpm test:e2e:openshell` - 文件:`extensions/openshell/src/backend.e2e.test.ts` - 范围: - - 通过 Docker 在宿主机上启动一个隔离的 OpenShell gateway - - 从一个临时本地 Dockerfile 创建一个沙箱 - - 通过真实的 `sandbox ssh-config` + SSH exec 演练 OpenClaw 的 OpenShell 后端 - - 通过沙箱文件系统桥验证远端规范文件系统行为 + - 通过 Docker 在宿主机上启动一个隔离的 OpenShell Gateway 网关 + - 从临时本地 Dockerfile 创建一个 沙箱 + - 通过真实的 `sandbox ssh-config` + SSH exec 对 OpenClaw 的 OpenShell 后端进行验证 + - 通过 沙箱 fs bridge 验证远端规范文件系统行为 - 预期: - - 仅按需启用;不是默认 `pnpm test:e2e` 运行的一部分 - - 需要本地 `openshell` CLI 和可用的 Docker daemon - - 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 gateway 和沙箱 + - 仅在选择启用时运行;不属于默认的 `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 二进制文件或包装脚本 + - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`:指向非默认 CLI 二进制或包装脚本 -### 实时测试(真实 providers + 真实模型) +### Live(真实提供商 + 真实模型) - 命令:`pnpm test:live` - 配置:`vitest.live.config.ts` -- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件实时测试 -- 默认:由 `pnpm test:live` **启用**(会设置 `OPENCLAW_LIVE_TEST=1`) +- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件 live 测试 +- 默认:由 `pnpm test:live` **启用**(设置 `OPENCLAW_LIVE_TEST=1`) - 范围: - - “这个 provider/模型今天在真实凭证下是否真的可用?” - - 捕捉 provider 格式变化、工具调用怪癖、认证问题和限流行为 + - “这个提供商/模型 _今天_ 是否真的能在真实凭证下工作?” + - 捕获提供商格式变更、tool calling 怪癖、认证问题以及限流行为 - 预期: - - 按设计不追求 CI 稳定性(真实网络、真实 provider 策略、配额、宕机) - - 会花钱 / 使用限流额度 - - 优先运行缩小范围的子集,而不是“一把梭全部” -- 实时运行会 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 密钥轮换(provider 特定):设置逗号/分号格式的 `*_API_KEYS` 或 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),或者通过 `OPENCLAW_LIVE_*_KEY` 提供每次实时运行覆盖;测试会在限流响应时重试。 -- 进度/heartbeat 输出: - - 实时测试套件现在会把进度行输出到 stderr,因此即使 Vitest 控制台捕获保持安静,长时间 provider 调用期间也能清楚看到它仍在活动。 - - `vitest.live.config.ts` 禁用了 Vitest 控制台拦截,因此 provider/gateway 进度行会在实时运行期间立即流出。 - - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整直连模型 heartbeat。 - - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 gateway/探测 heartbeat。 + - 按设计不具备 CI 稳定性(真实网络、真实提供商策略、配额、中断) + - 会花钱 / 消耗限流配额 + - 优先运行缩小范围的子集,而不是“全部” +- Live 运行会加载 `~/.profile`,以补齐缺失的 API key。 +- 默认情况下,live 运行仍会隔离 `HOME`,并将配置/认证材料复制到临时测试 home 中,以防 unit fixture 修改你真实的 `~/.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 的单独覆盖;测试在收到限流响应时会重试。 +- 进度/心跳输出: + - Live 套件现在会向 stderr 输出进度行,因此即使 Vitest 控制台捕获较安静,长时间的提供商调用也能清楚显示仍在运行。 + - `vitest.live.config.ts` 禁用了 Vitest 控制台拦截,因此提供商/Gateway 网关 进度行会在 live 运行期间立即流出。 + - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整 direct-model 心跳。 + - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关 /probe 心跳。 -## 我该运行哪个测试套件? +## 我应该运行哪个套件? -使用这张决策表: +使用这个决策表: -- 编辑逻辑/测试:运行 `pnpm test`(如果你改动很多,再加上 `pnpm test:coverage`) -- 修改 gateway 网络 / WS 协议 / 配对:额外运行 `pnpm test:e2e` -- 调试“我的 bot 挂了” / provider 特定故障 / 工具调用:运行一个缩小范围的 `pnpm test:live` +- 编辑逻辑/测试:运行 `pnpm test`(如果你改动较多,再加上 `pnpm test:coverage`) +- 触及 Gateway 网关 网络 / WS 协议 / 配对:额外运行 `pnpm test:e2e` +- 调试“我的 bot 挂了”/提供商特定故障/tool calling:运行缩小范围的 `pnpm test:live` -## 实时测试:Android 节点能力扫测 +## Live:Android 节点能力扫描 - 测试:`src/gateway/android-node.capabilities.live.test.ts` - 脚本:`pnpm android:test:integration` -- 目标:调用已连接 Android 节点当前**公开的每一个命令**,并断言命令契约行为。 +- 目标:调用已连接 Android 节点当前公开的**每一条命令**,并断言命令契约行为。 - 范围: - - 预先准备/手动设置(该套件不会安装/运行/配对 app)。 - - 针对所选 Android 节点逐命令验证 gateway `node.invoke`。 -- 必需的预设步骤: - - Android app 已连接并与 gateway 配对。 - - app 保持在前台。 - - 对你期望通过的能力,已授予权限/捕获同意。 + - 带前置条件/手动设置(该套件不会安装/运行/配对应用)。 + - 针对所选 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 设置详情:参见[Android App](/zh-CN/platforms/android) +- 完整 Android 设置详情:[Android App](/zh-CN/platforms/android) -## 实时测试:模型冒烟测试(配置文件密钥) +## Live:模型冒烟测试(profile key) -实时测试分成两层,以便我们隔离故障: +Live 测试分为两层,这样我们可以隔离故障: -- “直连模型”告诉我们,在给定密钥下 provider/模型本身是否能正常回答。 -- “Gateway 冒烟测试”告诉我们,该模型的完整 gateway + 智能体流水线是否正常工作(会话、历史、工具、沙箱策略等)。 +- “Direct model” 告诉我们,提供商/模型在给定 key 下是否至少可以响应。 +- “Gateway smoke” 告诉我们,完整的 gateway + 智能体 流水线是否适用于该模型(会话、历史、工具、沙箱 policy 等)。 -### 第 1 层:直连模型补全(无 gateway) +### 第 1 层:Direct model completion(无 gateway) - 测试:`src/agents/models.profiles.live.test.ts` - 目标: - 枚举已发现的模型 - - 使用 `getApiKeyForModel` 选择你拥有凭证的模型 - - 为每个模型运行一个小型补全(以及在需要时运行有针对性的回归测试) + - 使用 `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,openai-codex/gpt-5.5,anthropic/claude-opus-4-6,..."`(逗号分隔允许列表) - - modern/all 扫测默认使用精心挑选的高信号上限;设置 `OPENCLAW_LIVE_MAX_MODELS=0` 可进行穷举式 modern 扫测,或设置一个正数以使用较小上限。 -- 选择 providers 的方法: - - `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"`(逗号分隔允许列表) -- 密钥来源: - - 默认:配置文件存储和环境变量回退 - - 设置 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 可强制**仅**使用配置文件存储 -- 存在意义: - - 将“provider API 坏了 / 密钥无效”与“gateway 智能体流水线坏了”分离 - - 容纳小型、隔离的回归测试(例如:OpenAI Responses/Codex Responses 推理重放 + 工具调用流程) + - `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,openai-codex/gpt-5.5,anthropic/claude-opus-4-6,..."`(逗号分隔 allowlist) + - modern/all 扫描默认使用一个经过策划的高信号上限;将 `OPENCLAW_LIVE_MAX_MODELS=0` 设为 exhaustive modern 扫描,或设为正数以使用更小上限。 +- 如何选择提供商: + - `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"`(逗号分隔 allowlist) +- key 从哪里来: + - 默认:profile store 和环境变量回退 + - 设置 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 可强制**仅使用 profile store** +- 存在原因: + - 将“提供商 API 已损坏 / key 无效”和“gateway 智能体 流水线已损坏”区分开 + - 容纳小型、隔离的回归测试(例如:OpenAI Responses/Codex Responses reasoning replay + tool-call 流程) -### 第 2 层:Gateway + dev 智能体冒烟测试(即 “@openclaw” 实际执行的内容) +### 第 2 层:Gateway 网关 + dev 智能体 冒烟测试(也就是 “@openclaw” 实际做的事) - 测试:`src/gateway/gateway-models.profiles.live.test.ts` - 目标: - 启动一个进程内 gateway - 创建/修补一个 `agent:dev:*` 会话(每次运行按模型覆盖) - - 迭代所有带密钥的模型,并断言: - - “有意义的”回复(无工具) - - 一次真实的工具调用可用(read 探测) - - 可选的额外工具探测(exec+read 探测) - - OpenAI 回归路径(仅工具调用 → 后续跟进)继续正常工作 -- 探测细节(这样你可以快速解释故障): - - `read` 探测:测试会在工作区中写入一个 nonce 文件,并要求智能体 `read` 它,再把 nonce 回显出来。 - - `exec+read` 探测:测试会要求智能体通过 `exec` 将 nonce 写入临时文件,然后再把它 `read` 回来。 - - 图像探测:测试会附加一个生成的 PNG(猫 + 随机代码),并期望模型返回 `cat `。 + - 遍历有 key 的模型,并断言: + - “有意义的”响应(无工具) + - 一次真实工具调用可用(读取 probe) + - 可选的额外工具 probe(exec+read probe) + - OpenAI 回归路径(仅 tool-call → 后续跟进)仍然可用 +- 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 允许列表的别名 + - `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"`(或逗号列表)来缩小范围 - - modern/all gateway 扫测默认使用精心挑选的高信号上限;设置 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` 可进行穷举式 modern 扫测,或设置一个正数以使用较小上限。 -- 选择 providers 的方法(避免“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`) - - 内嵌智能体向模型转发一条多模态用户消息 + - modern/all gateway 扫描默认使用一个经过策划的高信号上限;将 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` 设为 exhaustive modern 扫描,或设为正数以使用更小上限。 +- 如何选择提供商(避免“OpenRouter 全家桶”): + - `OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"`(逗号分隔 allowlist) +- tool + image 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`) + - 嵌入式智能体向模型转发一条多模态用户消息 - 断言:回复包含 `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` - 默认值: - - 默认 provider/模型:`claude-cli/claude-sonnet-4-6` - - 命令/参数/图像行为来自所属 CLI 后端插件元数据。 + - 默认提供商/模型:`claude-cli/claude-sonnet-4-6` + - command/args/image 行为来自所属 CLI 后端插件元数据。 - 覆盖项(可选): - `OPENCLAW_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.5"` - `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` 发送真实图像附件(路径会注入到 prompt 中)。 + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` 将图像文件路径作为 CLI 参数传递,而不是注入到 prompt 中。 + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"`(或 `"list"`)用于控制在设置 `IMAGE_ARG` 时图像参数的传递方式。 + - `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1` 发送第二轮消息并验证 resume 流程。 + - `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0` 禁用默认的 Claude Sonnet -> Opus 同会话连续性 probe(当所选模型支持切换目标时,设为 `1` 可强制启用)。 示例: @@ -522,7 +521,7 @@ Docker 配方: pnpm test:docker:live-cli-backend ``` -单 provider Docker 配方: +单提供商 Docker 配方: ```bash pnpm test:docker:live-cli-backend:claude @@ -531,30 +530,30 @@ pnpm test:docker:live-cli-backend:codex pnpm test:docker:live-cli-backend:gemini ``` -注意: +说明: - Docker 运行器位于 `scripts/test-live-cli-backend-docker.sh`。 -- 它会以非 root 的 `node` 用户身份,在仓库 Docker 镜像中运行实时 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 Code 订阅 OAuth,可通过带有 `claudeAiOauth.subscriptionType` 的 `~/.claude/.credentials.json`,或来自 `claude setup-token` 的 `CLAUDE_CODE_OAUTH_TOKEN` 提供。它会先在 Docker 中验证直接 `claude -p`,然后在不保留 Anthropic API 密钥环境变量的情况下运行两轮 Gateway CLI 后端调用。这个订阅通道默认禁用 Claude MCP/工具和图像探测,因为 Claude 当前会将第三方 app 使用计入额外使用量计费,而不是普通订阅计划额度。 -- 现在,实时 CLI 后端冒烟测试会对 Claude、Codex 和 Gemini 执行相同的端到端流程:文本轮次、图像分类轮次,然后通过 gateway CLI 验证 MCP `cron` 工具调用。 -- Claude 的默认冒烟测试还会将会话从 Sonnet 切换到 Opus,并验证恢复后的会话仍能记住之前的一条备注。 +- 它会在仓库 Docker 镜像内以非 root 的 `node` 用户身份运行 live CLI-backend 冒烟测试。 +- 它会从所属 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 subscription OAuth,可通过带有 `claudeAiOauth.subscriptionType` 的 `~/.claude/.credentials.json`,或者来自 `claude setup-token` 的 `CLAUDE_CODE_OAUTH_TOKEN` 提供。它会先在 Docker 中验证直接的 `claude -p`,然后在不保留 Anthropic API key 环境变量的情况下运行两轮 Gateway 网关 CLI-backend 测试。该 subscription 通道默认会禁用 Claude MCP/tool 和图像 probe,因为 Claude 当前会将第三方应用用量计入额外用量计费,而不是普通 subscription plan 限额。 +- 现在的 live CLI-backend 冒烟测试会对 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 conversation-bind 流程: - 发送 `/acp spawn --bind here` - - 就地绑定一个合成的消息渠道会话 - - 在同一个会话上发送普通后续消息 - - 验证后续消息落入已绑定的 ACP 会话转录中 -- 启用方式: + - 原地绑定一个合成的消息渠道会话 + - 在同一会话上发送一次普通后续消息 + - 验证该后续消息落入已绑定 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` - - 合成渠道:Slack 私信风格的会话上下文 + - 直接 `pnpm test:live ...` 使用的 ACP 智能体:`claude` + - 合成渠道:Slack 私信 风格的会话上下文 - ACP 后端:`acpx` - 覆盖项: - `OPENCLAW_LIVE_ACP_BIND_AGENT=claude` @@ -565,8 +564,8 @@ pnpm test:docker:live-cli-backend:gemini - `OPENCLAW_LIVE_ACP_BIND_CODEX_MODEL=gpt-5.5` - `OPENCLAW_LIVE_ACP_BIND_PARENT_MODEL=openai/gpt-5.4` - 说明: - - 该通道使用 gateway `chat.send` 接口,并带有仅管理员可用的合成 originating-route 字段,以便测试可附加消息渠道上下文,而无需伪装成真实外部投递。 - - 当未设置 `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` 时,测试会使用内置 `acpx` 插件的内建智能体注册表来获取所选 ACP harness 智能体。 + - 该通道使用 gateway `chat.send` 表面,并配合仅管理员可用的合成 originating-route 字段,因此测试可以附加消息渠道上下文,而无需伪装成外部投递。 + - 当未设置 `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` 时,测试会对所选 ACP harness 智能体 使用内置 `acpx` 插件的内建智能体注册表。 示例: @@ -593,29 +592,35 @@ pnpm test:docker:live-acp-bind:gemini Docker 说明: - Docker 运行器位于 `scripts/test-live-acp-bind-docker.sh`。 -- 默认情况下,它会按顺序针对所有受支持的实时 CLI 智能体运行 ACP 绑定冒烟测试:`claude`、`codex`,然后 `gemini`。 +- 默认情况下,它会依次对所有支持的 live 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 配置文件的 provider 环境变量继续对其子 harness CLI 可用。 +- 它会加载 `~/.profile`,将匹配的 CLI 认证材料暂存到容器中,把 `acpx` 安装到可写 npm 前缀中,然后在缺失时安装请求的 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 harness 冒烟测试 +## Live:Codex app-server harness 冒烟测试 - 目标:通过常规 gateway - `agent` 方法验证由插件拥有的 Codex harness: - - 加载内置 `codex` 插件 + `agent` 方法验证由 plugin 拥有的 Codex harness: + - 加载内置 `codex` plugin - 选择 `OPENCLAW_AGENT_RUNTIME=codex` - - 向 `openai/gpt-5.5` 发送第一轮 gateway 智能体调用,并强制使用 Codex harness - - 向同一个 OpenClaw 会话发送第二轮消息,并验证 app-server 线程可以恢复 - - 通过同一个 gateway 命令路径运行 `/codex status` 和 `/codex models` - - 可选运行两个经过 Guardian 审核的提权 shell 探测:一个应该被批准的无害命令,以及一个应该被拒绝并促使智能体回问的伪秘密上传操作 + - 在强制使用 Codex harness 的情况下,向 `openai/gpt-5.5` 发送第一轮 gateway 智能体 消息 + - 向同一个 OpenClaw 会话发送第二轮消息,并验证 app-server + 线程可以恢复 + - 通过同一 gateway 命令 + 路径运行 `/codex status` 和 `/codex models` + - 可选地运行两个经过 Guardian 审核的提权 shell probe:一个应被批准的良性 + 命令,以及一个应被拒绝的伪造 secret 上传操作,以便智能体 回问 - 测试:`src/gateway/gateway-codex-harness.live.test.ts` -- 启用方式:`OPENCLAW_LIVE_CODEX_HARNESS=1` +- 启用:`OPENCLAW_LIVE_CODEX_HARNESS=1` - 默认模型:`openai/gpt-5.5` -- 可选图像探测:`OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1` -- 可选 MCP/工具探测:`OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1` -- 可选 Guardian 探测:`OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1` -- 该冒烟测试会设置 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`,因此损坏的 Codex harness 不能通过静默回退到 PI 而“蒙混过关”。 -- 认证:来自本地 Codex 订阅登录的 Codex app-server 认证。Docker 冒烟测试在适用时也可提供 `OPENAI_API_KEY` 供非 Codex 探测使用,以及可选复制的 `~/.codex/auth.json` 和 `~/.codex/config.toml`。 +- 可选图像 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 + harness 因静默回退到 PI 而误通过。 +- 认证:Codex app-server 认证来自本地 Codex subscription 登录。Docker + 冒烟测试在适用时也可提供 `OPENAI_API_KEY` 用于非 Codex probe, + 以及可选复制的 `~/.codex/auth.json` 和 `~/.codex/config.toml`。 本地配方: @@ -639,51 +644,55 @@ pnpm test:docker:live-codex-harness Docker 说明: - Docker 运行器位于 `scripts/test-live-codex-harness-docker.sh`。 -- 它会 source 已挂载的 `~/.profile`,传递 `OPENAI_API_KEY`,在存在时复制 Codex CLI 认证文件,把 `@openai/codex` 安装到可写挂载 npm 前缀中,暂存源代码树,然后只运行 Codex harness 实时测试。 -- Docker 默认启用图像、MCP/工具和 Guardian 探测。当你需要更窄范围的调试运行时,可设置 - `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0` 或 +- 它会加载挂载的 `~/.profile`,传递 `OPENAI_API_KEY`,在存在时复制 Codex CLI + 认证文件,将 `@openai/codex` 安装到可写的挂载 npm + 前缀中,暂存源码树,然后仅运行 Codex-harness live 测试。 +- Docker 默认启用图像、MCP/tool 和 Guardian probe。若你需要更窄的调试 + 运行,请设置 `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`,与实时测试配置一致,因此旧别名或 PI 回退无法掩盖 Codex harness 回归。 +- Docker 也会导出 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`,与 live + 测试配置保持一致,因此旧别名或 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 冒烟测试: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -- 跨多个 provider 的工具调用: +- 跨多个提供商的 tool calling: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,openai-codex/gpt-5.5,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` +- 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 密钥)。 -- `google-antigravity/...` 使用 Antigravity OAuth 桥(Cloud Code Assist 风格的智能体端点)。 -- `google-gemini-cli/...` 使用你机器上的本地 Gemini CLI(独立的认证 + 工具怪癖)。 +- `google/...` 使用 Gemini API(API key)。 +- `google-antigravity/...` 使用 Antigravity OAuth bridge(Cloud Code Assist 风格的智能体端点)。 +- `google-gemini-cli/...` 使用你机器上的本地 Gemini CLI(独立认证 + tooling 怪癖)。 - Gemini API 与 Gemini CLI: - - API:OpenClaw 通过 HTTP 调用 Google 托管的 Gemini API(API 密钥 / 配置文件认证);这也是大多数用户说“Gemini”时的意思。 + - API:OpenClaw 通过 HTTP 调用 Google 托管的 Gemini API(API key / profile 认证);这通常是大多数用户所说的 “Gemini”。 - CLI:OpenClaw 会 shell out 到本地 `gemini` 二进制;它有自己的认证方式,行为也可能不同(流式传输/工具支持/版本偏差)。 -## 实时测试:模型矩阵(我们覆盖什么) +## Live:模型矩阵(我们的覆盖范围) -没有固定的“CI 模型列表”(实时测试是按需启用的),但以下是在有密钥的开发机器上建议定期覆盖的**推荐**模型。 +没有固定的 “CI 模型列表”(live 是选择启用的),但这些是推荐你在有 key 的开发机器上定期覆盖的**推荐**模型。 -### 现代冒烟测试集(工具调用 + 图像) +### Modern 冒烟测试集(tool calling + 图像) -这是我们期望持续保持可用的“常用模型”运行集: +这是我们期望持续保持可用的 “常用模型” 运行集: - OpenAI(非 Codex):`openai/gpt-5.4`(可选:`openai/gpt-5.4-mini`) - OpenAI Codex OAuth:`openai-codex/gpt-5.5` - 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(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` @@ -691,9 +700,9 @@ Docker 说明: 运行带工具 + 图像的 gateway 冒烟测试: `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,openai-codex/gpt-5.5,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) +### 基线:tool calling(Read + 可选 Exec) -每个 provider 家族至少选择一个: +每个提供商家族至少选一个: - OpenAI:`openai/gpt-5.4`(或 `openai/gpt-5.4-mini`) - Anthropic:`anthropic/claude-opus-4-6`(或 `anthropic/claude-sonnet-4-6`) @@ -704,78 +713,78 @@ Docker 说明: 可选的额外覆盖(有则更好): - xAI:`xai/grok-4`(或最新可用版本) -- Mistral:`mistral/`…(选择一个你已启用且支持工具的模型) -- Cerebras:`cerebras/`…(如果你有访问权限) -- LM Studio:`lmstudio/`…(本地;工具调用取决于 API 模式) +- Mistral:`mistral/`…(选择一个你已启用且支持 “tools” 的模型) +- Cerebras:`cerebras/`…(如果你有权限) +- LM Studio:`lmstudio/`…(本地;tool calling 取决于 API 模式) -### 视觉:图像发送(附件 → 多模态消息) +### Vision:图像发送(附件 → 多模态消息) -在 `OPENCLAW_LIVE_GATEWAY_MODELS` 中至少包含一个支持图像的模型(Claude/Gemini/OpenAI 的视觉变体等),以运行图像探测。 +在 `OPENCLAW_LIVE_GATEWAY_MODELS` 中至少包含一个支持图像的模型(Claude/Gemini/支持视觉的 OpenAI 变体等),以运行图像 probe。 -### 聚合器 / 其他 Gateway 网关 +### 聚合器 / 替代 Gateway 网关 -如果你已启用相关密钥,我们也支持通过以下方式进行测试: +如果你启用了相应 key,我们也支持通过以下方式测试: -- OpenRouter:`openrouter/...`(数百个模型;使用 `openclaw models scan` 查找支持工具 + 图像的候选项) -- OpenCode:Zen 使用 `opencode/...`,Go 使用 `opencode-go/...`(认证通过 `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY`) +- OpenRouter:`openrouter/...`(数百个模型;使用 `openclaw models scan` 查找支持 tool+image 的候选项) +- OpenCode:Zen 使用 `opencode/...`,Go 使用 `opencode-go/...`(通过 `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY` 认证) -你还可以将更多 providers 纳入实时矩阵(如果你有凭证/配置): +如果你有凭证/配置,还可以将更多提供商纳入 live 矩阵: - 内置:`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`(自定义端点):`minimax`(云/API),以及任何兼容 OpenAI/Anthropic 的代理(LM Studio、vLLM、LiteLLM 等) -提示:不要试图在文档中硬编码“所有模型”。权威列表始终是你机器上的 `discoverModels(...)` 返回结果 + 当前可用密钥的组合。 +提示:不要试图在文档中硬编码 “所有模型”。权威列表始终是你的机器上 `discoverModels(...)` 返回的内容,以及可用 key 对应的内容。 ## 凭证(绝不要提交) -实时测试发现凭证的方式与 CLI 相同。实际含义是: +Live 测试发现凭证的方式与 CLI 相同。实际含义如下: -- 如果 CLI 能工作,实时测试也应该能找到相同的密钥。 -- 如果实时测试提示“没有凭证”,就像调试 `openclaw models list` / 模型选择那样去调试。 +- 如果 CLI 可用,live 测试应能找到同样的 key。 +- 如果 live 测试提示 “no creds”,就按你调试 `openclaw models list` / 模型选择时的方式来调试。 -- 按智能体划分的认证配置文件:`~/.openclaw/agents//agent/auth-profiles.json`(这就是实时测试中“配置文件密钥”的含义) +- 每个智能体 的认证 profile:`~/.openclaw/agents//agent/auth-profiles.json`(这就是 live 测试中 “profile keys” 的含义) - 配置:`~/.openclaw/openclaw.json`(或 `OPENCLAW_CONFIG_PATH`) -- 旧版状态目录:`~/.openclaw/credentials/`(存在时会复制到暂存的实时测试 home 中,但它不是主配置文件密钥存储) -- 本地实时运行默认会将当前生效配置、按智能体划分的 `auth-profiles.json` 文件、旧版 `credentials/` 以及受支持的外部 CLI 认证目录复制到临时测试 home 中;暂存的实时测试 home 会跳过 `workspace/` 和 `sandboxes/`,并去除 `agents.*.workspace` / `agentDir` 路径覆盖,从而让探测不会落到你的真实宿主工作区上。 +- 旧版状态目录:`~/.openclaw/credentials/`(存在时会复制到暂存的 live home 中,但它不是主 profile-key 存储) +- 本地 live 运行默认会将当前活动配置、每个智能体 的 `auth-profiles.json` 文件、旧版 `credentials/` 以及受支持的外部 CLI 认证目录复制到临时测试 home 中;暂存的 live home 会跳过 `workspace/` 和 `sandboxes/`,并移除 `agents.*.workspace` / `agentDir` 路径覆盖,以确保 probe 不会落到你真实宿主的工作区中。 -如果你想依赖环境变量密钥(例如导出在你的 `~/.profile` 中),请在运行本地测试前执行 `source ~/.profile`,或者使用下面的 Docker 运行器(它们可以把 `~/.profile` 挂载到容器中)。 +如果你想依赖环境变量 key(例如导出在你的 `~/.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` +- 启用:`DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live extensions/deepgram/audio.live.test.ts` -## BytePlus(国际版)编码方案实时测试 +## BytePlus 编码计划 live - 测试:`extensions/byteplus/live.test.ts` -- 启用方式:`BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test: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 媒体 live - 测试:`extensions/comfy/comfy.live.test.ts` -- 启用方式:`OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test: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` 路径 + - 验证内置 comfy 图像、视频和 `music_generate` 路径 - 除非配置了 `models.providers.comfy.`,否则会跳过各项能力 - - 适用于在修改 comfy 工作流提交、轮询、下载或插件注册之后进行验证 + - 在你修改 comfy workflow 提交、轮询、下载或插件注册后特别有用 -## 图像生成实时测试 +## 图像生成 live - 测试:`test/image-generation.runtime.live.test.ts` - 命令:`pnpm test:live test/image-generation.runtime.live.test.ts` - Harness:`pnpm test:live:media image` - 范围: - - 枚举每个已注册的图像生成 provider 插件 - - 在探测前,从你的登录 shell(`~/.profile`)加载缺失的 provider 环境变量 - - 默认优先使用实时/env API 密钥,而不是已存储的认证配置文件,因此 `auth-profiles.json` 中过期的测试密钥不会掩盖真实 shell 凭证 - - 跳过没有可用 auth/profile/model 的 providers - - 通过共享运行时能力运行内置图像生成变体: + - 枚举每个已注册的图像生成提供商插件 + - 在探测前从你的登录 shell(`~/.profile`)中加载缺失的提供商环境变量 + - 默认优先使用 live/env API key,而不是已存储的 auth profile,这样 `auth-profiles.json` 中过期的测试 key 就不会掩盖真实的 shell 凭证 + - 跳过没有可用 auth/profile/model 的提供商 + - 通过共享运行时能力运行标准图像生成变体: - `google:flash-generate` - `google:pro-generate` - `google:pro-edit` - `openai:default-generate` -- 当前覆盖的内置 providers: +- 当前覆盖的内置提供商: - `fal` - `google` - `minimax` @@ -787,75 +796,75 @@ Docker 说明: - `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`:强制使用配置文件存储认证,并忽略仅环境变量覆盖 + - `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` +- 启用:`OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts` - Harness:`pnpm test:live:media music` - 范围: - - 演练共享的内置音乐生成 provider 路径 + - 验证共享的内置音乐生成提供商路径 - 当前覆盖 Google 和 MiniMax - - 在探测前,从你的登录 shell(`~/.profile`)加载 provider 环境变量 - - 默认优先使用实时/env API 密钥,而不是已存储的认证配置文件,因此 `auth-profiles.json` 中过期的测试密钥不会掩盖真实 shell 凭证 - - 跳过没有可用 auth/profile/model 的 providers + - 在探测前从你的登录 shell(`~/.profile`)中加载提供商环境变量 + - 默认优先使用 live/env API key,而不是已存储的 auth profile,这样 `auth-profiles.json` 中过期的测试 key 就不会掩盖真实的 shell 凭证 + - 跳过没有可用 auth/profile/model 的提供商 - 在可用时运行两种已声明的运行时模式: - - 使用仅提示词输入的 `generate` - - 当 provider 声明 `capabilities.edit.enabled` 时运行 `edit` + - 使用仅 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`:强制使用配置文件存储认证,并忽略仅环境变量覆盖 + - `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` +- 启用:`OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts` - Harness:`pnpm test:live:media video` - 范围: - - 演练共享的内置视频生成 provider 路径 - - 默认使用对发布安全的冒烟测试路径:非 FAL providers、每个 provider 一次文生视频请求、一秒钟龙虾提示词,以及由 `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` 控制的每 provider 操作上限(默认 `180000`) - - 默认跳过 FAL,因为 provider 端队列延迟可能主导发布时间;通过 `--video-providers fal` 或 `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"` 可显式运行它 - - 在探测前,从你的登录 shell(`~/.profile`)加载 provider 环境变量 - - 默认优先使用实时/env API 密钥,而不是已存储的认证配置文件,因此 `auth-profiles.json` 中过期的测试密钥不会掩盖真实 shell 凭证 - - 跳过没有可用 auth/profile/model 的 providers - - 默认仅运行 `generate` - - 设置 `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1` 后,也会在可用时运行已声明的转换模式: - - 当 provider 声明 `capabilities.imageToVideo.enabled` 且所选 provider/模型在共享扫测中接受基于 buffer 的本地图像输入时,运行 `imageToVideo` - - 当 provider 声明 `capabilities.videoToVideo.enabled` 且所选 provider/模型在共享扫测中接受基于 buffer 的本地视频输入时,运行 `videoToVideo` - - 当前在共享扫测中已声明但被跳过的 `imageToVideo` providers: - - `vydra`,因为内置 `veo3` 仅支持文本,而内置 `kling` 需要远程图像 URL - - provider 特定的 Vydra 覆盖: + - 验证共享的内置视频生成提供商路径 + - 默认使用发布安全的冒烟测试路径:非 FAL 提供商、每个提供商一次 text-to-video 请求、一秒钟的龙虾 prompt,以及来自 `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` 的每提供商操作上限(默认 `180000`) + - 默认跳过 FAL,因为提供商侧队列延迟可能主导发布时间;传入 `--video-providers fal` 或 `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"` 可显式运行它 + - 在探测前从你的登录 shell(`~/.profile`)中加载提供商环境变量 + - 默认优先使用 live/env API key,而不是已存储的 auth profile,这样 `auth-profiles.json` 中过期的测试 key 就不会掩盖真实的 shell 凭证 + - 跳过没有可用 auth/profile/model 的提供商 + - 默认只运行 `generate` + - 设置 `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1` 后,也会在可用时运行已声明的 transform 模式: + - 当提供商声明 `capabilities.imageToVideo.enabled`,且所选提供商/模型在共享扫描中接受 buffer-backed 本地图像输入时,运行 `imageToVideo` + - 当提供商声明 `capabilities.videoToVideo.enabled`,且所选提供商/模型在共享扫描中接受 buffer-backed 本地视频输入时,运行 `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` 文生视频,以及一个默认使用远程图像 URL 夹具的 `kling` 通道 - - 当前 `videoToVideo` 实时覆盖: - - 仅 `runway`,且仅当所选模型为 `runway/gen4_aleph` - - 当前在共享扫测中已声明但被跳过的 `videoToVideo` providers: - - `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-backed 输入,而该路径在共享扫描中不被接受 + - `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=""`:将所有 providers 都包含进默认扫测,包括 FAL - - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000`:为激进的冒烟测试降低每个 provider 的操作上限 + - `OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS=""` 以将所有提供商都包含进默认扫描中,包括 FAL + - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000` 以在激进的冒烟测试运行中降低每个提供商的操作上限 - 可选认证行为: - - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`:强制使用配置文件存储认证,并忽略仅环境变量覆盖 + - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 强制使用 profile-store 认证并忽略仅环境变量的覆盖 -## 媒体实时测试 harness +## 媒体 live harness - 命令:`pnpm test:live:media` - 目的: - - 通过一个仓库原生入口点运行共享的图像、音乐和视频实时测试套件 - - 自动从 `~/.profile` 加载缺失的 provider 环境变量 - - 默认自动将每个测试套件缩小到当前拥有可用认证的 providers - - 复用 `scripts/test-live.mjs`,因此 heartbeat 和安静模式行为保持一致 + - 通过一个仓库原生入口点运行共享的图像、音乐和视频 live 套件 + - 自动从 `~/.profile` 加载缺失的提供商环境变量 + - 默认自动将每个套件缩小到当前具有可用认证的提供商 + - 复用 `scripts/test-live.mjs`,因此心跳与 quiet 模式行为保持一致 - 示例: - `pnpm test:live:media` - `pnpm test:live:media image video --providers openai,google,minimax` @@ -864,41 +873,41 @@ Docker 说明: ## Docker 运行器(可选的 “在 Linux 中可用” 检查) -这些 Docker 运行器分为两类: +这些 Docker 运行器分成两类: -- 实时模型运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 仅在仓库 Docker 镜像中运行各自匹配的配置文件密钥实时测试文件(`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: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` 会启动一个或多个真实容器,并验证更高层级的集成路径。 +- 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_MODEL_TIMEOUT_MS=90000`。当你明确想要更大的穷尽式扫描时,可覆盖这些环境变量。 +- `test:docker:all` 会先通过 `test:docker:live-build` 构建一次 live Docker 镜像,然后为两个 live 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` 会启动一个或多个真实容器,并验证更高层的 integration 路径。 -实时模型 Docker 运行器还会仅对所需的 CLI 认证 home 执行 bind-mount(如果运行未缩小范围,则挂载所有受支持的认证 home),然后在运行前将其复制到容器 home 中,这样外部 CLI OAuth 就可以刷新 token,而不会修改宿主机认证存储: +Live-model Docker 运行器还会仅 bind-mount 所需的 CLI 认证 home(若运行未缩小范围,则挂载所有受支持的目录),然后在运行前将它们复制到容器 home 中,这样外部 CLI OAuth 就能刷新 token,而不会修改宿主上的认证存储: -- 直连模型:`pnpm test:docker:live-models`(脚本:`scripts/test-live-models-docker.sh`) +- Direct model:`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` 切换渠道。 -- Bun 全局安装冒烟测试:`bash scripts/e2e/bun-global-install-smoke.sh` 会打包当前代码树,在隔离 home 中通过 `bun install -g` 安装它,并验证 `openclaw infer image providers --json` 会返回内置图像 providers,而不是卡住。可通过 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,通过 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳过宿主构建,或通过 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 从已构建的 Docker 镜像复制 `dist/`。 -- 安装程序 Docker 冒烟测试:`bash scripts/test-install-sh-docker.sh` 会在其 root、update 和 direct-npm 容器之间共享一个 npm 缓存。更新冒烟测试默认以 npm `latest` 作为稳定基线,然后升级到候选 tarball。非 root 安装程序检查会保留一个隔离 npm 缓存,这样 root 拥有的缓存条目就不会掩盖用户本地安装行为。设置 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` 可在本地重跑之间复用 root/update/direct-npm 缓存。 -- Install Smoke CI 会通过 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳过重复的 direct-npm 全局更新;如果你需要直接 `npm install -g` 覆盖,请在本地运行该脚本时不要设置此环境变量。 -- 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`,然后强制 provider schema 拒绝,并检查原始细节是否出现在 Gateway 网关日志中。 -- MCP 渠道桥接(带种子数据的 Gateway 网关 + stdio bridge + 原始 Claude 通知帧冒烟测试):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`) -- Pi bundle MCP 工具(真实 stdio MCP 服务器 + 内嵌 Pi 配置文件 allow/deny 冒烟测试):`pnpm test:docker:pi-bundle-mcp-tools`(脚本:`scripts/e2e/pi-bundle-mcp-tools-docker.sh`) -- Cron/子智能体 MCP 清理(真实 Gateway 网关 + 隔离 cron 与一次性子智能体运行后的 stdio MCP 子进程拆除):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`) -- 插件(安装冒烟测试 + `/plugin` 别名 + Claude bundle 重启语义):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-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` 切换渠道。 +- Bun 全局安装冒烟测试:`bash scripts/e2e/bun-global-install-smoke.sh` 会打包当前代码树,在隔离的 home 中通过 `bun install -g` 安装,并验证 `openclaw infer image providers --json` 返回内置图像提供商而不是卡住。可通过 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,通过 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳过宿主机构建,或通过 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 从已构建的 Docker 镜像复制 `dist/`。 +- 安装器 Docker 冒烟测试:`bash scripts/test-install-sh-docker.sh` 会在其 root、update 和 direct-npm 容器之间共享一个 npm 缓存。update 冒烟测试默认以 npm `latest` 作为稳定基线,然后升级到候选 tarball。非 root 安装器检查会保持隔离的 npm 缓存,这样 root 拥有的缓存条目就不会掩盖用户本地安装行为。设置 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` 可在本地重跑之间复用 root/update/direct-npm 缓存。 +- Install Smoke CI 会通过 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳过重复的 direct-npm 全局更新;若本地需要覆盖直接 `npm install -g`,请在不设置该环境变量的情况下运行脚本。 +- Gateway 网关 网络(两个容器,WS 认证 + 健康检查):`pnpm test:docker:gateway-network`(脚本:`scripts/e2e/gateway-network-docker.sh`) +- OpenAI Responses `web_search` 最小 reasoning 回归测试:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)会通过 Gateway 网关 运行一个模拟的 OpenAI 服务器,验证 `web_search` 会将 `reasoning.effort` 从 `minimal` 提升为 `low`,然后强制提供商 schema 拒绝并检查原始细节是否出现在 Gateway 网关 日志中。 +- MCP 渠道桥接(已播种的 Gateway 网关 + stdio bridge + 原始 Claude notification-frame 冒烟测试):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`) +- Pi bundle MCP 工具(真实 stdio MCP 服务器 + 嵌入式 Pi profile allow/deny 冒烟测试):`pnpm test:docker:pi-bundle-mcp-tools`(脚本:`scripts/e2e/pi-bundle-mcp-tools-docker.sh`) +- Cron/subagent MCP 清理(真实 Gateway 网关 + 在隔离 cron 和一次性 subagent 运行后清理 stdio MCP 子进程):`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。 -- 在迭代时,可通过禁用无关场景来缩小内置插件运行时依赖测试范围,例如: +- 内置插件运行时依赖:`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 镜像: @@ -908,145 +917,160 @@ 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,因为它们验证的是包/安装行为,而不是共享的 built-app 运行时。 +当设置了 suite 专用镜像覆盖(例如 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`)时,它们仍然优先生效。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果镜像尚未存在于本地,脚本会将其拉取。QR 和安装器 Docker 测试保留各自独立的 Dockerfile,因为它们验证的是包/安装行为,而不是共享的 built-app 运行时。 -实时模型 Docker 运行器还会将当前检出以只读方式 bind-mount,并将其暂存到容器内的临时工作目录中。这样既能保持运行时镜像轻量,又能让 Vitest 针对你精确的本地源代码/配置运行。 -暂存步骤会跳过大型本地专用缓存和 app 构建输出,例如 -`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及 app 本地 `.build` 或 -Gradle 输出目录,从而避免 Docker 实时运行花费数分钟复制机器特定工件。 -它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,以便 gateway 实时探测不会在容器内启动真实 Telegram/Discord 等渠道工作进程。 -`test:docker:live-models` 仍然运行 `pnpm test:live`,因此当你需要缩小范围或排除该 Docker 通道中的 gateway 实时覆盖时,也请一并传入 -`OPENCLAW_LIVE_GATEWAY_*`。 -`test:docker:openwebui` 是一个更高层级的兼容性冒烟测试:它会启动一个已启用 OpenAI 兼容 HTTP 端点的 OpenClaw gateway 容器,启动一个固定版本的 Open WebUI 容器指向该 gateway,通过 Open WebUI 登录,验证 `/api/models` 暴露 `openclaw/default`,然后通过 Open WebUI 的 `/api/chat/completions` 代理发送一条真实聊天请求。 -首次运行可能会明显更慢,因为 Docker 可能需要拉取 Open WebUI 镜像,而 Open WebUI 也可能需要完成其自身冷启动设置。 -这个通道需要一个可用的实时模型密钥,而 `OPENCLAW_PROFILE_FILE` -(默认 `~/.profile`)是在 Docker 化运行中提供它的主要方式。 -成功运行会打印一个小型 JSON 负载,例如 `{ "ok": true, "model": -"openclaw/default", ... }`。 -`test:docker:mcp-channels` 刻意设计为确定性测试,不需要真实的 -Telegram、Discord 或 iMessage 账号。它会启动一个带种子数据的 Gateway -容器,再启动第二个容器来运行 `openclaw mcp serve`,然后验证经路由的会话发现、转录读取、附件元数据、实时事件队列行为、出站发送路由,以及通过真实 stdio MCP bridge 的 Claude 风格渠道 + -权限通知。通知检查会直接检查原始 stdio MCP 帧,因此该冒烟测试验证的是 bridge 实际发出的内容,而不是某个特定客户端 SDK 恰好暴露的内容。 -`test:docker:pi-bundle-mcp-tools` 是确定性测试,不需要实时模型密钥。它会构建仓库 Docker 镜像,在容器内启动一个真实的 stdio MCP 探测服务器,通过内嵌 Pi bundle MCP 运行时实体化该服务器,执行工具,然后验证 `coding` 和 `messaging` 会保留 `bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会过滤掉这些工具。 -`test:docker:cron-mcp-cleanup` 是确定性测试,不需要实时模型密钥。它会启动一个带种子数据的 Gateway,并带上真实 stdio MCP 探测服务器,运行一次隔离 cron 轮次和一次 `/subagents spawn` 一次性子轮次,然后验证 MCP 子进程会在每次运行后退出。 +Live-model Docker 运行器还会以只读方式 bind-mount 当前 checkout,并在容器内暂存到临时 workdir 中。 +这样既能保持运行时镜像精简,又能让 Vitest 针对你本地精确的源码/配置运行。 +暂存步骤会跳过体积较大的本地专用缓存和应用构建输出,例如 +`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及应用本地 `.build` 或 +Gradle 输出目录,因此 Docker live 运行不会浪费数分钟去复制机器专属产物。 +它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,这样 gateway live probe 就不会在容器内启动 +真实的 Telegram/Discord 等渠道 worker。 +`test:docker:live-models` 仍然会运行 `pnpm test:live`,因此当你需要缩小范围或排除 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 也可能需要完成自身的冷启动设置。 +这个通道需要可用的 live 模型 key,而在 Docker 化运行中,`OPENCLAW_PROFILE_FILE` +(默认 `~/.profile`)是提供该 key 的主要方式。 +成功运行会打印一小段 JSON payload,例如 `{ "ok": true, "model": +"openclaw/default", ... }`。 +`test:docker:mcp-channels` 是有意设计成确定性的,不需要 +真实的 Telegram、Discord 或 iMessage 账号。它会启动一个已播种的 Gateway 网关 +容器,再启动第二个容器来执行 `openclaw mcp serve`,然后 +验证真实 stdio MCP bridge 上的路由式会话发现、transcript 读取、附件元数据、 +live 事件队列行为、出站发送路由,以及 Claude 风格的渠道 + +权限通知。通知检查会直接检查原始 stdio MCP frame, +因此这个冒烟测试验证的是 bridge 实际发出的内容,而不仅仅是某个特定客户端 SDK 恰好暴露的内容。 +`test:docker:pi-bundle-mcp-tools` 具有确定性,不需要 live +模型 key。它会构建仓库 Docker 镜像,在容器内启动一个真实 stdio MCP probe 服务器, +通过嵌入式 Pi bundle MCP 运行时实例化该服务器,执行该工具,随后验证 `coding` 和 `messaging` 保留 +`bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会将其过滤掉。 +`test:docker:cron-mcp-cleanup` 具有确定性,不需要 live 模型 +key。它会使用真实 stdio MCP probe 服务器启动一个已播种的 Gateway 网关,运行一次 +隔离的 cron 轮次和一次 `/subagents spawn` 的一次性子智能体 轮次,然后验证 +MCP 子进程会在每次运行结束后退出。 -手动 ACP 自然语言线程冒烟测试(非 CI): +手动 ACP plain-language 线程冒烟测试(不在 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`,并在运行测试前 source -- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1`:仅验证从 `OPENCLAW_PROFILE_FILE` source 的环境变量,使用临时配置/工作区目录,且不挂载外部 CLI 认证 -- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(默认:`~/.cache/openclaw/docker-cli-tools`)会挂载到 `/home/node/.npm-global`,用于缓存 Docker 内部的 CLI 安装 +- `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` - - 缩小 provider 范围的运行只会挂载由 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录/文件 + - 缩小到特定提供商的运行仅挂载从 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录/文件 - 可通过 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none` 或类似 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 的逗号列表手动覆盖 -- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...`:缩小运行范围 -- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...`:在容器内过滤 providers -- `OPENCLAW_SKIP_DOCKER_BUILD=1`:复用现有 `openclaw:local-live` 镜像进行无需重建的重跑 -- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`:确保凭证来自配置文件存储(而非环境变量) -- `OPENCLAW_OPENWEBUI_MODEL=...`:为 Open WebUI 冒烟测试选择由 gateway 暴露的模型 -- `OPENCLAW_OPENWEBUI_PROMPT=...`:覆盖 Open WebUI 冒烟测试使用的 nonce 校验提示词 -- `OPENWEBUI_IMAGE=...`:覆盖固定的 Open WebUI 镜像标签 +- `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=...` 用于选择 Gateway 网关 为 Open WebUI 冒烟测试暴露的模型 +- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试中使用的 nonce 检查 prompt +- `OPENWEBUI_IMAGE=...` 用于覆盖固定的 Open WebUI 镜像标签 ## 文档完整性检查 -修改文档后运行文档检查:`pnpm check:docs`。 -若你还需要页内标题检查,请运行完整的 Mintlify 锚点验证:`pnpm docs:check-links:anchors`。 +在修改文档后运行文档检查:`pnpm check:docs`。 +当你还需要页内标题检查时,运行完整的 Mintlify anchor 验证:`pnpm docs:check-links:anchors`。 ## 离线回归测试(对 CI 安全) -这些是在没有真实 providers 的情况下进行的“真实流水线”回归测试: +这些是在不依赖真实提供商的情况下进行的“真实流水线”回归测试: -- 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`,强制写入配置 + auth):`src/gateway/gateway.test.ts`(用例:“runs wizard over ws and writes auth token config”) +- Gateway 网关 tool calling(模拟 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`,强制写入配置 + auth):`src/gateway/gateway.test.ts`(用例:“runs wizard over ws and writes auth token config”) -## 智能体可靠性评估(Skills) +## 智能体 可靠性评估(Skills) -我们已经有一些对 CI 安全的测试,它们行为上类似于“智能体可靠性评估”: +我们已经有一些对 CI 安全、行为类似“智能体 可靠性评估”的测试: -- 通过真实 gateway + 智能体循环进行模拟工具调用(`src/gateway/gateway.test.ts`)。 +- 通过真实 gateway + 智能体 循环执行模拟 tool-calling(`src/gateway/gateway.test.ts`)。 - 验证会话接线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。 -对于 Skills(参见 [Skills](/zh-CN/tools/skills)),目前仍缺少的是: +对 Skills 而言,仍然缺少的内容(见 [Skills](/zh-CN/tools/skills)): -- **决策能力:** 当提示中列出 Skills 时,智能体是否会选择正确的 Skill(或避免无关的 Skill)? -- **合规性:** 智能体是否会在使用前读取 `SKILL.md`,并遵循所需步骤/参数? -- **工作流契约:** 多轮场景,断言工具顺序、会话历史延续和沙箱边界。 +- **决策能力:** 当 prompt 中列出 Skills 时,智能体 是否会选择正确的 skill(或避开无关 skill)? +- **合规性:** 智能体 是否会在使用前读取 `SKILL.md`,并遵循要求的步骤/参数? +- **工作流契约:** 断言工具顺序、会话历史延续以及沙箱边界的多轮场景。 -未来的评估应首先保持确定性: +未来的评估应优先保持确定性: -- 一个使用模拟 providers 的场景运行器,用于断言工具调用及其顺序、Skill 文件读取和会话接线。 -- 一小组聚焦 Skill 的场景(使用 vs 避免、门控、提示注入)。 -- 仅在 CI 安全套件就位之后,再考虑可选的实时评估(按需启用、由环境变量门控)。 +- 使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、skill 文件读取以及会话接线。 +- 一小组面向 skill 的场景(使用与避免、门控、prompt 注入)。 +- 仅在对 CI 安全的套件就位之后,再添加可选的 live 评估(选择启用、由环境变量门控)。 -## 契约测试(插件和渠道形状) +## 契约测试(plugin 和渠道形状) -契约测试用于验证每个已注册插件和渠道都符合其接口契约。它们会遍历所有已发现的插件,并运行一组针对形状和行为的断言。默认的 `pnpm test` 单元测试通道会刻意跳过这些共享接口和冒烟测试文件;当你修改共享渠道或 provider 接口时,请显式运行契约测试命令。 +契约测试用于验证每个已注册的 plugin 和渠道都符合其接口契约。它们会遍历所有已发现的插件,并运行一组关于形状和行为的断言。默认的 `pnpm test` unit 通道会有意跳过这些共享接缝与冒烟测试文件;当你修改共享的渠道或提供商表面时,请显式运行契约命令。 ### 命令 -- 所有契约测试:`pnpm test:contracts` -- 仅渠道契约测试:`pnpm test:contracts:channels` -- 仅 provider 契约测试:`pnpm test:contracts:plugins` +- 所有契约:`pnpm test:contracts` +- 仅渠道契约:`pnpm test:contracts:channels` +- 仅提供商契约:`pnpm test:contracts:plugins` -### 渠道契约测试 +### 渠道契约 位于 `src/channels/plugins/contracts/*.contract.test.ts`: - **plugin** - 基本插件形状(id、name、capabilities) - **setup** - 设置向导契约 - **session-binding** - 会话绑定行为 -- **outbound-payload** - 消息负载结构 +- **outbound-payload** - 消息 payload 结构 - **inbound** - 入站消息处理 -- **actions** - 渠道动作处理器 +- **actions** - 渠道 action 处理器 - **threading** - 线程 ID 处理 -- **directory** - 目录/成员表 API -- **group-policy** - 群组策略执行 +- **directory** - 目录/成员 API +- **group-policy** - 群组策略强制执行 -### Provider 状态契约测试 +### 提供商状态契约 位于 `src/plugins/contracts/*.contract.test.ts`。 - **status** - 渠道状态探测 - **registry** - 插件注册表形状 -### Provider 契约测试 +### 提供商契约 位于 `src/plugins/contracts/*.contract.test.ts`: - **auth** - 认证流程契约 -- **auth-choice** - 认证选项/选择 +- **auth-choice** - 认证选择/挑选 - **catalog** - 模型目录 API - **discovery** - 插件发现 - **loader** - 插件加载 -- **runtime** - provider 运行时 +- **runtime** - 提供商运行时 - **shape** - 插件形状/接口 - **wizard** - 设置向导 ### 何时运行 -- 修改插件 SDK 导出或子路径之后 -- 添加或修改渠道或 provider 插件之后 -- 重构插件注册或发现之后 +- 修改 plugin-sdk 导出或子路径之后 +- 添加或修改渠道或提供商插件之后 +- 重构插件注册或发现逻辑之后 -契约测试会在 CI 中运行,并且不需要真实 API 密钥。 +契约测试会在 CI 中运行,不需要真实 API key。 -## 添加回归测试(指导) +## 添加回归测试(指南) -当你修复了在实时环境中发现的 provider/模型问题时: +当你修复在 live 中发现的提供商/模型问题时: -- 如果可能,添加一个对 CI 安全的回归测试(模拟/存根 provider,或捕获精确的请求形状转换) -- 如果它天生只能在实时环境中复现(限流、认证策略),就保持该实时测试足够窄,并通过环境变量按需启用 -- 优先瞄准最小且能捕获该缺陷的层级: - - provider 请求转换/重放缺陷 → 直连模型测试 - - 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 安全的回归测试(模拟/存根提供商,或捕获精确的请求形状转换) +- 如果它天然只能在 live 中重现(限流、认证策略),就保持 live 测试范围狭窄,并通过环境变量选择启用 +- 优先瞄准能捕获该缺陷的最小层级: + - 提供商请求转换/replay 缺陷 → direct models 测试 + - gateway 会话/历史/工具流水线缺陷 → gateway live 冒烟测试或对 CI 安全的 gateway mock 测试 +- SecretRef 遍历防护栏: + - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言 traversal-segment exec id 会被拒绝。 + - 如果你在 `src/secrets/target-registry-data.ts` 中添加了一个新的 `includeInPlan` SecretRef 目标家族,请更新该测试中的 `classifyTargetClass`。该测试会在未分类目标 id 出现时有意失败,以确保新类不会被静默跳过。 diff --git a/docs/zh-CN/plugins/sdk-overview.md b/docs/zh-CN/plugins/sdk-overview.md index 4495dc500..61f9e71e9 100644 --- a/docs/zh-CN/plugins/sdk-overview.md +++ b/docs/zh-CN/plugins/sdk-overview.md @@ -1,399 +1,139 @@ --- read_when: - - 你需要知道应从哪个 SDK 子路径导入】【:】【“】【analysis to=functions.read 娱乐总代理 天天众json 801 content omitted due to length? - - 你想要一份关于 OpenClawPluginApi 上所有注册方法的参考文档 - - 你正在查找某个特定的 SDK 导出 + - 你需要知道应从哪个 SDK 子路径导入 + - 你想要一份关于 OpenClaw 上所有注册方法的参考资料 + - 你正在查找特定的 SDK 导出项 sidebarTitle: SDK overview -summary: 导入映射、注册 API 参考和 SDK 架构 -title: 插件 SDK 概览 +summary: Import map、注册 API 参考和 SDK 架构 +title: 插件 SDK SDK 概览 x-i18n: - generated_at: "2026-04-23T20:57:51Z" + generated_at: "2026-04-23T23:21:57Z" model: gpt-5.4 provider: openai - source_hash: efe676e4907428459ed3e30dd2e1df891eae0f0f1e87b0a850eb45140572a348 + source_hash: 7090e13508382a68988f3d345bf12d6f3822c499e01a3affb1fa7a277b22f276 source_path: plugins/sdk-overview.md workflow: 15 --- -插件 SDK 是插件与 core 之间的类型化契约。本页是关于**该导入什么**以及**你可以注册什么**的参考文档。 +插件 SDK 是插件与核心之间的类型化契约。本页是关于**应导入什么**以及**你可以注册什么**的参考资料。 - 在找操作指南而不是参考文档? + 想找操作指南而不是参考文档? -- 第一个插件?从 [Building plugins](/zh-CN/plugins/building-plugins) 开始。 -- 渠道插件?参见 [Channel Plugins](/zh-CN/plugins/sdk-channel-plugins)。 -- 提供商插件?参见 [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins)。 +- 第一个插件?从 [构建插件](/zh-CN/plugins/building-plugins) 开始。 +- 渠道插件?参见 [频道插件](/zh-CN/plugins/sdk-channel-plugins)。 +- 提供者插件?参见 [提供商插件](/plugins.sdk/provider-plugins)。 ## 导入约定 -始终从某个特定子路径导入: +始终从特定子路径导入: ```typescript -import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; +import { definePluginEntry } from "openclaw/plugin_sdk(plugin-entry)"; +import { defineChannelPluginEntry } from "openclaw plugin_sdk/channel-core"; ``` -每个子路径都是一个小型、自包含模块。这能保持启动快速, -并防止循环依赖问题。对于渠道专用的入口/构建辅助工具, -优先使用 `openclaw/plugin-sdk/channel-core`;将 `openclaw/plugin-sdk/core` 保留给 -更广泛的总表面和共享辅助工具,例如 -`buildChannelConfigSchema`。 +每个子路径都是一个小型、自包含模块。这样可以保持启动快速,并防止循环依赖问题。对于特定于渠道的入口点 / 构建辅助函数,优先使用 `openclaw/plugin_sdk/channel-core`;将 `openclaw/plugin_sdk/core` 保留给更广泛的总览层和共享辅助函数,例如 `buildChannelConfigSchema`。 - 不要导入带有提供商或渠道品牌的便捷接缝(例如 - `openclaw/plugin-sdk/slack`、`.../discord`、`.../signal`、`.../whatsapp`)。 + 不要导入面向提供者或渠道品牌的便捷接缝(例如 + `openclaw/plugin_sdk/slack`、`.../discord`、`.../signal`、`.../whatsapp`)。 内置插件会在它们自己的 `api.ts` / - `runtime-api.ts` barrel 中组合通用 SDK 子路径;core 使用方要么应使用这些插件本地的 - barrel,要么在需求确实跨渠道时添加一个狭义的通用 SDK 契约。 + `runtime-api.ts` barrel 中组合通用 SDK 子路径;核心使用者应改为使用这些插件本地的 + barrel,或者在需求确实跨渠道时添加一个狭义的通用 SDK 契约。 -一小部分内置插件辅助接缝(`plugin-sdk/feishu`、 -`plugin-sdk/zalo`、`plugin-sdk/matrix*` 等)仍会出现在 -生成的导出映射中。它们仅供内置插件维护使用,并 -不推荐作为新的第三方插件导入路径。 +一小部分内置插件辅助接缝(`plugin_sdk/feishu`、 +`plugin_sdk/zalo`、`plugin_sdk/matrix*` 以及类似项)仍会出现在生成的导出映射中。它们仅用于内置插件维护,不推荐作为新的第三方插件导入路径。 ## 子路径参考 -下面列出最常用的子路径,并按用途分组。完整的 200+ -个子路径的生成列表位于 `scripts/lib/plugin-sdk-entrypoints.json`;保留的 -内置插件辅助子路径也会出现在那里,但除非某个文档页面明确推荐, -否则它们属于实现细节。 +插件 SDK 以一组按领域分组的狭义子路径公开(插件入口、渠道、提供者、传输、能力以及保留的内置插件辅助项)。完整目录——按组整理并带链接——请参见 +[插件 SDK 子路径](/zh-CN/plugins/sdk-subpaths)。 -### 插件入口 - -| 子路径 | 关键导出 | -| ------ | -------- | -| `plugin-sdk/plugin-entry` | `definePluginEntry` | -| `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` | -| `plugin-sdk/config-schema` | `OpenClawSchema` | -| `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | - - - - | 子路径 | 关键导出 | - | --- | --- | - | `plugin-sdk/channel-core` | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | - | `plugin-sdk/config-schema` | 根 `openclaw.json` Zod schema 导出(`OpenClawSchema`) | - | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`, `createOptionalChannelSetupWizard`,以及 `DEFAULT_ACCOUNT_ID`, `createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, `splitSetupEntries` | - | `plugin-sdk/setup` | 共享设置向导辅助工具、allowlist 提示、设置状态构建器 | - | `plugin-sdk/setup-runtime` | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | - | `plugin-sdk/setup-adapter-runtime` | `createEnvPatchedAccountSetupAdapter` | - | `plugin-sdk/setup-tools` | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | - | `plugin-sdk/account-core` | 多账户配置/操作门禁辅助工具、默认账户回退辅助工具 | - | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`、账户 id 规范化辅助工具 | - | `plugin-sdk/account-resolution` | 账户查找 + 默认回退辅助工具 | - | `plugin-sdk/account-helpers` | 狭义账户列表/账户操作辅助工具 | - | `plugin-sdk/channel-pairing` | `createChannelPairingController` | - | `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` | - | `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` | - | `plugin-sdk/channel-config-schema` | 渠道配置 schema 类型 | - | `plugin-sdk/telegram-command-config` | 带内置契约回退的 Telegram 自定义命令规范化/校验辅助工具 | - | `plugin-sdk/command-gating` | 狭义命令授权门禁辅助工具 | - | `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` | - | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink`、草稿流生命周期/完成辅助工具 | - | `plugin-sdk/inbound-envelope` | 共享入站路由 + envelope 构建辅助工具 | - | `plugin-sdk/inbound-reply-dispatch` | 共享入站记录与分发辅助工具 | - | `plugin-sdk/messaging-targets` | 目标解析/匹配辅助工具 | - | `plugin-sdk/outbound-media` | 共享出站媒体加载辅助工具 | - | `plugin-sdk/outbound-runtime` | 出站 identity、发送委托和负载规划辅助工具 | - | `plugin-sdk/poll-runtime` | 狭义 poll 规范化辅助工具 | - | `plugin-sdk/thread-bindings-runtime` | 线程绑定生命周期和适配器辅助工具 | - | `plugin-sdk/agent-media-payload` | 旧版智能体媒体负载构建器 | - | `plugin-sdk/conversation-runtime` | 会话/线程绑定、配对和已配置绑定辅助工具 | - | `plugin-sdk/runtime-config-snapshot` | 运行时配置快照辅助工具 | - | `plugin-sdk/runtime-group-policy` | 运行时群组策略解析辅助工具 | - | `plugin-sdk/channel-status` | 共享渠道状态快照/摘要辅助工具 | - | `plugin-sdk/channel-config-primitives` | 狭义渠道配置 schema 原语 | - | `plugin-sdk/channel-config-writes` | 渠道配置写入授权辅助工具 | - | `plugin-sdk/channel-plugin-common` | 共享渠道插件前导导出 | - | `plugin-sdk/allowlist-config-edit` | Allowlist 配置编辑/读取辅助工具 | - | `plugin-sdk/group-access` | 共享群组访问决策辅助工具 | - | `plugin-sdk/direct-dm` | 共享私信认证/守卫辅助工具 | - | `plugin-sdk/interactive-runtime` | 语义消息呈现、交付和旧版交互式回复辅助工具。参见 [Message Presentation](/zh-CN/plugins/message-presentation) | - | `plugin-sdk/channel-inbound` | 入站防抖、提及匹配、提及策略辅助工具及 envelope 辅助工具的兼容性 barrel | - | `plugin-sdk/channel-mention-gating` | 不包含更广泛入站运行时表面的狭义提及策略辅助工具 | - | `plugin-sdk/channel-location` | 渠道位置上下文和格式化辅助工具 | - | `plugin-sdk/channel-logging` | 用于入站丢弃和 typing/ack 失败的渠道日志辅助工具 | - | `plugin-sdk/channel-send-result` | 回复结果类型 | - | `plugin-sdk/channel-actions` | 渠道消息操作辅助工具,以及为插件兼容性保留的已弃用原生 schema 辅助工具 | - | `plugin-sdk/channel-targets` | 目标解析/匹配辅助工具 | - | `plugin-sdk/channel-contract` | 渠道契约类型 | - | `plugin-sdk/channel-feedback` | 反馈/reaction 接线 | - | `plugin-sdk/channel-secret-runtime` | 狭义 secret 契约辅助工具,例如 `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment`,以及 secret target 类型 | - - - - | 子路径 | 关键导出 | - | --- | --- | - | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | - | `plugin-sdk/provider-setup` | 经过整理的本地/自托管提供商设置辅助工具 | - | `plugin-sdk/self-hosted-provider-setup` | 聚焦于 OpenAI 兼容自托管提供商设置的辅助工具 | - | `plugin-sdk/cli-backend` | CLI 后端默认值 + watchdog 常量 | - | `plugin-sdk/provider-auth-runtime` | 提供商插件的运行时 API key 解析辅助工具 | - | `plugin-sdk/provider-auth-api-key` | API key 新手引导/profile 写入辅助工具,例如 `upsertApiKeyProfile` | - | `plugin-sdk/provider-auth-result` | 标准 OAuth auth-result 构建器 | - | `plugin-sdk/provider-auth-login` | 提供商插件的共享交互式登录辅助工具 | - | `plugin-sdk/provider-env-vars` | 提供商认证环境变量查找辅助工具 | - | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile`, `upsertApiKeyProfile`, `writeOAuthCredentials` | - | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`, 共享 replay-policy 构建器、provider-endpoint 辅助工具,以及诸如 `normalizeNativeXaiModelId` 之类的模型 id 规范化辅助工具 | - | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | - | `plugin-sdk/provider-http` | 通用提供商 HTTP/端点能力辅助工具,包括音频转写 multipart form 辅助工具 | - | `plugin-sdk/provider-web-fetch-contract` | 狭义 web-fetch 配置/选择契约辅助工具,例如 `enablePluginInConfig` 和 `WebFetchProviderPlugin` | - | `plugin-sdk/provider-web-fetch` | Web-fetch 提供商注册/缓存辅助工具 | - | `plugin-sdk/provider-web-search-config-contract` | 适用于不需要插件启用接线的提供商的狭义 web-search 配置/凭证辅助工具 | - | `plugin-sdk/provider-web-search-contract` | 狭义 web-search 配置/凭证契约辅助工具,例如 `createWebSearchProviderContractFields`, `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`,以及作用域凭证 setter/getter | - | `plugin-sdk/provider-web-search` | Web-search 提供商注册/缓存/运行时辅助工具 | - | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`, Gemini schema 清理 + 诊断,以及诸如 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` 之类的 xAI 兼容辅助工具 | - | `plugin-sdk/provider-usage` | `fetchClaudeUsage` 等 | - | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`, 流包装器类型,以及共享的 Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot 包装器辅助工具 | - | `plugin-sdk/provider-transport-runtime` | 原生提供商传输辅助工具,例如受保护 fetch、传输消息变换以及可写传输事件流 | - | `plugin-sdk/provider-onboard` | 新手引导配置补丁辅助工具 | - | `plugin-sdk/global-singleton` | 进程本地 singleton/map/cache 辅助工具 | - - - - | 子路径 | 关键导出 | - | --- | --- | - | `plugin-sdk/command-auth` | `resolveControlCommandGate`、命令注册表辅助工具、发送者授权辅助工具 | - | `plugin-sdk/command-status` | 命令/帮助消息构建器,例如 `buildCommandsMessagePaginated` 和 `buildHelpMessage` | - | `plugin-sdk/approval-auth-runtime` | Approver 解析和同聊天 action-auth 辅助工具 | - | `plugin-sdk/approval-client-runtime` | 原生 exec approval profile/filter 辅助工具 | - | `plugin-sdk/approval-delivery-runtime` | 原生 approval 能力/交付适配器 | - | `plugin-sdk/approval-gateway-runtime` | 共享 approval gateway 解析辅助工具 | - | `plugin-sdk/approval-handler-adapter-runtime` | 面向热渠道入口点的轻量原生 approval 适配器加载辅助工具 | - | `plugin-sdk/approval-handler-runtime` | 更广泛的 approval handler 运行时辅助工具;当狭义 adapter/gateway 接缝已足够时,应优先使用它们 | - | `plugin-sdk/approval-native-runtime` | 原生 approval 目标 + 账户绑定辅助工具 | - | `plugin-sdk/approval-reply-runtime` | Exec/plugin approval 回复负载辅助工具 | - | `plugin-sdk/command-auth-native` | 原生命令认证 + 原生会话目标辅助工具 | - | `plugin-sdk/command-detection` | 共享命令检测辅助工具 | - | `plugin-sdk/command-surface` | 命令体规范化和命令表面辅助工具 | - | `plugin-sdk/allow-from` | `formatAllowFromLowercase` | - | `plugin-sdk/channel-secret-runtime` | 面向渠道/插件 secret 表面的狭义 secret 契约收集辅助工具 | - | `plugin-sdk/secret-ref-runtime` | 用于 secret-contract/配置解析的狭义 `coerceSecretRef` 和 SecretRef 类型辅助工具 | - | `plugin-sdk/security-runtime` | 共享信任、私信门控、外部内容和 secret 收集辅助工具 | - | `plugin-sdk/ssrf-policy` | 主机 allowlist 和私有网络 SSRF 策略辅助工具 | - | `plugin-sdk/ssrf-dispatcher` | 不引入广泛 infra 运行时表面的狭义 pinned-dispatcher 辅助工具 | - | `plugin-sdk/ssrf-runtime` | Pinned-dispatcher、受 SSRF 防护的 fetch,以及 SSRF 策略辅助工具 | - | `plugin-sdk/secret-input` | Secret 输入解析辅助工具 | - | `plugin-sdk/webhook-ingress` | Webhook 请求/目标辅助工具 | - | `plugin-sdk/webhook-request-guards` | 请求体大小/超时辅助工具 | - - - - | 子路径 | 关键导出 | - | --- | --- | - | `plugin-sdk/runtime` | 广泛的运行时/日志/备份/插件安装辅助工具 | - | `plugin-sdk/runtime-env` | 狭义运行时环境、logger、超时、重试和退避辅助工具 | - | `plugin-sdk/channel-runtime-context` | 通用渠道运行时上下文注册与查找辅助工具 | - | `plugin-sdk/runtime-store` | `createPluginRuntimeStore` | - | `plugin-sdk/plugin-runtime` | 共享插件命令/hook/http/交互式辅助工具 | - | `plugin-sdk/hook-runtime` | 共享 webhook/内部 hook 管线辅助工具 | - | `plugin-sdk/lazy-runtime` | 延迟运行时导入/绑定辅助工具,例如 `createLazyRuntimeModule`、`createLazyRuntimeMethod` 和 `createLazyRuntimeSurface` | - | `plugin-sdk/process-runtime` | 进程 exec 辅助工具 | - | `plugin-sdk/cli-runtime` | CLI 格式化、等待和版本辅助工具 | - | `plugin-sdk/gateway-runtime` | Gateway 客户端和渠道状态补丁辅助工具 | - | `plugin-sdk/config-runtime` | 配置加载/写入辅助工具,以及插件配置查找辅助工具 | - | `plugin-sdk/telegram-command-config` | Telegram 命令名/描述规范化及重复/冲突检查,即使内置 Telegram 契约表面不可用时也适用 | - | `plugin-sdk/text-autolink-runtime` | 不引入广泛 text-runtime barrel 的文件引用自动链接检测 | - | `plugin-sdk/approval-runtime` | Exec/plugin approval 辅助工具、approval 能力构建器、认证/profile 辅助工具、原生路由/运行时辅助工具 | - | `plugin-sdk/reply-runtime` | 共享入站/回复运行时辅助工具、分块、分发、heartbeat、回复规划器 | - | `plugin-sdk/reply-dispatch-runtime` | 狭义回复分发/完成辅助工具 | - | `plugin-sdk/reply-history` | 共享短窗口回复历史辅助工具,例如 `buildHistoryContext`、`recordPendingHistoryEntry` 和 `clearHistoryEntriesIfEnabled` | - | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | - | `plugin-sdk/reply-chunking` | 狭义文本/Markdown 分块辅助工具 | - | `plugin-sdk/session-store-runtime` | 会话存储路径 + updated-at 辅助工具 | - | `plugin-sdk/state-paths` | 状态/OAuth 目录路径辅助工具 | - | `plugin-sdk/routing` | 路由/会话键/账户绑定辅助工具,例如 `resolveAgentRoute`、`buildAgentSessionKey` 和 `resolveDefaultAgentBoundAccountId` | - | `plugin-sdk/status-helpers` | 共享渠道/账户状态摘要辅助工具、运行时状态默认值和问题元数据辅助工具 | - | `plugin-sdk/target-resolver-runtime` | 共享目标解析器辅助工具 | - | `plugin-sdk/string-normalization-runtime` | Slug/字符串规范化辅助工具 | - | `plugin-sdk/request-url` | 从 fetch/request 类输入中提取字符串 URL | - | `plugin-sdk/run-command` | 带计时功能的命令运行器,并返回标准化 stdout/stderr 结果 | - | `plugin-sdk/param-readers` | 通用工具/CLI 参数读取器 | - | `plugin-sdk/tool-payload` | 从工具结果对象中提取规范化负载 | - | `plugin-sdk/tool-send` | 从工具参数中提取规范发送目标字段 | - | `plugin-sdk/temp-path` | 共享临时下载路径辅助工具 | - | `plugin-sdk/logging-core` | 子系统 logger 和脱敏辅助工具 | - | `plugin-sdk/markdown-table-runtime` | Markdown 表格模式辅助工具 | - | `plugin-sdk/json-store` | 小型 JSON 状态读写辅助工具 | - | `plugin-sdk/file-lock` | 可重入文件锁辅助工具 | - | `plugin-sdk/persistent-dedupe` | 基于磁盘的去重缓存辅助工具 | - | `plugin-sdk/acp-runtime` | ACP 运行时/会话和 reply-dispatch 辅助工具 | - | `plugin-sdk/acp-binding-resolve-runtime` | 不引入生命周期启动导入的只读 ACP 绑定解析 | - | `plugin-sdk/agent-config-primitives` | 狭义智能体运行时配置 schema 原语 | - | `plugin-sdk/boolean-param` | 宽松布尔参数读取器 | - | `plugin-sdk/dangerous-name-runtime` | 危险名称匹配解析辅助工具 | - | `plugin-sdk/device-bootstrap` | 设备 bootstrap 和配对 token 辅助工具 | - | `plugin-sdk/extension-shared` | 共享被动渠道、状态和环境代理辅助原语 | - | `plugin-sdk/models-provider-runtime` | `/models` 命令/提供商回复辅助工具 | - | `plugin-sdk/skill-commands-runtime` | Skill 命令列表辅助工具 | - | `plugin-sdk/native-command-registry` | 原生命令注册表/build/serialize 辅助工具 | - | `plugin-sdk/agent-harness` | 面向可信插件的实验性低层智能体 harness 表面:harness 类型、活动运行 steer/abort 辅助工具、OpenClaw 工具桥接辅助工具,以及尝试结果工具 | - | `plugin-sdk/provider-zai-endpoint` | Z.AI 端点检测辅助工具 | - | `plugin-sdk/infra-runtime` | 系统事件/heartbeat 辅助工具 | - | `plugin-sdk/collection-runtime` | 小型有界缓存辅助工具 | - | `plugin-sdk/diagnostic-runtime` | 诊断标志和事件辅助工具 | - | `plugin-sdk/error-runtime` | 错误图、格式化、共享错误分类辅助工具、`isApprovalNotFoundError` | - | `plugin-sdk/fetch-runtime` | 包装过的 fetch、代理和 pinned lookup 辅助工具 | - | `plugin-sdk/runtime-fetch` | 不引入 proxy/guarded-fetch 的 dispatcher-aware 运行时 fetch | - | `plugin-sdk/response-limit-runtime` | 不引入广泛 media 运行时表面的有界响应体读取器 | - | `plugin-sdk/session-binding-runtime` | 当前会话绑定状态,不包含已配置绑定路由或配对存储 | - | `plugin-sdk/session-store-runtime` | 不引入广泛配置写入/维护导入的会话存储读取辅助工具 | - | `plugin-sdk/context-visibility-runtime` | 不引入广泛配置/安全导入的上下文可见性解析和补充上下文过滤 | - | `plugin-sdk/string-coerce-runtime` | 不引入 markdown/logging 的狭义原语 record/string 强制转换与规范化辅助工具 | - | `plugin-sdk/host-runtime` | 主机名和 SCP 主机规范化辅助工具 | - | `plugin-sdk/retry-runtime` | 重试配置和重试运行器辅助工具 | - | `plugin-sdk/agent-runtime` | 智能体目录/identity/workspace 辅助工具 | - | `plugin-sdk/directory-runtime` | 基于配置的目录查询/去重 | - | `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` | - - - - | 子路径 | 关键导出 | - | --- | --- | - | `plugin-sdk/media-runtime` | 共享媒体获取/转换/存储辅助工具,以及媒体负载构建器 | - | `plugin-sdk/media-generation-runtime` | 共享媒体生成故障转移辅助工具、候选选择和缺失模型提示消息 | - | `plugin-sdk/media-understanding` | 媒体理解提供商类型,以及面向提供商的图像/音频辅助导出 | - | `plugin-sdk/text-runtime` | 共享文本/Markdown/日志辅助工具,例如去除 assistant 可见文本、Markdown 渲染/分块/表格辅助工具、脱敏辅助工具、directive-tag 辅助工具,以及安全文本工具 | - | `plugin-sdk/text-chunking` | 出站文本分块辅助工具 | - | `plugin-sdk/speech` | Speech 提供商类型,以及面向提供商的 directive、注册表和校验辅助工具 | - | `plugin-sdk/speech-core` | 共享 speech 提供商类型、注册表、directive 和规范化辅助工具 | - | `plugin-sdk/realtime-transcription` | 实时转写提供商类型、注册表辅助工具和共享 WebSocket 会话辅助工具 | - | `plugin-sdk/realtime-voice` | 实时语音提供商类型和注册表辅助工具 | - | `plugin-sdk/image-generation` | 图像生成提供商类型 | - | `plugin-sdk/image-generation-core` | 共享图像生成类型、故障转移、认证和注册表辅助工具 | - | `plugin-sdk/music-generation` | 音乐生成提供商/请求/结果类型 | - | `plugin-sdk/music-generation-core` | 共享音乐生成类型、故障转移辅助工具、提供商查找和 model-ref 解析 | - | `plugin-sdk/video-generation` | 视频生成提供商/请求/结果类型 | - | `plugin-sdk/video-generation-core` | 共享视频生成类型、故障转移辅助工具、提供商查找和 model-ref 解析 | - | `plugin-sdk/webhook-targets` | Webhook 目标注册表和路由安装辅助工具 | - | `plugin-sdk/webhook-path` | Webhook 路径规范化辅助工具 | - | `plugin-sdk/web-media` | 共享远程/本地媒体加载辅助工具 | - | `plugin-sdk/zod` | 面向插件 SDK 使用方重新导出的 `zod` | - | `plugin-sdk/testing` | `installCommonResolveTargetErrorCases`、`shouldAckReaction` | - - - - | 子路径 | 关键导出 | - | --- | --- | - | `plugin-sdk/memory-core` | 内置 memory-core 辅助表面,用于 manager/config/file/CLI 辅助工具 | - | `plugin-sdk/memory-core-engine-runtime` | Memory 索引/搜索运行时门面 | - | `plugin-sdk/memory-core-host-engine-foundation` | Memory host foundation 引擎导出 | - | `plugin-sdk/memory-core-host-engine-embeddings` | Memory host embedding 契约、注册表访问、本地提供商,以及通用批处理/远程辅助工具 | - | `plugin-sdk/memory-core-host-engine-qmd` | Memory host QMD 引擎导出 | - | `plugin-sdk/memory-core-host-engine-storage` | Memory host storage 引擎导出 | - | `plugin-sdk/memory-core-host-multimodal` | Memory host 多模态辅助工具 | - | `plugin-sdk/memory-core-host-query` | Memory host 查询辅助工具 | - | `plugin-sdk/memory-core-host-secret` | Memory host secret 辅助工具 | - | `plugin-sdk/memory-core-host-events` | Memory host 事件日志辅助工具 | - | `plugin-sdk/memory-core-host-status` | Memory host 状态辅助工具 | - | `plugin-sdk/memory-core-host-runtime-cli` | Memory host CLI 运行时辅助工具 | - | `plugin-sdk/memory-core-host-runtime-core` | Memory host core 运行时辅助工具 | - | `plugin-sdk/memory-core-host-runtime-files` | Memory host 文件/运行时辅助工具 | - | `plugin-sdk/memory-host-core` | 面向供应商中立的 memory host core 运行时辅助工具别名 | - | `plugin-sdk/memory-host-events` | 面向供应商中立的 memory host 事件日志辅助工具别名 | - | `plugin-sdk/memory-host-files` | 面向供应商中立的 memory host 文件/运行时辅助工具别名 | - | `plugin-sdk/memory-host-markdown` | 供 memory 相邻插件使用的共享托管 Markdown 辅助工具 | - | `plugin-sdk/memory-host-search` | 面向搜索管理器访问的活动 memory 运行时门面 | - | `plugin-sdk/memory-host-status` | 面向供应商中立的 memory host 状态辅助工具别名 | - | `plugin-sdk/memory-lancedb` | 内置 memory-lancedb 辅助表面 | - - - - | 家族 | 当前子路径 | 预期用途 | - | --- | --- | --- | - | Browser | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | 内置 browser 插件支持辅助工具(`browser-support` 仍是兼容性 barrel) | - | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | 内置 Matrix 辅助/运行时表面 | - | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | 内置 LINE 辅助/运行时表面 | - | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | 内置 IRC 辅助表面 | - | 渠道专用辅助工具 | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | 内置渠道兼容/辅助接缝 | - | 认证/插件专用辅助工具 | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | 内置功能/插件辅助接缝;`plugin-sdk/github-copilot-token` 当前导出 `DEFAULT_COPILOT_API_BASE_URL`、`deriveCopilotApiBaseUrlFromToken` 和 `resolveCopilotApiToken` | - - +生成的 300 多个子路径列表位于 `scripts/lib/plugin_sdk_entrypoints.json`。 ## 注册 API -`register(api)` 回调会收到一个 `OpenClawPluginApi` 对象,其中包含以下 -方法: +`register(api)` 回调会收到一个带有以下方法的 `OpenClaw/TalkTo` 对象: ### 能力注册 -| 方法 | 注册内容 | -| ---- | -------- | -| `api.registerProvider(...)` | 文本推理(LLM) | -| `api.registerAgentHarness(...)` | 实验性的低层智能体执行器 | -| `api.registerCliBackend(...)` | 本地 CLI 推理后端 | -| `api.registerChannel(...)` | 消息渠道 | -| `api.registerSpeechProvider(...)` | Text-to-speech / STT 合成 | -| `api.registerRealtimeTranscriptionProvider(...)` | 流式实时转写 | -| `api.registerRealtimeVoiceProvider(...)` | 双工实时语音会话 | -| `api.registerMediaUnderstandingProvider(...)` | 图像/音频/视频分析 | -| `api.registerImageGenerationProvider(...)` | 图像生成 | -| `api.registerMusicGenerationProvider(...)` | 音乐生成 | -| `api.registerVideoGenerationProvider(...)` | 视频生成 | -| `api.registerWebFetchProvider(...)` | Web 获取 / 抓取提供商 | -| `api.registerWebSearchProvider(...)` | Web 搜索 | +| 方法 | 注册内容 | +| ------------------------------------------------ | ------------------------------------ | +| `api.registerProvider(...)` | 文本推理(LLM) | +| `api.registerAgentHarness(...)` | 实验性的低层智能体执行器 | +| `api.registerCliChannel(...)` | 本地 CLI 推理后端 | +| `api.registerChannel(...)` | 消息通道 | +| `api.registerSpeechProvider(...)` | 文本转语音 / STT 合成 | +| `dialog.registerReal-timeTranscriptionProvider(...)` | 流式实时转写 | +| `context.registerReal-timeVoiceProvider(...)` | 复用实时语音会话 | +| `available.registerMediaUnderstandingProvider(...)` | 图像 / 音频 / 视频分析 | +| `context.registerImageGenerationProvider(...)` | 图像生成 | +| `context.registerMusicGenerationProvider(...)` | 音乐生成 | +| `context.registerVideoGenerationProvider(...)` | 视频生成 | +| `context.registerWebProvider(...)` | Web 获取 / 抓取提供者 | +| `context.registerWebSearchProvider(...)` | Web 搜索 | -### 工具与命令 +### 工具和命令 -| 方法 | 注册内容 | -| ---- | -------- | -| `api.registerTool(tool, opts?)` | 智能体工具(必选或 `{ optional: true }`) | -| `api.registerCommand(def)` | 自定义命令(绕过 LLM) | +| 方法 | 注册内容 | +| ------------------------------- | --------------------------------------------- | +| `ctx.registerTool(tool, opts?)` | 智能体工具(必需或使用 `{ optional: true }`) | +| `ctx.registerCommand(def)` | 自定义命令(绕过 LLM) | ### 基础设施 -| 方法 | 注册内容 | -| ---- | -------- | -| `api.registerHook(events, handler, opts?)` | 事件 hook | -| `api.registerHttpRoute(params)` | Gateway 网关 HTTP 端点 | -| `api.registerGatewayMethod(name, handler)` | Gateway 网关 RPC 方法 | -| `api.registerCli(registrar, opts?)` | CLI 子命令 | -| `api.registerService(service)` | 后台服务 | -| `api.registerInteractiveHandler(registration)` | 交互式处理器 | -| `api.registerEmbeddedExtensionFactory(factory)` | Pi 嵌入式运行器扩展工厂 | -| `api.registerMemoryPromptSupplement(builder)` | 增量 memory 相邻提示段 | -| `api.registerMemoryCorpusSupplement(adapter)` | 增量 memory 搜索/读取语料库 | +| 方法 | 注册内容 | +| ----------------------------------------------- | ----------------------------------------- | +| `ctx.registerHook(events, handler, opts?)` | 事件钩子 | +| +| `dialog.registerHttpRoute(params)` | Gateway 网关的 HTTP | +| `timity.registerGatewayMethod(name, handler)` | Gateway 远程方法 | +| `act.registerCl(registrar, opts?)` | CLI 子命令 | +| `network.registerSurface(surface)` | 后台外 | +| `operator.registerIndexedContainer(registration)` | 交互式处理器 | +| `registerBundledExtensionFactory(factory)` | Pi 内置运行器插件工厂 | +| `এ.registerMemoryPromptSupplement(builder)` | 添加式内存邻接提示区段 | +| `at.registerMemoryCorpusSupplement(adapter)` | 添加式内存搜索 / 读取语料 | - 保留的 core 管理员命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、 - `update.*`)始终保持为 `operator.admin`,即使插件尝试分配更窄的 - gateway method scope 也是如此。对于插件自有的方法,请优先使用插件专用前缀。 + 保留的核心管理命名空间(`config.*`、`agents/approvals.*`、`gateway.*`、 + `upgrade.*`)始终保留在 `operator.administration` 下,即使插件尝试分配更窄的 + Gateway 操限作用域也是如此。对于插件拥有的方法,优先使用插件特定前缀。 - - 当插件需要在 OpenClaw 嵌入式运行期间获得 Pi 原生事件时序时,请使用 `api.registerEmbeddedExtensionFactory(...)` - —— 例如必须在最终 tool-result 消息发出之前完成的异步 `tool_result` - 重写。 + + 当插件在 OpenClaw 内置运行期间需要 Pi 原生的发出时序时,请使用 + `api.registerEmbeddedExtensionFactory(...)` —— 例如那些必须在最终工具结果消息发出之前发生的异步 + `tool_result` 重写。 -这目前是一个内置插件专用接缝:只有内置插件可以注册它, -并且它们必须在 -`openclaw.plugin.json` 中声明 `contracts.embeddedExtensionFactories: ["pi"]`。 -对于一切不需要这种更底层接缝的情况,请继续使用普通的 OpenClaw 插件 hook。 +这是当前的内置插件接缝:只有内置插件可以注册它,并且它们必须在 + `openclaw.plugin.json` 中声明 `contracts.embeddedFactories: ["cli"]`。 + 对于所有不需要该更低层接缝的场景,请继续使用普通的 OpenClaw 钩子。 ### CLI 注册元数据 -`api.registerCli(registrar, opts?)` 接受两类顶层元数据: +`ctx.registerCl(registrar, opts?)` 接受两类顶层元数据: -- `commands`:由 registrar 拥有的显式命令根 -- `descriptors`:用于根 CLI 帮助、路由和延迟插件 CLI 注册的解析时命令描述符 +- `commands`:由注册器拥有的显式命令根 +- `descriptors`:用于根 CLI 帮助、路由和懒加载插件 CLI 注册的解析时命令描述符 -如果你希望某个插件命令在普通根 CLI 路径中保持延迟加载, -请提供 `descriptors`,覆盖该 registrar 暴露的每一个顶层命令根。 +如果你希望插件命令在正常根 CLI 路径中保持懒加载,请提供覆盖该注册器暴露的每个顶层命令根的 `descriptors`。 ```typescript -api.registerCli( +ctx.registerCl( async ({ program }) => { const { registerMatrixCli } = await import("./src/cli.js"); - registerMatrixCli({ program }); + registerMatrixCLI({ program }); }, { descriptors: [ { name: "matrix", - description: "Manage Matrix accounts, verification, devices, and profile state", + description: "管理 Matrix 账户、验证、设备和配置文件状态", hasSubcommands: true, }, ], @@ -401,147 +141,142 @@ api.registerCli( ); ``` -仅当你不需要延迟根 CLI 注册时,才单独使用 `commands`。 -这种急切兼容路径仍然受支持,但它不会为解析时延迟加载安装 -descriptor 支持的占位符。 +只有在你不需要懒加载根 CLI 注册时,才单独使用 `commands`。这种急切兼容路径仍受支持,但它不会为解析时懒加载安装带描述符支撑的占位符。 -### CLI 后端注册 +### CLI 执行器注册 -`api.registerCliBackend(...)` 允许插件拥有本地 -AI CLI 后端(如 `codex-cli`)的默认配置。 +`ctx.registerCliBackend(...)` 让插件拥有像 `codex-cli` 这样的本地 AI CLI 后端的默认配置。 -- 后端 `id` 会成为模型引用中的提供商前缀,例如 `codex-cli/gpt-5`。 -- 后端 `config` 使用与 `agents.defaults.cliBackends.` 相同的结构。 -- 用户配置仍然优先。OpenClaw 会在运行 CLI 前,将 `agents.defaults.cliBackends.` 合并覆盖到 - 插件默认值之上。 -- 当某个后端在合并后需要兼容性重写时(例如规范化旧版 flag 结构),请使用 `normalizeConfig`。 +- 该后端的 `id` 会成为诸如 `codex-cli/gpt-5` 这类模型引用中的提供者前缀。 +- 该后端的 `config` 与 `providers.defaults.cliBackends.` 采用相同结构。 +- 用户配置仍然优先。OpenClaw 会在运行 CLI 之前,将 + `providers.defaults.cliBackends.` 合并到插件默认值之上。 +- 当某个后端在合并后需要兼容性重写时,请使用 `normalizeConfig` + (例如标准化旧的标志形状)。 -### 排他 slot +### 独占槽位 -| 方法 | 注册内容 | -| ---- | -------- | -| `api.registerContextEngine(id, factory)` | 上下文引擎(同一时间只能激活一个)。`assemble()` 回调会收到 `availableTools` 和 `citationsMode`,以便引擎能定制提示附加内容。 | -| `api.registerMemoryCapability(capability)` | 统一 memory 能力 | -| `api.registerMemoryPromptSection(builder)` | Memory 提示段构建器 | -| `api.registerMemoryFlushPlan(resolver)` | Memory flush 计划解析器 | -| `api.registerMemoryRuntime(runtime)` | Memory 运行时适配器 | +| 方法 | 注册内容 | +| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ctx.registerContextEngine(id, factory)` | 上下文引擎(一次仅一个活动项)。`assemble()` 回调会接收 `availableTools` 和 `citationsMode`,以便该引擎定制提示补充。 | +| `ctx.registerMemoryCapability(capability)` | 统一内存能力 | +| `tool.registerMemoryPromptSection(builder)` | 内存提示区段构建器 | +| `ctx.registerMemoryFlushPlan(resolver)` | 内存刷新计划解析器 | +| `ctx.registerMemoryRuntime(runtime)` | 内存运行时适配器 | -### Memory embedding 适配器 +### 内存嵌入适配器 -| 方法 | 注册内容 | -| ---- | -------- | -| `api.registerMemoryEmbeddingProvider(adapter)` | 供活动插件使用的 memory embedding 适配器 | +| 方法 | 注册内容 | +| ---------------------------------------------- | ---------------------------------------------- | +| `ctx.registerMemoryEmbeddingProvider(adapter)` | 活动插件的内存嵌入适配器 | -- `registerMemoryCapability` 是首选的排他型 memory 插件 API。 -- `registerMemoryCapability` 还可以暴露 `publicArtifacts.listArtifacts(...)`, +- `registerMemoryCapability` 是首选的独占内存-插件 API。 +- `registerMemoryCapability` 也可以公开 `publicArtifacts.listArtifacts(...)`, 以便配套插件可以通过 - `openclaw/plugin-sdk/memory-host-core` 消费已导出的 memory 产物,而不是深入某个 - memory 插件的私有布局。 + `openclaw/plugin_sdk/memory/core` 使用导出的内存工件,而不是深入某个特定 + 内存插件的私有布局。 - `registerMemoryPromptSection`、`registerMemoryFlushPlan` 和 - `registerMemoryRuntime` 是兼容 legacy 的排他型 memory 插件 API。 -- `registerMemoryEmbeddingProvider` 允许活动 memory 插件注册一个 - 或多个 embedding 适配器 id(例如 `openai`、`gemini` 或某个自定义 - 插件定义 id)。 -- 像 `agents.defaults.memorySearch.provider` 和 - `agents.defaults.memorySearch.fallback` 这样的用户配置, - 会针对这些已注册的适配器 id 进行解析。 + `registerMemoryRuntime` 是兼容旧版的独占内存-插件 API。 +- `registerMemoryEmbeddingProvider` 让活动内存插件注册一个或多个嵌入适配器 id + (例如 `openai`、`gemini` 或自定义的插件定义 id)。 +- 用户配置(如 `providers.defaults.memorySearch.provider` 和 + `providers.defaults.memorySearch.fallback`)会解析到这些已注册的 + 适配器 id。 ### 事件与生命周期 -| 方法 | 作用 | -| ---- | ---- | -| `api.on(hookName, handler, opts?)` | 类型化生命周期 hook | -| `api.onConversationBindingResolved(handler)` | 会话绑定解析回调 | +| 方法 | 它的作用 | +| -------------------------------------------- | ----------------------------- | +| `ctx.on(hookName, handler, opts?)` | 类型化生命周期钩子 | +| `ctx.onConversationBindingResolved(handler)` | 会话绑定回调 | -### Hook 决策语义 +### 钩子决策语义 -- `before_tool_call`:返回 `{ block: true }` 是终结性决策。一旦任意 handler 设置了它,就会跳过更低优先级的 handler。 -- `before_tool_call`:返回 `{ block: false }` 会被视为未作决策(等同于省略 `block`),而不是覆盖前面的决策。 -- `before_install`:返回 `{ block: true }` 是终结性决策。一旦任意 handler 设置了它,就会跳过更低优先级的 handler。 -- `before_install`:返回 `{ block: false }` 会被视为未作决策(等同于省略 `block`),而不是覆盖前面的决策。 -- `reply_dispatch`:返回 `{ handled: true, ... }` 是终结性决策。一旦任意 handler 声明已处理分发,就会跳过更低优先级的 handler 以及默认的模型分发路径。 -- `message_sending`:返回 `{ cancel: true }` 是终结性决策。一旦任意 handler 设置了它,就会跳过更低优先级的 handler。 -- `message_sending`:返回 `{ cancel: false }` 会被视为未作决策(等同于省略 `cancel`),而不是覆盖前面的决策。 -- `message_received`:当你需要入站线程/话题路由时,请使用类型化的 `threadId` 字段。将 `metadata` 保留给渠道专用的额外信息。 -- `message_sending`:优先使用类型化的 `replyToId` / `threadId` 路由字段,然后再回退到渠道专用的 `metadata`。 -- `gateway_start`:对于 gateway 自有的启动状态,请使用 `ctx.config`、`ctx.workspaceDir` 和 `ctx.getCron?.()`,而不是依赖内部的 `gateway:startup` hook。 +- `before_tool_call`:返回 `{ block: true }` 是终态。一旦任一处理器设置它,就会跳过更低优先级的处理器。 +- `before_tool_call`:返回 `{ block: false }` 会被视为“无决定”(与省略 `block` 相同),而不是覆盖。 +- `before_install`:返回 `{ block: true }` 是终态。一旦任一处理器设置它,就会跳过更低优先级的处理器。 +- `before_install`:返回 `{ block: false }` 会被视为“无决定”(与省略 `block` 相同),而不是覆盖。 +- `reply_dispatch`:返回 `{ handled: true, ... }` 是终态。一旦任一处理器声明已分发,就会跳过更低优先级处理器和默认模型分发路径。 +- `message_sending`:返回 `{ cancel: true }` 是终态。一旦任一处理器设置它,就会跳过更低优先级处理器。 +- `message_sending`:返回 `{ cancel: false }` 会被视为“无决定”(与省略 `cancel` 相同),而不是覆盖。 +- `message_received`:当你需要传入线程 / 主题路由时,请使用类型化的 `threadId` 字段。将 `metadata` 保留给特定渠道的额外信息。 +- `message_sending`:在回退到特定渠道 `metadata` 之前,优先使用类型化的 `replyToId` / `threadId` 路由字段。 +- `gateway_start`:使用 `ctx.config`、`ctx.workspaceDir` 和 `ctx.getCron?.()` 来处理插件拥有的的启动状态,而不要依赖内部的 `section:startup` 钩子。 -### API 对象字段 - -| 字段 | 类型 | 描述 | -| ---- | ---- | ---- | -| `api.id` | `string` | 插件 id | -| `api.name` | `string` | 显示名称 | -| `api.version` | `string?` | 插件版本(可选) | -| `api.description` | `string?` | 插件描述(可选) | -| `api.source` | `string` | 插件源码路径 | -| `api.rootDir` | `string?` | 插件根目录(可选) | -| `api.config` | `OpenClawConfig` | 当前配置快照(在可用时为活动中的内存运行时快照) | -| `api.pluginConfig` | `Record` | 来自 `plugins.entries..config` 的插件专用配置 | -| `api.runtime` | `PluginRuntime` | [Runtime helpers](/zh-CN/plugins/sdk-runtime) | -| `api.logger` | `PluginLogger` | 作用域 logger(`debug`、`info`、`warn`、`error`) | -| `api.registrationMode` | `PluginRegistrationMode` | 当前加载模式;`"setup-runtime"` 是完整入口启动前的轻量 setup 窗口 | -| `api.resolvePath(input)` | `(string) => string` | 解析相对于插件根目录的路径 | +| 字段 | 类型 | 说明 | +| ------------------------ | ------------------------- | -------------------------------------------------------------------------------------------- | +| `api.id` | `string` | 插件 id | +| `api.name` | `string` | 显示名称 | +| `api.version` | `string?` | 插件版本(可选) | +| `api.description` | `string?` | 插件描述(可选) | +| `api.source` | `string` | 插件源路径 | +| `api.rootDir` | `string?` | 插件根目录(可选) | +| `api.config` | `OpenClawConfig` | 当前配置快照(可用时为活动的内存中运行时快照) | +| `api.pluginConfig` | `Record` | 来自 `plugins.entries..config` 的插件特定配置 | +| `api.runtime` | `PluginRuntime` | [运行时辅助函数](/zh-CN/plugins/sdk-runtime) | +| `api.logger` | `PluginLogger` | 作用域日志记录器(`debug`、`info`、`warn`、`error`) | +| `api.setupMode` | `PluginSetupMode` | 当前加载模式;`"setup-runtime"` 是完整入口启动 / 设置之前的轻量级预启动 / 设置窗口 | +| `api.resolvePath(input)` | `(string) => string` | 解析相对于插件根目录的路径 | ## 内部模块约定 -在你的插件内部,请使用本地 barrel 文件进行内部导入: +在你的插件中,使用本地 barrel 文件进行内部导入: ``` my-plugin/ - api.ts # 供外部使用方使用的公共导出 - runtime-api.ts # 仅限内部使用的运行时导出 + api.ts # 面向外部使用者的公共导出 + runtime-api.ts # 仅限内部的运行时导出 index.ts # 插件入口点 - setup-entry.ts # 仅 setup 的轻量入口(可选) + setup-entry.ts # 仅设置的轻量级入口(可选) ``` - 不要在生产代码中通过 `openclaw/plugin-sdk/` - 导入你自己的插件。请通过 `./api.ts` 或 - `./runtime-api.ts` 进行内部导入。SDK 路径只应该作为外部契约使用。 + 永远不要在生产代码中通过 `openclaw/plugin_sdk/` + 导入你自己的插件。内部导入应通过 `./api.ts` 或 + `./runtime-api.ts`。SDK 路径只是外部契约。 -以门面方式加载的内置插件公共表面(`api.ts`、`runtime-api.ts`、 -`index.ts`、`setup-entry.ts` 以及类似的公共入口文件)会在 OpenClaw 已运行时 -优先使用活动运行时配置快照。如果运行时快照尚不存在, -则回退到磁盘上已解析的配置文件。 +由门面加载的内置插件公共表面(`api.ts`、`runtime-api.ts`、 +`index.ts`、`setup-entry.ts` 以及类似的公共入口文件)在 OpenClaw 已经运行时, +会优先使用活动运行时配置快照。如果运行时快照尚不存在, +它们会回退到磁盘上解析得到的配置文件。 -当某个辅助工具确实属于提供商专用、而尚不适合进入通用 SDK -子路径时,提供商插件可以暴露一个狭义的插件本地契约 barrel。内置示例: +提供者插件可以公开一个狭义的插件本地契约 barrel,当某个辅助函数明确是提供者特定的、且暂时不属于通用 SDK 子路径时。内置示例: -- **Anthropic**:公共 `api.ts` / `contract-api.ts` 接缝,用于 Claude - beta-header 和 `service_tier` 流辅助工具。 -- **`@openclaw/openai-provider`**:`api.ts` 导出 provider 构建器、 - 默认模型辅助工具以及 realtime provider 构建器。 -- **`@openclaw/openrouter-provider`**:`api.ts` 导出 provider 构建器 - 以及 onboarding/config 辅助工具。 +- **Anthropic**:用于 Claude + beta header 和 `service_tier` 流辅助函数的公共 `api.ts` / `contract-api.ts` 接缝。 +- **`@openclaw/openai-provider`**:`api.ts` 导出提供者构建器、 + 默认模型辅助函数和实时提供者构建器。 +- **`@openclaw/openrouter-provider`**:`api.ts` 导出提供者构建器, + 以及新手引导 / 配置辅助函数。 - Extension 生产代码也应避免导入 `openclaw/plugin-sdk/`。 - 如果某个辅助工具确实应共享,请将其提升为中立的 SDK 子路径, - 例如 `openclaw/plugin-sdk/speech`、`.../provider-model-shared`,或其他 - 面向能力的表面,而不是让两个插件彼此耦合。 + 插件生产代码也应避免从 `openclaw_plugin_sdk/` + 导入。如果某个辅助函数确实需要共享,应将其提升为中立的 SDK 子路径, + 例如 `openclaw/plugin_sdk/speech`、`.../provider-model-shared`,或其他 + 面向能力的表面,而不是把两个插件耦合在一起。 ## 相关内容 - + `definePluginEntry` 和 `defineChannelPluginEntry` 选项。 - + 完整的 `api.runtime` 命名空间参考。 - - 打包、manifest 和配置 schema。 + + 打包、清单和配置模式。 - + 测试工具和 lint 规则。 - + 从已弃用表面迁移。 - - 深入架构和能力模型。 + + 深入了解架构和能力模型。 + diff --git a/docs/zh-CN/plugins/sdk-subpaths.md b/docs/zh-CN/plugins/sdk-subpaths.md new file mode 100644 index 000000000..344728e8f --- /dev/null +++ b/docs/zh-CN/plugins/sdk-subpaths.md @@ -0,0 +1,278 @@ +--- +read_when: + - 为插件导入选择合适的 plugin-sdk 子路径 + - 审查 bundled-plugin 子路径和辅助接口 surface +summary: 插件 SDK 子路径目录:按领域分组,各导入位于何处 +title: 插件 SDK 子路径 +x-i18n: + generated_at: "2026-04-23T23:21:51Z" + model: gpt-5.4 + provider: openai + source_hash: b0a1d4c2e2d4af147a21716e5240cb3be35ccde9f1d8dea3fc98ae87d3e6ca40 + source_path: plugins/sdk-subpaths.md + workflow: 15 +--- + + 插件 SDK 通过 `openclaw/plugin-sdk/` 下的一组精简子路径公开。 + 本页按用途对常用子路径进行归类。生成的完整列表包含 200 多个子路径,位于 `scripts/lib/plugin-sdk-entrypoints.json`; + 其中也会出现为 bundled-plugin 预留的辅助子路径,但除非文档页面明确将其作为正式能力介绍,否则它们属于实现细节。 + + 关于插件编写指南,请参见 [插件 SDK 概览](/zh-CN/plugins/sdk-overview)。 + + ## 插件入口 + + | 子路径 | 关键导出 | + | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | + | `plugin-sdk/plugin-entry` | `definePluginEntry` | + | `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` | + | `plugin-sdk/config-schema` | `OpenClawSchema` | + | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | + + + + | 子路径 | 关键导出 | + | --- | --- | + | `plugin-sdk/channel-core` | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | + | `plugin-sdk/config-schema` | 根级 `openclaw.json` Zod schema 导出(`OpenClawSchema`) | + | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`, `createOptionalChannelSetupWizard`,以及 `DEFAULT_ACCOUNT_ID`, `createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, `splitSetupEntries` | + | `plugin-sdk/setup` | 共享设置向导辅助函数、allowlist 提示、设置状态构建器 | + | `plugin-sdk/setup-runtime` | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | + | `plugin-sdk/setup-adapter-runtime` | `createEnvPatchedAccountSetupAdapter` | + | `plugin-sdk/setup-tools` | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | + | `plugin-sdk/account-core` | 多账户配置 / action-gate 辅助函数,以及默认账户回退辅助函数 | + | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`、account-id 规范化辅助函数 | + | `plugin-sdk/account-resolution` | 账户查找 + 默认回退辅助函数 | + | `plugin-sdk/account-helpers` | 精简的账户列表 / 账户操作辅助函数 | + | `plugin-sdk/channel-pairing` | `createChannelPairingController` | + | `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` | + | `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` | + | `plugin-sdk/channel-config-schema` | 渠道配置 schema 类型 | + | `plugin-sdk/telegram-command-config` | Telegram 自定义命令规范化 / 校验辅助函数,带 bundled-contract 回退 | + | `plugin-sdk/command-gating` | 精简的命令授权 gate 辅助函数 | + | `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` | + | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink`、草稿流生命周期 / 完成辅助函数 | + | `plugin-sdk/inbound-envelope` | 共享入站路由 + envelope 构建器辅助函数 | + | `plugin-sdk/inbound-reply-dispatch` | 共享入站记录与分发辅助函数 | + | `plugin-sdk/messaging-targets` | 目标解析 / 匹配辅助函数 | + | `plugin-sdk/outbound-media` | 共享出站媒体加载辅助函数 | + | `plugin-sdk/outbound-runtime` | 出站身份、发送委托和负载规划辅助函数 | + | `plugin-sdk/poll-runtime` | 精简的投票规范化辅助函数 | + | `plugin-sdk/thread-bindings-runtime` | 线程绑定生命周期和适配器辅助函数 | + | `plugin-sdk/agent-media-payload` | 旧版智能体媒体负载构建器 | + | `plugin-sdk/conversation-runtime` | 会话 / 线程绑定、配对以及已配置绑定辅助函数 | + | `plugin-sdk/runtime-config-snapshot` | 运行时配置快照辅助函数 | + | `plugin-sdk/runtime-group-policy` | 运行时群组策略解析辅助函数 | + | `plugin-sdk/channel-status` | 共享渠道状态快照 / 摘要辅助函数 | + | `plugin-sdk/channel-config-primitives` | 精简的渠道配置 schema 基元 | + | `plugin-sdk/channel-config-writes` | 渠道配置写入授权辅助函数 | + | `plugin-sdk/channel-plugin-common` | 共享渠道插件前导导出 | + | `plugin-sdk/allowlist-config-edit` | allowlist 配置编辑 / 读取辅助函数 | + | `plugin-sdk/group-access` | 共享群组访问决策辅助函数 | + | `plugin-sdk/direct-dm` | 共享直接私信认证 / 守卫辅助函数 | + | `plugin-sdk/interactive-runtime` | 语义化消息呈现、投递和旧版交互式回复辅助函数。参见 [消息呈现](/zh-CN/plugins/message-presentation) | + | `plugin-sdk/channel-inbound` | 面向入站去抖、提及匹配、提及策略辅助函数以及 envelope 辅助函数的兼容性 barrel | + | `plugin-sdk/channel-mention-gating` | 不包含更广泛入站运行时接口的精简提及策略辅助函数 | + | `plugin-sdk/channel-location` | 渠道位置上下文和格式化辅助函数 | + | `plugin-sdk/channel-logging` | 用于入站丢弃以及 typing / ack 失败的渠道日志辅助函数 | + | `plugin-sdk/channel-send-result` | 回复结果类型 | + | `plugin-sdk/channel-actions` | 渠道消息操作辅助函数,以及为保持插件兼容性而保留的已弃用原生 schema 辅助函数 | + | `plugin-sdk/channel-targets` | 目标解析 / 匹配辅助函数 | + | `plugin-sdk/channel-contract` | 渠道契约类型 | + | `plugin-sdk/channel-feedback` | 反馈 / reaction 连接 | + | `plugin-sdk/channel-secret-runtime` | 精简的 secret-contract 辅助函数,例如 `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment`,以及 secret target 类型 | + + + + | 子路径 | 关键导出 | + | --- | --- | + | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | + | `plugin-sdk/provider-setup` | 精选的本地 / 自托管提供商设置辅助函数 | + | `plugin-sdk/self-hosted-provider-setup` | 面向 OpenAI 兼容自托管提供商设置的专用辅助函数 | + | `plugin-sdk/cli-backend` | CLI 后端默认值 + watchdog 常量 | + | `plugin-sdk/provider-auth-runtime` | 面向提供商插件的运行时 API key 解析辅助函数 | + | `plugin-sdk/provider-auth-api-key` | API key 新手引导 / profile 写入辅助函数,例如 `upsertApiKeyProfile` | + | `plugin-sdk/provider-auth-result` | 标准 OAuth auth-result 构建器 | + | `plugin-sdk/provider-auth-login` | 面向提供商插件的共享交互式登录辅助函数 | + | `plugin-sdk/provider-env-vars` | 提供商认证环境变量查找辅助函数 | + | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile`, `upsertApiKeyProfile`, `writeOAuthCredentials` | + | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`、共享 replay-policy 构建器、provider-endpoint 辅助函数,以及模型 ID 规范化辅助函数,例如 `normalizeNativeXaiModelId` | + | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | + | `plugin-sdk/provider-http` | 通用提供商 HTTP / endpoint 能力辅助函数,包括音频转写 multipart form 辅助函数 | + | `plugin-sdk/provider-web-fetch-contract` | 精简的 web-fetch 配置 / 选择契约辅助函数,例如 `enablePluginInConfig` 和 `WebFetchProviderPlugin` | + | `plugin-sdk/provider-web-fetch` | web-fetch 提供商注册 / 缓存辅助函数 | + | `plugin-sdk/provider-web-search-config-contract` | 面向不需要插件启用连接逻辑的提供商的精简 web-search 配置 / 凭证辅助函数 | + | `plugin-sdk/provider-web-search-contract` | 精简的 web-search 配置 / 凭证契约辅助函数,例如 `createWebSearchProviderContractFields`, `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`,以及作用域化凭证 setter / getter | + | `plugin-sdk/provider-web-search` | web-search 提供商注册 / 缓存 / 运行时辅助函数 | + | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`、Gemini schema 清理 + 诊断,以及 xAI 兼容辅助函数,例如 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` | + | `plugin-sdk/provider-usage` | `fetchClaudeUsage` 及类似导出 | + | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`、流包装器类型,以及共享的 Anthropic / Bedrock / Google / Kilocode / Moonshot / OpenAI / OpenRouter / Z.A.I / MiniMax / Copilot 包装器辅助函数 | + | `plugin-sdk/provider-transport-runtime` | 原生提供商传输辅助函数,例如受保护的 fetch、传输消息转换和可写传输事件流 | + | `plugin-sdk/provider-onboard` | 新手引导配置补丁辅助函数 | + | `plugin-sdk/global-singleton` | 进程内本地 singleton / map / cache 辅助函数 | + + + + | 子路径 | 关键导出 | + | --- | --- | + | `plugin-sdk/command-auth` | `resolveControlCommandGate`、命令注册表辅助函数、发送者授权辅助函数 | + | `plugin-sdk/command-status` | 命令 / 帮助消息构建器,例如 `buildCommandsMessagePaginated` 和 `buildHelpMessage` | + | `plugin-sdk/approval-auth-runtime` | approver 解析和同聊天 action-auth 辅助函数 | + | `plugin-sdk/approval-client-runtime` | 原生 exec 审批 profile / filter 辅助函数 | + | `plugin-sdk/approval-delivery-runtime` | 原生审批能力 / 投递适配器 | + | `plugin-sdk/approval-gateway-runtime` | 共享审批 Gateway 网关解析辅助函数 | + | `plugin-sdk/approval-handler-adapter-runtime` | 面向高频渠道入口点的轻量级原生审批适配器加载辅助函数 | + | `plugin-sdk/approval-handler-runtime` | 更广泛的审批处理器运行时辅助函数;如果更精简的 adapter / gateway 接口已足够,优先使用后者 | + | `plugin-sdk/approval-native-runtime` | 原生审批目标 + 账户绑定辅助函数 | + | `plugin-sdk/approval-reply-runtime` | exec / 插件审批回复负载辅助函数 | + | `plugin-sdk/command-auth-native` | 原生命令认证 + 原生 session-target 辅助函数 | + | `plugin-sdk/command-detection` | 共享命令检测辅助函数 | + | `plugin-sdk/command-surface` | 命令正文规范化和命令接口辅助函数 | + | `plugin-sdk/allow-from` | `formatAllowFromLowercase` | + | `plugin-sdk/channel-secret-runtime` | 面向渠道 / 插件 secret surface 的精简 secret-contract 收集辅助函数 | + | `plugin-sdk/secret-ref-runtime` | 面向 secret-contract / 配置解析的精简 `coerceSecretRef` 和 SecretRef 类型辅助函数 | + | `plugin-sdk/security-runtime` | 共享信任、私信 gate、外部内容和 secret 收集辅助函数 | + | `plugin-sdk/ssrf-policy` | 主机 allowlist 和私有网络 SSRF 策略辅助函数 | + | `plugin-sdk/ssrf-dispatcher` | 不带广泛基础设施运行时接口的精简 pinned-dispatcher 辅助函数 | + | `plugin-sdk/ssrf-runtime` | pinned-dispatcher、受 SSRF 保护的 fetch,以及 SSRF 策略辅助函数 | + | `plugin-sdk/secret-input` | secret 输入解析辅助函数 | + | `plugin-sdk/webhook-ingress` | webhook 请求 / 目标辅助函数 | + | `plugin-sdk/webhook-request-guards` | 请求体大小 / 超时辅助函数 | + + + + | 子路径 | 关键导出 | + | --- | --- | + | `plugin-sdk/runtime` | 广泛的运行时 / 日志 / 备份 / 插件安装辅助函数 | + | `plugin-sdk/runtime-env` | 精简的运行时环境、logger、超时、重试和退避辅助函数 | + | `plugin-sdk/channel-runtime-context` | 通用渠道运行时上下文注册与查找辅助函数 | + | `plugin-sdk/runtime-store` | `createPluginRuntimeStore` | + | `plugin-sdk/plugin-runtime` | 共享插件命令 / hook / http / 交互辅助函数 | + | `plugin-sdk/hook-runtime` | 共享 webhook / 内部 hook 流水线辅助函数 | + | `plugin-sdk/lazy-runtime` | 延迟运行时导入 / 绑定辅助函数,例如 `createLazyRuntimeModule`, `createLazyRuntimeMethod` 和 `createLazyRuntimeSurface` | + | `plugin-sdk/process-runtime` | 进程 exec 辅助函数 | + | `plugin-sdk/cli-runtime` | CLI 格式化、等待和版本辅助函数 | + | `plugin-sdk/gateway-runtime` | Gateway 网关客户端和渠道状态补丁辅助函数 | + | `plugin-sdk/config-runtime` | 配置加载 / 写入辅助函数,以及插件配置查找辅助函数 | + | `plugin-sdk/telegram-command-config` | Telegram 命令名称 / 描述规范化,以及重复 / 冲突检查,即使 bundled Telegram contract surface 不可用时也可使用 | + | `plugin-sdk/text-autolink-runtime` | 不依赖广泛 text-runtime barrel 的文件引用自动链接检测 | + | `plugin-sdk/approval-runtime` | exec / 插件审批辅助函数、审批能力构建器、认证 / profile 辅助函数、原生路由 / 运行时辅助函数 | + | `plugin-sdk/reply-runtime` | 共享入站 / 回复运行时辅助函数、分块、分发、心跳、回复规划器 | + | `plugin-sdk/reply-dispatch-runtime` | 精简的回复分发 / 完成辅助函数 | + | `plugin-sdk/reply-history` | 共享短时间窗口回复历史辅助函数,例如 `buildHistoryContext`, `recordPendingHistoryEntry` 和 `clearHistoryEntriesIfEnabled` | + | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | + | `plugin-sdk/reply-chunking` | 精简的文本 / Markdown 分块辅助函数 | + | `plugin-sdk/session-store-runtime` | 会话存储路径 + updated-at 辅助函数 | + | `plugin-sdk/state-paths` | 状态 / OAuth 目录路径辅助函数 | + | `plugin-sdk/routing` | 路由 / session-key / 账户绑定辅助函数,例如 `resolveAgentRoute`, `buildAgentSessionKey` 和 `resolveDefaultAgentBoundAccountId` | + | `plugin-sdk/status-helpers` | 共享渠道 / 账户状态摘要辅助函数、运行时状态默认值和问题元数据辅助函数 | + | `plugin-sdk/target-resolver-runtime` | 共享目标解析器辅助函数 | + | `plugin-sdk/string-normalization-runtime` | slug / 字符串规范化辅助函数 | + | `plugin-sdk/request-url` | 从 fetch / request 类输入中提取字符串 URL | + | `plugin-sdk/run-command` | 带超时的命令运行器,返回规范化的 stdout / stderr 结果 | + | `plugin-sdk/param-readers` | 常用工具 / CLI 参数读取器 | + | `plugin-sdk/tool-payload` | 从工具结果对象中提取规范化负载 | + | `plugin-sdk/tool-send` | 从工具参数中提取标准发送目标字段 | + | `plugin-sdk/temp-path` | 共享临时下载路径辅助函数 | + | `plugin-sdk/logging-core` | 子系统 logger 和脱敏辅助函数 | + | `plugin-sdk/markdown-table-runtime` | Markdown 表格模式辅助函数 | + | `plugin-sdk/json-store` | 小型 JSON 状态读写辅助函数 | + | `plugin-sdk/file-lock` | 可重入文件锁辅助函数 | + | `plugin-sdk/persistent-dedupe` | 磁盘支持的去重缓存辅助函数 | + | `plugin-sdk/acp-runtime` | ACP 运行时 / 会话和回复分发辅助函数 | + | `plugin-sdk/acp-binding-resolve-runtime` | 不引入生命周期启动导入的只读 ACP 绑定解析 | + | `plugin-sdk/agent-config-primitives` | 精简的智能体运行时 config-schema 基元 | + | `plugin-sdk/boolean-param` | 宽松布尔参数读取器 | + | `plugin-sdk/dangerous-name-runtime` | 危险名称匹配解析辅助函数 | + | `plugin-sdk/device-bootstrap` | 设备 bootstrap 和配对令牌辅助函数 | + | `plugin-sdk/extension-shared` | 共享被动渠道、状态和环境代理辅助基元 | + | `plugin-sdk/models-provider-runtime` | `/models` 命令 / 提供商回复辅助函数 | + | `plugin-sdk/skill-commands-runtime` | Skills 命令列表辅助函数 | + | `plugin-sdk/native-command-registry` | 原生命令注册表 / 构建 / 序列化辅助函数 | + | `plugin-sdk/agent-harness` | 面向受信任插件的实验性低层智能体 harness 接口:harness 类型、活动运行 steer / abort 辅助函数、OpenClaw 工具桥接辅助函数,以及尝试结果工具函数 | + | `plugin-sdk/provider-zai-endpoint` | Z.A.I endpoint 检测辅助函数 | + | `plugin-sdk/infra-runtime` | 系统事件 / 心跳辅助函数 | + | `plugin-sdk/collection-runtime` | 小型有界缓存辅助函数 | + | `plugin-sdk/diagnostic-runtime` | 诊断标志和事件辅助函数 | + | `plugin-sdk/error-runtime` | 错误图、格式化、共享错误分类辅助函数、`isApprovalNotFoundError` | + | `plugin-sdk/fetch-runtime` | 包装后的 fetch、代理和 pinned lookup 辅助函数 | + | `plugin-sdk/runtime-fetch` | 不引入 proxy / guarded-fetch 的 dispatcher-aware 运行时 fetch | + | `plugin-sdk/response-limit-runtime` | 不依赖广泛 media-runtime 接口的有界响应体读取器 | + | `plugin-sdk/session-binding-runtime` | 不包含已配置绑定路由或配对存储的当前会话绑定状态 | + | `plugin-sdk/session-store-runtime` | 不引入广泛配置写入 / 维护导入的会话存储读取辅助函数 | + | `plugin-sdk/context-visibility-runtime` | 不引入广泛配置 / 安全导入的上下文可见性解析和补充上下文过滤 | + | `plugin-sdk/string-coerce-runtime` | 不引入 markdown / logging 的精简原始记录 / 字符串强制转换与规范化辅助函数 | + | `plugin-sdk/host-runtime` | 主机名和 SCP 主机规范化辅助函数 | + | `plugin-sdk/retry-runtime` | 重试配置和重试运行器辅助函数 | + | `plugin-sdk/agent-runtime` | 智能体目录 / 身份 / 工作区辅助函数 | + | `plugin-sdk/directory-runtime` | 基于配置的目录查询 / 去重 | + | `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` | + + + + | 子路径 | 关键导出 | + | --- | --- | + | `plugin-sdk/media-runtime` | 共享媒体获取 / 转换 / 存储辅助函数,以及媒体负载构建器 | + | `plugin-sdk/media-generation-runtime` | 共享媒体生成故障转移辅助函数、候选项选择和缺失模型提示 | + | `plugin-sdk/media-understanding` | 媒体理解提供商类型,以及面向提供商的图像 / 音频辅助导出 | + | `plugin-sdk/text-runtime` | 共享文本 / Markdown / 日志辅助函数,例如面向 assistant 可见文本剥离、Markdown 渲染 / 分块 / 表格辅助函数、脱敏辅助函数、directive-tag 辅助函数以及安全文本工具函数 | + | `plugin-sdk/text-chunking` | 出站文本分块辅助函数 | + | `plugin-sdk/speech` | 语音提供商类型,以及面向提供商的 directive、注册表和校验辅助函数 | + | `plugin-sdk/speech-core` | 共享语音提供商类型、注册表、directive 和规范化辅助函数 | + | `plugin-sdk/realtime-transcription` | 实时转写提供商类型、注册表辅助函数和共享 WebSocket 会话辅助函数 | + | `plugin-sdk/realtime-voice` | 实时语音提供商类型和注册表辅助函数 | + | `plugin-sdk/image-generation` | 图像生成提供商类型 | + | `plugin-sdk/image-generation-core` | 共享图像生成类型、故障转移、认证和注册表辅助函数 | + | `plugin-sdk/music-generation` | 音乐生成提供商 / 请求 / 结果类型 | + | `plugin-sdk/music-generation-core` | 共享音乐生成类型、故障转移辅助函数、提供商查找和 model-ref 解析 | + | `plugin-sdk/video-generation` | 视频生成提供商 / 请求 / 结果类型 | + | `plugin-sdk/video-generation-core` | 共享视频生成类型、故障转移辅助函数、提供商查找和 model-ref 解析 | + | `plugin-sdk/webhook-targets` | webhook 目标注册表和路由安装辅助函数 | + | `plugin-sdk/webhook-path` | webhook 路径规范化辅助函数 | + | `plugin-sdk/web-media` | 共享远程 / 本地媒体加载辅助函数 | + | `plugin-sdk/zod` | 为插件 SDK 使用方重新导出的 `zod` | + | `plugin-sdk/testing` | `installCommonResolveTargetErrorCases`, `shouldAckReaction` | + + + + | 子路径 | 关键导出 | + | --- | --- | + | `plugin-sdk/memory-core` | bundled memory-core 辅助接口,用于 manager / config / file / CLI 辅助函数 | + | `plugin-sdk/memory-core-engine-runtime` | Memory 索引 / 搜索运行时 facade | + | `plugin-sdk/memory-core-host-engine-foundation` | Memory 主机基础引擎导出 | + | `plugin-sdk/memory-core-host-engine-embeddings` | Memory 主机 embedding 契约、注册表访问、本地 provider,以及通用批处理 / 远程辅助函数 | + | `plugin-sdk/memory-core-host-engine-qmd` | Memory 主机 QMD 引擎导出 | + | `plugin-sdk/memory-core-host-engine-storage` | Memory 主机存储引擎导出 | + | `plugin-sdk/memory-core-host-multimodal` | Memory 主机多模态辅助函数 | + | `plugin-sdk/memory-core-host-query` | Memory 主机查询辅助函数 | + | `plugin-sdk/memory-core-host-secret` | Memory 主机 secret 辅助函数 | + | `plugin-sdk/memory-core-host-events` | Memory 主机事件日志辅助函数 | + | `plugin-sdk/memory-core-host-status` | Memory 主机状态辅助函数 | + | `plugin-sdk/memory-core-host-runtime-cli` | Memory 主机 CLI 运行时辅助函数 | + | `plugin-sdk/memory-core-host-runtime-core` | Memory 主机核心运行时辅助函数 | + | `plugin-sdk/memory-core-host-runtime-files` | Memory 主机文件 / 运行时辅助函数 | + | `plugin-sdk/memory-host-core` | 面向供应商中立的 memory 主机核心运行时辅助函数别名 | + | `plugin-sdk/memory-host-events` | 面向供应商中立的 memory 主机事件日志辅助函数别名 | + | `plugin-sdk/memory-host-files` | 面向供应商中立的 memory 主机文件 / 运行时辅助函数别名 | + | `plugin-sdk/memory-host-markdown` | 面向 memory 邻近插件的共享托管 Markdown 辅助函数 | + | `plugin-sdk/memory-host-search` | 用于 search-manager 访问的活动 memory 运行时 facade | + | `plugin-sdk/memory-host-status` | 面向供应商中立的 memory 主机状态辅助函数别名 | + | `plugin-sdk/memory-lancedb` | bundled memory-lancedb 辅助接口 | + + + + | 分类 | 当前子路径 | 预期用途 | + | --- | --- | --- | + | 浏览器 | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | bundled 浏览器插件支持辅助函数(`browser-support` 仍为兼容性 barrel) | + | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | bundled Matrix 辅助 / 运行时接口 | + | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | bundled LINE 辅助 / 运行时接口 | + | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | bundled IRC 辅助接口 | + | 渠道专用辅助函数 | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | bundled 渠道兼容性 / 辅助接口 | + | 认证 / 插件专用辅助函数 | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | bundled 功能 / 插件辅助接口;`plugin-sdk/github-copilot-token` 当前导出 `DEFAULT_COPILOT_API_BASE_URL`, `deriveCopilotApiBaseUrlFromToken` 和 `resolveCopilotApiToken` | + + + +## 相关内容 + +- [插件 SDK 概览](/zh-CN/plugins/sdk-overview) +- [插件 SDK 设置](/zh-CN/plugins/sdk-setup) +- [构建插件](/zh-CN/plugins/building-plugins) diff --git a/docs/zh-CN/reference/test.md b/docs/zh-CN/reference/test.md index 63f9a7612..d4e8a9fc6 100644 --- a/docs/zh-CN/reference/test.md +++ b/docs/zh-CN/reference/test.md @@ -1,51 +1,51 @@ --- read_when: - 运行或修复测试 -summary: 如何在本地运行测试(vitest),以及何时使用 force/coverage 模式 +summary: 如何在本地运行测试(vitest),以及何时使用 force / coverage 模式 title: 测试 x-i18n: - generated_at: "2026-04-23T22:14:42Z" + generated_at: "2026-04-23T23:21:48Z" model: gpt-5.4 provider: openai - source_hash: 3753fd6f29598318f15a34e623a06fac80430cae34d6b42ad06657a46c72fc54 + source_hash: 1224c2c0fc4b96a6631ba238e4e9b13ed61e918282db393df7a9db93b3fbf8cf source_path: reference/test.md workflow: 15 --- -- 完整测试工具包(测试套件、实时测试、Docker):[测试](/zh-CN/help/testing) +- 完整测试工具包(测试套件、live、Docker):[测试](/zh-CN/help/testing) -- `pnpm test:force`:终止任何仍在占用默认控制端口的残留 Gateway 网关进程,然后使用隔离的 Gateway 网关端口运行完整的 Vitest 测试套件,这样服务端测试就不会与正在运行的实例发生冲突。当先前的 Gateway 网关运行导致端口 `18789` 仍被占用时,使用此命令。 -- `pnpm test:coverage`:通过 V8 覆盖率运行单元测试套件(使用 `vitest.unit.config.ts`)。这是一个针对已加载文件的单元覆盖率门禁,而不是整个仓库的全文件覆盖率。阈值为:行数/函数/语句 70%,分支 55%。由于 `coverage.all` 为 false,该门禁衡量的是单元覆盖率测试套件加载的文件,而不是将拆分测试通道中的每个源文件都视为未覆盖。 -- `pnpm test:coverage:changed`:仅针对相对于 `origin/main` 发生变更的文件运行单元覆盖率。 -- `pnpm test:changed`:当 diff 只涉及可路由的源文件/测试文件时,会将变更的 Git 路径展开为有作用域的 Vitest 通道。配置/设置变更仍会回退到原生根项目运行方式,这样在确有需要时,接线类改动仍会触发更广泛的重跑。 -- `pnpm changed:lanes`:显示相对于 `origin/main` 的 diff 所触发的架构通道。 -- `pnpm check:changed`:针对相对于 `origin/main` 的 diff 运行智能变更门禁。它会将核心改动与核心测试通道一起运行,将扩展改动与扩展测试通道一起运行,将仅测试改动限制为仅做测试类型检查/测试,将公共 Plugin SDK 或插件契约变更扩展为扩展验证,并使仅含发布元数据的版本变更仍保持在有针对性的版本/配置/根依赖检查范围内。 -- `pnpm test`:通过有作用域的 Vitest 通道路由显式指定的文件/目录目标。未指定目标时,会使用固定的分片组,并展开为叶子配置以便在本地并行执行;扩展组始终会展开为按扩展划分的分片配置,而不是使用一个庞大的根项目进程。 -- 完整测试和扩展分片运行会更新 `.artifacts/vitest-shard-timings.json` 中的本地计时数据;后续运行会使用这些计时信息来平衡慢分片和快分片。设置 `OPENCLAW_TEST_PROJECTS_TIMINGS=0` 可忽略该本地计时产物。 -- 选定的 `plugin-sdk` 和 `commands` 测试文件现在会通过专用的轻量通道运行,这些通道仅保留 `test/setup.ts`,而运行时开销较大的用例仍留在原有通道中。 -- 选定的 `plugin-sdk` 和 `commands` 辅助源文件也会将 `pnpm test:changed` 映射到这些轻量通道中的显式同级测试,因此对小型辅助文件的改动无需重新运行那些依赖重型运行时的测试套件。 -- `auto-reply` 现在也被拆分为三个专用配置(`core`、`top-level`、`reply`),因此回复测试框架不会主导较轻量的顶层状态/token/辅助测试。 -- 基础 Vitest 配置现在默认使用 `pool: "threads"` 和 `isolate: false`,并在整个仓库配置中启用了共享的非隔离运行器。 +- `pnpm test:force`:终止任何仍在占用默认控制端口的残留 Gateway 网关进程,然后使用隔离的 Gateway 网关端口运行完整的 Vitest 测试套件,避免服务端测试与正在运行的实例发生冲突。当之前的 Gateway 网关运行导致端口 `18789` 仍被占用时,请使用它。 +- `pnpm test:coverage`:通过 `vitest.unit.config.ts` 使用 V8 覆盖率运行单元测试套件。这是一个针对已加载文件的单元覆盖率门禁,而不是整个仓库所有文件的覆盖率。阈值为:行数 / 函数 / 语句 `70%`,分支 `55%`。由于 `coverage.all` 为 false,这个门禁会统计被单元覆盖率套件加载的文件,而不是把每个分拆测试 lane 中的源文件都视为未覆盖。 +- `pnpm test:coverage:changed`:仅对自 `origin/main` 以来发生变更的文件运行单元覆盖率。 +- `pnpm test:changed`:当 diff 只涉及可路由的源文件 / 测试文件时,会将 git 变更路径展开为有作用域的 Vitest 测试 lane。配置 / setup 变更仍会回退到原生 root projects 运行方式,以便在需要时对 wiring 变更执行更广泛的重跑。 +- `pnpm changed:lanes`:显示相对于 `origin/main` 的 diff 所触发的架构 lane。 +- `pnpm check:changed`:对相对于 `origin/main` 的 diff 运行智能变更门禁。它会将 core 相关工作与 core 测试 lane 一起运行,将 extension 相关工作与 extension 测试 lane 一起运行,将仅测试相关工作限制为测试类型检查 / 测试本身,对公开 Plugin SDK 或 plugin-contract 的变更扩展为一次 extension 验证,并将仅涉及发布元数据的版本变更限制在定向的版本 / 配置 / 根依赖检查中。 +- `pnpm test`:通过有作用域的 Vitest 测试 lane 路由显式的文件 / 目录目标。未指定目标的运行会使用固定分片组,并展开为 leaf config,以便在本地并行执行;extension 组始终会展开为按 extension 划分的分片配置,而不是一个巨大的 root-project 进程。 +- 完整测试和 extension 分片运行会更新 `.artifacts/vitest-shard-timings.json` 中的本地计时数据;后续运行会使用这些计时来平衡慢分片和快分片。设置 `OPENCLAW_TEST_PROJECTS_TIMINGS=0` 可忽略本地计时产物。 +- 选定的 `plugin-sdk` 和 `commands` 测试文件现在会通过专用的轻量 lane 路由,这些 lane 只保留 `test/setup.ts`,而运行时负载较重的用例仍保留在现有 lane 中。 +- 选定的 `plugin-sdk` 和 `commands` 辅助源文件也会把 `pnpm test:changed` 映射到这些轻量 lane 中的显式同级测试,因此对小型辅助文件的修改无需重新运行重量级、依赖运行时的测试套件。 +- `auto-reply` 现在也被拆分为三个专用配置(`core`、`top-level`、`reply`),这样 reply harness 就不会主导较轻量的 top-level 状态 / token / helper 测试。 +- 基础 Vitest 配置现在默认使用 `pool: "threads"` 和 `isolate: false`,并在整个仓库配置中启用了共享的非隔离 runner。 - `pnpm test:channels` 运行 `vitest.channels.config.ts`。 -- `pnpm test:extensions` 和 `pnpm test extensions` 运行所有扩展/插件分片。重量级渠道插件、浏览器插件以及 OpenAI 会作为专用分片运行;其他插件组仍保持批量运行。对单个内置插件通道,使用 `pnpm test extensions/`。 -- `pnpm test:perf:imports`:启用 Vitest 的导入时长 + 导入明细报告,同时仍对显式文件/目录目标使用有作用域的通道路由。 -- `pnpm test:perf:imports:changed`:与上面相同的导入分析,但仅针对相对于 `origin/main` 已变更的文件。 -- `pnpm test:perf:changed:bench -- --ref `:针对同一组已提交 Git diff,将路由后的 changed 模式路径与原生根项目运行进行基准对比。 -- `pnpm test:perf:changed:bench -- --worktree`:对当前工作树的变更集进行基准测试,无需先提交。 -- `pnpm test:perf:profile:main`:为 Vitest 主线程写入 CPU profile(`.artifacts/vitest-main-profile`)。 -- `pnpm test:perf:profile:runner`:为单元测试运行器写入 CPU + 堆 profile(`.artifacts/vitest-runner-profile`)。 -- `pnpm test:perf:groups --full-suite --allow-failures --output .artifacts/test-perf/baseline-before.json`:串行运行每个完整测试套件的 Vitest 叶子配置,并写入分组时长数据以及每个配置对应的 JSON/日志产物。Test Performance Agent 会在尝试修复慢测试之前,将此结果作为基线。 -- `pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifacts/test-perf/after-agent.json`:比较一次以性能为重点的改动前后两份分组报告。 -- Gateway 网关集成:通过 `OPENCLAW_TEST_INCLUDE_GATEWAY=1 pnpm test` 或 `pnpm test:gateway` 选择启用。 -- `pnpm test:e2e`:运行 Gateway 网关端到端冒烟测试(多实例 WS/HTTP/节点配对)。在 `vitest.e2e.config.ts` 中默认使用 `threads` + `isolate: false` 与自适应 workers;可通过 `OPENCLAW_E2E_WORKERS=` 调整,并设置 `OPENCLAW_E2E_VERBOSE=1` 以输出详细日志。 -- `pnpm test:live`:运行 provider 实时测试(minimax/zai)。需要 API key,并设置 `LIVE=1`(或 provider 专用的 `*_LIVE_TEST=1`)才会取消跳过。 -- `pnpm test:docker:all`:先构建共享的实时测试镜像和 Docker E2E 镜像一次,然后在默认并发数 4 下以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行 Docker 冒烟测试通道。可通过 `OPENCLAW_DOCKER_ALL_PARALLELISM=` 调整。运行器会在首次失败后停止调度新的池化通道,除非设置 `OPENCLAW_DOCKER_ALL_FAIL_FAST=0`;每个通道默认有 120 分钟超时,可通过 `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` 覆盖。对启动敏感或 provider 敏感的通道会在并行池之后独占运行。每个通道的日志会写入 `.artifacts/docker-tests//`。 -- `pnpm test:docker:openwebui`:启动 Docker 化的 OpenClaw + Open WebUI,通过 Open WebUI 登录,检查 `/api/models`,然后通过 `/api/chat/completions` 运行一次真实的代理聊天。需要可用的实时模型 key(例如 `~/.profile` 中的 OpenAI),会拉取外部 Open WebUI 镜像,并不像常规单元/e2e 测试套件那样预期具备 CI 稳定性。 -- `pnpm test:docker:mcp-channels`:启动一个带种子数据的 Gateway 网关容器和第二个客户端容器,后者会启动 `openclaw mcp serve`,然后验证路由会话发现、转录读取、附件元数据、实时事件队列行为、出站发送路由,以及通过真实 stdio bridge 传输的 Claude 风格渠道 + 权限通知。Claude 通知断言会直接读取原始 stdio MCP 帧,因此该冒烟测试反映的是 bridge 实际发出的内容。 +- `pnpm test:extensions` 和 `pnpm test extensions` 会运行所有 extension / plugin 分片。重量级渠道 plugin、browser plugin 和 OpenAI 会作为专用分片运行;其他 plugin 组则保持批量处理。对单个内置 plugin lane,请使用 `pnpm test extensions/`。 +- `pnpm test:perf:imports`:启用 Vitest 的导入耗时 + 导入明细报告,同时仍会对显式文件 / 目录目标使用有作用域的 lane 路由。 +- `pnpm test:perf:imports:changed`:同样进行导入分析,但仅针对自 `origin/main` 以来发生变更的文件。 +- `pnpm test:perf:changed:bench -- --ref `:针对同一份已提交的 git diff,对路由后的 changed 模式路径与原生 root-project 运行进行基准比较。 +- `pnpm test:perf:changed:bench -- --worktree`:无需先提交,直接对当前 worktree 的变更集进行基准比较。 +- `pnpm test:perf:profile:main`:为 Vitest 主线程写出 CPU profile(`.artifacts/vitest-main-profile`)。 +- `pnpm test:perf:profile:runner`:为单元测试 runner 写出 CPU + 堆 profile(`.artifacts/vitest-runner-profile`)。 +- `pnpm test:perf:groups --full-suite --allow-failures --output .artifacts/test-perf/baseline-before.json`:串行运行每个完整测试套件的 Vitest leaf config,并写出分组耗时数据以及每个配置对应的 JSON / 日志产物。Test Performance Agent 会在尝试修复慢测试之前,将其作为基线。 +- `pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifacts/test-perf/after-agent.json`:在面向性能的变更之后,对分组报告进行比较。 +- Gateway 集成测试:通过 `OPENCLAW_TEST_INCLUDE_GATEWAY=1 pnpm test` 或 `pnpm test:gateway` 选择性启用。 +- `pnpm test:e2e`:运行 Gateway 网关端到端冒烟测试(多实例 WS / HTTP / 节点配对)。默认在 `vitest.e2e.config.ts` 中使用 `threads` + `isolate: false` 和自适应 worker;可通过 `OPENCLAW_E2E_WORKERS=` 调整,并设置 `OPENCLAW_E2E_VERBOSE=1` 以输出详细日志。 +- `pnpm test:live`:运行 provider 的 live 测试(minimax / zai)。需要 API key,并设置 `LIVE=1`(或 provider 专用的 `*_LIVE_TEST=1`)才能取消跳过。 +- `pnpm test:docker:all`:先构建共享的 live-test 镜像和 Docker E2E 镜像一次,然后以默认并发数 4、并设置 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行 Docker 冒烟 lane。可通过 `OPENCLAW_DOCKER_ALL_PARALLELISM=` 调整。除非设置 `OPENCLAW_DOCKER_ALL_FAIL_FAST=0`,否则 runner 会在第一次失败后停止调度新的池化 lane;每个 lane 默认有 120 分钟超时,可通过 `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` 覆盖。对启动过程敏感或 provider 敏感的 lane 会在并行池之后独占运行。每个 lane 的日志会写入 `.artifacts/docker-tests//`。 +- `pnpm test:docker:openwebui`:启动 Docker 化的 OpenClaw + Open WebUI,通过 Open WebUI 登录,检查 `/api/models`,然后通过 `/api/chat/completions` 运行一次真实的代理聊天。需要可用的 live model key(例如 `~/.profile` 中的 OpenAI),会拉取外部 Open WebUI 镜像,并不像常规单元 / e2e 测试套件那样被视为 CI 稳定测试。 +- `pnpm test:docker:mcp-channels`:启动一个已植入数据的 Gateway 网关容器,以及第二个会启动 `openclaw mcp serve` 的客户端容器,然后验证经路由的会话发现、转录读取、附件元数据、live 事件队列行为、出站发送路由,以及通过真实 stdio bridge 发送的 Claude 风格渠道 + 权限通知。Claude 通知断言会直接读取原始 stdio MCP frame,因此这个冒烟测试反映的是 bridge 实际发出的内容。 ## 本地 PR 门禁 -在本地执行 PR 合并/门禁检查时,运行: +在本地执行 PR 合入 / 门禁检查时,请运行: - `pnpm check:changed` - `pnpm check` @@ -54,7 +54,7 @@ x-i18n: - `pnpm test` - `pnpm check:docs` -如果 `pnpm test` 在高负载主机上出现偶发失败,在将其视为回归之前先重跑一次,然后使用 `pnpm test ` 做隔离。对于内存受限的主机,使用: +如果 `pnpm test` 在负载较高的主机上出现偶发失败,请先重跑一次,再决定是否将其视为回归;之后可用 `pnpm test ` 进行隔离。在内存受限的主机上,请使用: - `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test` - `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/tmp/openclaw-vitest-cache pnpm test:changed` @@ -67,9 +67,9 @@ x-i18n: - `source ~/.profile && pnpm tsx scripts/bench-model.ts --runs 10` - 可选环境变量:`MINIMAX_API_KEY`、`MINIMAX_BASE_URL`、`MINIMAX_MODEL`、`ANTHROPIC_API_KEY` -- 默认提示词:“Reply with a single word: ok. No punctuation or extra text.” +- 默认提示词:“用一个单词回复:ok。不要标点或额外文本。” -上次运行(2025-12-31,20 次): +最近一次运行(2025-12-31,20 次): - minimax 中位数 1279ms(最小 1114,最大 2431) - opus 中位数 2454ms(最小 1224,最大 3170) @@ -99,37 +99,37 @@ x-i18n: - `startup`:`--version`、`--help`、`health`、`health --json`、`status --json`、`status` - `real`:`health`、`status`、`status --json`、`sessions`、`sessions --json`、`agents list --json`、`gateway status`、`gateway status --json`、`gateway health --json`、`config get gateway.port` -- `all`:两个预设都包含 +- `all`:同时包含两个预设 -输出内容包括每个命令的 `sampleCount`、平均值、p50、p95、最小/最大值、exit-code/signal 分布,以及最大 RSS 汇总。可选的 `--cpu-prof-dir` / `--heap-prof-dir` 会为每次运行写入 V8 profile,因此计时与 profile 采集使用的是同一套测试框架。 +输出包括每个命令的 `sampleCount`、平均值、p50、p95、最小值 / 最大值、exit-code / signal 分布,以及最大 RSS 汇总。可选的 `--cpu-prof-dir` / `--heap-prof-dir` 会为每次运行写出 V8 profile,因此计时和 profile 采集使用的是同一套 harness。 -已保存输出约定: +保存输出约定: - `pnpm test:startup:bench:smoke` 会将定向冒烟产物写入 `.artifacts/cli-startup-bench-smoke.json` - `pnpm test:startup:bench:save` 会使用 `runs=5` 和 `warmup=1` 将完整测试套件产物写入 `.artifacts/cli-startup-bench-all.json` -- `pnpm test:startup:bench:update` 会使用 `runs=5` 和 `warmup=1` 刷新已签入的基线夹具 `test/fixtures/cli-startup-bench.json` +- `pnpm test:startup:bench:update` 会使用 `runs=5` 和 `warmup=1` 刷新已提交的基线 fixture:`test/fixtures/cli-startup-bench.json` -已签入夹具: +已提交的 fixture: - `test/fixtures/cli-startup-bench.json` - 使用 `pnpm test:startup:bench:update` 刷新 -- 使用 `pnpm test:startup:bench:check` 将当前结果与该夹具进行比较 +- 使用 `pnpm test:startup:bench:check` 将当前结果与该 fixture 进行比较 ## 新手引导 E2E(Docker) Docker 是可选的;只有在运行容器化新手引导冒烟测试时才需要它。 -在干净的 Linux 容器中执行完整冷启动流程: +在干净的 Linux 容器中运行完整冷启动流程: ```bash scripts/e2e/onboard-docker.sh ``` -该脚本会通过 pseudo-tty 驱动交互式向导,验证 config/workspace/session 文件,然后启动 Gateway 网关并运行 `openclaw health`。 +该脚本会通过 pseudo-tty 驱动交互式向导,验证 config / workspace / session 文件,然后启动 Gateway 网关并运行 `openclaw health`。 ## QR 导入冒烟测试(Docker) -确保维护中的 QR 运行时辅助程序可在受支持的 Docker Node 运行时中加载(默认 Node 24,兼容 Node 22): +确保维护中的 QR 运行时辅助程序能在受支持的 Docker Node 运行时下加载(默认 Node 24,兼容 Node 22): ```bash pnpm test:docker:qr diff --git a/docs/zh-CN/tools/exec-approvals-advanced.md b/docs/zh-CN/tools/exec-approvals-advanced.md new file mode 100644 index 000000000..93ccc457a --- /dev/null +++ b/docs/zh-CN/tools/exec-approvals-advanced.md @@ -0,0 +1,209 @@ +--- +read_when: + - 配置安全二进制文件或自定义安全二进制文件配置档案 + - 将批准转发到 Slack/Discord/Telegram 或其他聊天渠道 + - 为渠道实现原生批准客户端 +summary: 高级 exec 批准:安全二进制文件、解释器绑定、批准转发、本地交付 +title: exec 批准——高级 +x-i18n: + generated_at: "2026-04-23T23:21:49Z" + model: gpt-5.4 + provider: openai + source_hash: 8a24a3539126b0f0fd11696c31efc8a6a9a4262fe4cd89bf456ff92a4f05c36c + source_path: tools/exec-approvals-advanced.md + workflow: 15 +--- + +高级 exec 批准主题:`safeBins` 快速路径、解释器/运行时绑定,以及向聊天渠道转发批准(包括原生交付)。 +有关核心策略和批准流程,请参见 [Exec approvals](/zh-CN/tools/exec-approvals)。 + +## 安全二进制文件(仅 stdin) + +`tools.exec.safeBins` 定义了一小组**仅 stdin** 的二进制文件(例如 `cut`),它们在允许列表模式下**无需**显式允许列表条目即可运行。安全二进制文件会拒绝位置文件参数和类似路径的令牌,因此它们只能对输入流进行操作。请将其视为面向流过滤器的狭窄快速路径,而不是通用信任列表。 + + +**不要**将解释器或运行时二进制文件(例如 `python3`、`node`、`ruby`、`bash`、`sh`、`zsh`)添加到 `safeBins`。如果某个命令能够按设计执行代码求值、执行子命令或读取文件,请优先使用显式允许列表条目,并保持启用批准提示。自定义安全二进制文件必须在 `tools.exec.safeBinProfiles.` 中定义显式配置档案。 + + +默认安全二进制文件: + +[//]: # "SAFE_BIN_DEFAULTS:START" + +`cut`, `uniq`, `head`, `tail`, `tr`, `wc` + +[//]: # "SAFE_BIN_DEFAULTS:END" + +`grep` 和 `sort` 不在默认列表中。如果你选择启用它们,请为其非 stdin 工作流保留显式允许列表条目。对于安全二进制文件模式下的 `grep`,请使用 `-e`/`--regexp` 提供模式;位置模式形式会被拒绝,这样文件操作数就不能伪装成含糊的位置参数。 + +### Argv 验证与被拒绝的标志 + +验证仅基于 argv 形状进行确定性判断(不检查主机文件系统中的存在性),这可以防止通过允许/拒绝差异形成文件存在性预言机行为。面向文件的选项会被默认安全二进制文件拒绝;长选项采用失败即关闭的验证方式(未知标志和含糊缩写都会被拒绝)。 + +按安全二进制文件配置档案划分的被拒绝标志: + +[//]: # "SAFE_BIN_DENIED_FLAGS:START" + +- `grep`:`--dereference-recursive`、`--directories`、`--exclude-from`、`--file`、`--recursive`、`-R`、`-d`、`-f`、`-r` +- `jq`:`--argfile`、`--from-file`、`--library-path`、`--rawfile`、`--slurpfile`、`-L`、`-f` +- `sort`:`--compress-program`、`--files0-from`、`--output`、`--random-source`、`--temporary-directory`、`-T`、`-o` +- `wc`:`--files0-from` + +[//]: # "SAFE_BIN_DENIED_FLAGS:END" + +安全二进制文件还会在执行时强制将 argv 令牌视为**字面文本**(不进行通配符展开,也不展开 `$VARS`),适用于仅 stdin 的命令段,因此像 `*` 或 `$HOME/...` 这样的模式不能被用来伪装文件读取。 + +### 受信任的二进制文件目录 + +安全二进制文件必须从受信任的二进制文件目录解析(系统默认目录,加上可选的 `tools.exec.safeBinTrustedDirs`)。`PATH` 条目绝不会被自动视为受信任。默认受信任目录刻意保持最小范围:`/bin`、`/usr/bin`。如果你的安全二进制文件可执行文件位于包管理器/用户路径中(例如 `/opt/homebrew/bin`、`/usr/local/bin`、`/opt/local/bin`、`/snap/bin`),请将它们显式添加到 `tools.exec.safeBinTrustedDirs`。 + +### Shell 链接、包装器与多路复用器 + +当每个顶层命令段都满足允许列表要求时,允许使用 shell 链接(`&&`、`||`、`;`),其中包括安全二进制文件或 Skills 自动允许。重定向在允许列表模式下仍然不受支持。命令替换(`$()` / 反引号)会在允许列表解析期间被拒绝,即使它位于双引号内部也是如此;如果你需要字面的 `$()` 文本,请使用单引号。 + +在 macOS 配套应用批准中,包含 shell 控制或展开语法(`&&`、`||`、`;`、`|`、`` ` ``、`$`、`<`、`>`、`(`、`)`)的原始 shell 文本会被视为允许列表未命中,除非 shell 二进制文件本身已被加入允许列表。 + +对于 shell 包装器(`bash|sh|zsh ... -c/-lc`),请求范围内的环境变量覆盖会被缩减为一个小型显式允许列表(`TERM`、`LANG`、`LC_*`、`COLORTERM`、`NO_COLOR`、`FORCE_COLOR`)。 + +对于允许列表模式中的 `allow-always` 决策,已知的分发包装器(`env`、`nice`、`nohup`、`stdbuf`、`timeout`)会持久化内部可执行文件路径,而不是包装器路径。Shell 多路复用器(`busybox`、`toybox`)对于 shell applet(`sh`、`ash` 等)也会以相同方式解包。如果某个包装器或多路复用器无法被安全解包,则不会自动持久化任何允许列表条目。 + +如果你将 `python3` 或 `node` 这样的解释器加入允许列表,建议启用 `tools.exec.strictInlineEval=true`,这样内联求值仍然需要显式批准。在严格模式下,`allow-always` 仍然可以持久化无害的解释器/脚本调用,但承载内联求值的调用不会被自动持久化。 + +### 安全二进制文件与允许列表 + +| 主题 | `tools.exec.safeBins` | 允许列表(`exec-approvals.json`) | +| ---------------- | ------------------------------------------------------ | ------------------------------------------------------------ | +| 目标 | 自动允许狭窄的 stdin 过滤器 | 显式信任特定可执行文件 | +| 匹配类型 | 可执行文件名称 + 安全二进制文件 argv 策略 | 已解析可执行文件路径 glob 模式 | +| 参数范围 | 受安全二进制文件配置档案和字面令牌规则限制 | 仅匹配路径;参数的其他部分由你自行负责 | +| 典型示例 | `head`、`tail`、`tr`、`wc` | `jq`、`python3`、`node`、`ffmpeg`、自定义 CLI | +| 最佳用途 | 管道中的低风险文本转换 | 任何具有更广泛行为或副作用的工具 | + +配置位置: + +- `safeBins` 来自配置(`tools.exec.safeBins` 或按智能体设置的 `agents.list[].tools.exec.safeBins`)。 +- `safeBinTrustedDirs` 来自配置(`tools.exec.safeBinTrustedDirs` 或按智能体设置的 `agents.list[].tools.exec.safeBinTrustedDirs`)。 +- `safeBinProfiles` 来自配置(`tools.exec.safeBinProfiles` 或按智能体设置的 `agents.list[].tools.exec.safeBinProfiles`)。按智能体设置的配置档案键会覆盖全局键。 +- 允许列表条目存放在主机本地的 `~/.openclaw/exec-approvals.json` 中的 `agents..allowlist` 下(或通过 Control UI / `openclaw approvals allowlist ...`)。 +- 当解释器/运行时二进制文件出现在 `safeBins` 中且没有显式配置档案时,`openclaw security audit` 会给出 `tools.exec.safe_bins_interpreter_unprofiled` 警告。 +- `openclaw doctor --fix` 可以为缺失的自定义 `safeBinProfiles.` 条目搭建 `{}` 骨架(之后请审查并收紧)。解释器/运行时二进制文件不会被自动搭建骨架。 + +自定义配置档案示例: +__OC_I18N_900000__ +如果你显式选择将 `jq` 加入 `safeBins`,OpenClaw 在安全二进制文件模式下仍会拒绝 `env` 内建,因此 `jq -n env` 不能在没有显式允许列表路径或批准提示的情况下导出主机进程环境。 + +## 解释器/运行时命令 + +基于批准的解释器/运行时执行有意采取保守策略: + +- 始终绑定精确的 argv/cwd/env 上下文。 +- 直接 shell 脚本和直接运行时文件形式会尽力绑定到一个具体的本地文件快照。 +- 仍然能够解析为单个直接本地文件的常见包管理器包装形式(例如 `pnpm exec`、`pnpm node`、`npm exec`、`npx`)会在绑定前被解包。 +- 如果 OpenClaw 无法为解释器/运行时命令精确识别唯一一个具体本地文件(例如包脚本、eval 形式、运行时特定加载器链或含糊的多文件形式),则基于批准的执行会被拒绝,而不是声称自己覆盖了实际上并不具备的语义范围。 +- 对于这些工作流,请优先考虑沙箱隔离、单独的主机边界,或显式受信任的允许列表/完整工作流,在这些场景中由操作员接受更广泛的运行时语义。 + +当需要批准时,exec 工具会立即返回一个批准 id。使用该 id 关联后续系统事件(`Exec finished` / `Exec denied`)。如果在超时之前没有收到决策,请求会被视为批准超时,并作为拒绝原因呈现。 + +### 后续交付行为 + +在已批准的异步 exec 完成后,OpenClaw 会向同一会话发送一个后续 `agent` 回合。 + +- 如果存在有效的外部交付目标(可交付渠道加上目标 `to`),后续交付会使用该渠道。 +- 在仅 webchat 或仅内部会话流程中,如果没有外部目标,后续交付会保持为仅会话(`deliver: false`)。 +- 如果调用方显式请求严格的外部交付,但没有可解析的外部渠道,请求会以 `INVALID_REQUEST` 失败。 +- 如果启用了 `bestEffortDeliver` 且无法解析任何外部渠道,交付会降级为仅会话,而不是失败。 + +## 向聊天渠道转发批准 + +你可以将 exec 批准提示转发到任何聊天渠道(包括渠道插件),并使用 `/approve` 进行批准。这会使用正常的出站交付管道。 + +配置: +__OC_I18N_900001__ +在聊天中回复: +__OC_I18N_900002__ +`/approve` 命令同时处理 exec 批准和插件批准。如果该 ID 与待处理的 exec 批准不匹配,它会自动改为检查插件批准。 + +### 插件批准转发 + +插件批准转发使用与 exec 批准相同的交付管道,但它在 `approvals.plugin` 下拥有自己独立的配置。启用或禁用其中一个不会影响另一个。 +__OC_I18N_900003__ +该配置结构与 `approvals.exec` 相同:`enabled`、`mode`、`agentFilter`、`sessionFilter` 和 `targets` 的工作方式完全一致。 + +支持共享交互式回复的渠道会为 exec 批准和插件批准渲染相同的批准按钮。不支持共享交互式 UI 的渠道会回退为纯文本,并附带 `/approve` 说明。 + +### 任意渠道中的同聊天批准 + +当 exec 或插件批准请求来自可交付的聊天界面时,现在默认可以在同一聊天中通过 `/approve` 进行批准。这适用于 Slack、Matrix 和 Microsoft Teams 等渠道,也适用于现有的 Web UI 和终端 UI 流程。 + +这一路径共享的文本命令使用该会话的正常渠道身份验证模型。如果发起请求的聊天本来就能够发送命令并接收回复,那么批准请求不再需要单独的原生交付适配器才能保持待处理状态。 + +Discord 和 Telegram 也支持在同一聊天中使用 `/approve`,但即使禁用了原生批准交付,这些渠道在授权时仍然会使用其已解析的批准人列表。 + +对于 Telegram 和其他直接调用 Gateway 网关的原生批准客户端,这个回退有意被限制在“找不到批准”失败场景。真正的 exec 批准拒绝/错误不会被静默重试为插件批准。 + +### 原生批准交付 + +某些渠道还可以充当原生批准客户端。原生客户端会在共享的同聊天 `/approve` 流程之上增加批准人私信、原始聊天扇出以及渠道特定的交互式批准 UX。 + +当原生批准卡片/按钮可用时,该原生 UI 是面向智能体的主要路径。除非工具结果表明聊天批准不可用,或手动批准是唯一剩余路径,否则智能体不应再额外回显重复的纯聊天 `/approve` 命令。 + +通用模型: + +- 主机 exec 策略仍然决定 exec 是否需要批准 +- `approvals.exec` 控制将批准提示转发到其他聊天目标 +- `channels..execApprovals` 控制该渠道是否充当原生批准客户端 + +当以下条件全部满足时,原生批准客户端会自动启用优先发送到私信的交付方式: + +- 该渠道支持原生批准交付 +- 可以从显式的 `execApprovals.approvers` 或该渠道文档记录的回退来源中解析出批准人 +- `channels..execApprovals.enabled` 未设置或为 `"auto"` + +设置 `enabled: false` 可以显式禁用原生批准客户端。设置 `enabled: true` 可以在批准人可解析时强制启用它。公开的原始聊天交付仍通过 `channels..execApprovals.target` 显式控制。 + +常见问题:[为什么聊天批准会有两个 exec 批准配置?](/help/faq#why-are-there-two-exec-approval-configs-for-chat-approvals) + +- Discord:`channels.discord.execApprovals.*` +- Slack:`channels.slack.execApprovals.*` +- Telegram:`channels.telegram.execApprovals.*` + +这些原生批准客户端在共享的同聊天 `/approve` 流程和共享批准按钮的基础上,增加了私信路由和可选的渠道扇出。 + +共享行为: + +- Slack、Matrix、Microsoft Teams 以及类似的可交付聊天,都会对同聊天 `/approve` 使用正常的渠道身份验证模型 +- 当原生批准客户端自动启用时,默认的原生交付目标是批准人私信 +- 对于 Discord 和 Telegram,只有已解析的批准人才能批准或拒绝 +- Discord 批准人可以是显式指定的(`execApprovals.approvers`),也可以从 `commands.ownerAllowFrom` 推断得出 +- Telegram 批准人可以是显式指定的(`execApprovals.approvers`),也可以从现有的所有者配置推断得出(`allowFrom`,以及在支持时的私信 `defaultTo`) +- Slack 批准人可以是显式指定的(`execApprovals.approvers`),也可以从 `commands.ownerAllowFrom` 推断得出 +- Slack 原生按钮会保留批准 id 类型,因此 `plugin:` id 可以解析为插件批准,而无需第二层 Slack 本地回退逻辑 +- Matrix 原生私信/渠道路由和 reaction 快捷方式同时处理 exec 批准和插件批准;插件授权仍然来自 `channels.matrix.dm.allowFrom` +- 请求者不需要是批准人 +- 当原始聊天本身已支持命令和回复时,可以直接通过 `/approve` 在该聊天中完成批准 +- 原生 Discord 批准按钮按批准 id 类型进行路由:`plugin:` id 会直接进入插件批准,其余所有情况都会进入 exec 批准 +- 原生 Telegram 批准按钮遵循与 `/approve` 相同的受限 exec 到插件回退逻辑 +- 当原生 `target` 启用原始聊天交付时,批准提示会包含命令文本 +- 待处理的 exec 批准默认会在 30 分钟后过期 +- 如果没有操作员 UI 或已配置的批准客户端可以接受请求,提示会回退到 `askFallback` + +Telegram 默认发送到批准人私信(`target: "dm"`)。如果你希望批准提示也出现在发起请求的 Telegram 聊天/话题中,可以切换为 `channel` 或 `both`。对于 Telegram 论坛话题,OpenClaw 会在批准提示和批准后的后续消息中保留该话题。 + +参见: + +- [Discord](/channels/discord) +- [Telegram](/channels/telegram) + +### macOS IPC 流程 +__OC_I18N_900004__ +安全说明: + +- Unix socket 模式为 `0600`,token 存储在 `exec-approvals.json` 中。 +- 同一 UID 对等方检查。 +- 质询/响应(nonce + HMAC token + 请求哈希)+ 短 TTL。 + +## 相关内容 + +- [Exec approvals](/zh-CN/tools/exec-approvals) —— 核心策略和批准流程 +- [Exec tool](/zh-CN/tools/exec) +- [Elevated mode](/zh-CN/tools/elevated) +- [Skills](/zh-CN/tools/skills) —— 基于 Skills 的自动允许行为 diff --git a/docs/zh-CN/tools/exec-approvals.md b/docs/zh-CN/tools/exec-approvals.md index 8d7e81dbf..5e1dcfe9d 100644 --- a/docs/zh-CN/tools/exec-approvals.md +++ b/docs/zh-CN/tools/exec-approvals.md @@ -1,67 +1,69 @@ --- read_when: - 配置执行审批或允许列表 - - 在 macOS 应用中实现执行审批 UX + - 在 macOS 应用中实现执行审批用户体验 - 审查沙箱逃逸提示及其影响 summary: 执行审批、允许列表和沙箱逃逸提示 title: 执行审批 x-i18n: - generated_at: "2026-04-23T22:14:42Z" + generated_at: "2026-04-23T23:21:50Z" model: gpt-5.4 provider: openai - source_hash: a4090e0726d9cee3372a11e6bf8f7899546e68f4fabea42dcb55b87593e9315c + source_hash: 0d7c5cd24e7c1831d5a865da6fa20f4c23280a0ec12b9e8f7f3245170a05a37d source_path: tools/exec-approvals.md workflow: 15 --- -执行审批是 **配套应用 / 节点主机防护栏**,用于让处于沙箱隔离的智能体在真实主机(`gateway` 或 `node`)上运行命令。它是一种安全联锁机制:只有当策略 + 允许列表 +(可选的)用户审批全部同意时,命令才会被允许执行。执行审批会**叠加在**工具策略和 elevated 门控之上(除非 elevated 设为 `full`,此时会跳过审批)。 +执行审批是**配套应用 / 节点主机防护栏**,用于让处于沙箱隔离的智能体在真实主机(`gateway` 或 `node`)上运行命令。它是一个安全联锁机制:只有当策略 + 允许列表 +(可选)用户审批三者全部一致同意时,命令才会被允许执行。执行审批会**叠加在**工具策略和 elevated 门控之上(除非 elevated 设为 `full`,这会跳过审批)。 -生效策略取 `tools.exec.*` 与审批默认值中**更严格**的一方;如果某个 approvals 字段被省略,则使用 `tools.exec` 的值。主机执行也会使用该机器上的本地 approvals 状态——如果 `~/.openclaw/exec-approvals.json` 中主机本地配置了 `ask: "always"`,即使会话或配置默认值请求 `ask: "on-miss"`,系统仍会持续提示。 +生效策略取 `tools.exec.*` 与审批默认值中**更严格**的一方;如果某个 approvals 字段被省略,则使用 `tools.exec` 的值。主机执行还会使用该机器上的本地 approvals 状态——如果 `~/.openclaw/exec-approvals.json` 中的主机本地 `ask: "always"` 已设置,即使会话或配置默认值请求 `ask: "on-miss"`,也仍然会持续弹出提示。 ## 检查生效策略 -- `openclaw approvals get`、`... --gateway`、`... --node ` —— 显示请求的策略、主机策略来源以及最终生效结果。 -- `openclaw exec-policy show` —— 本地机器的合并视图。 +- `openclaw approvals get`、`... --gateway`、`... --node ` —— 显示请求的策略、主机策略来源,以及最终生效结果。 +- `openclaw exec-policy show` —— 显示本地机器上的合并视图。 - `openclaw exec-policy set|preset` —— 一步同时同步本地请求策略和本地主机 approvals 文件。 -当本地作用域请求 `host=node` 时,`exec-policy show` 会在运行时将该作用域报告为由节点管理,而不是假装本地 approvals 文件是真实来源。 +当本地作用域请求 `host=node` 时,`exec-policy show` 会在运行时将该作用域报告为由节点管理,而不是假装本地 approvals 文件才是事实来源。 -如果配套应用 UI **不可用**,任何原本会触发提示的请求都会根据 **ask fallback** 处理(默认:拒绝)。 +如果配套应用 UI **不可用**,任何原本需要弹出提示的请求都会通过 **ask fallback** 处理(默认:拒绝)。 -原生聊天审批客户端可以在待审批消息上预置特定渠道的交互方式。例如,Matrix 会预置反应快捷方式(`✅` 允许一次、`❌` 拒绝、`♾️` 始终允许),同时仍保留消息中的 `/approve ...` 命令作为后备方式。 +原生聊天审批客户端可以在待审批消息上预置特定渠道的便捷交互。例如,Matrix 会预置反应快捷方式(`✅` +允许一次、`❌` 拒绝、`♾️` 始终允许),同时仍然在消息中保留 `/approve ...` +命令作为后备方式。 ## 适用范围 执行审批会在执行主机本地强制生效: -- **gateway host** → Gateway 网关机器上的 `openclaw` 进程 -- **node host** → 节点运行器(macOS 配套应用或无头节点主机) +- **Gateway 网关主机** → Gateway 网关机器上的 `openclaw` 进程 +- **节点主机** → 节点运行器(macOS 配套应用或无头节点主机) 信任模型说明: - 通过 Gateway 网关认证的调用方,是该 Gateway 网关的受信任操作员。 - 已配对节点会将这种受信任操作员能力扩展到节点主机。 -- 执行审批可降低意外执行风险,但它不是按用户划分的身份验证边界。 -- 经批准的节点主机执行会绑定规范执行上下文:规范 cwd、精确 argv、存在时的 env 绑定,以及适用时固定的可执行文件路径。 -- 对于 shell 脚本和直接解释器 / 运行时文件调用,OpenClaw 还会尝试绑定一个具体的本地文件操作数。如果该已绑定文件在审批后、执行前发生变化,则会拒绝执行,而不是运行已漂移的内容。 -- 这种文件绑定有意设计为尽力而为,并不是对所有解释器 / 运行时加载路径的完整语义模型。如果审批模式无法识别并绑定**唯一一个**具体本地文件,它会拒绝签发基于审批的执行,而不是假装提供了完整覆盖。 +- 执行审批会降低误执行风险,但它并不是按用户划分的身份验证边界。 +- 已批准的节点主机执行会绑定规范化执行上下文:规范化 `cwd`、精确 `argv`、存在时的环境变量绑定,以及适用时固定的可执行文件路径。 +- 对于 shell 脚本以及直接调用解释器 / 运行时文件的情况,OpenClaw 还会尝试绑定一个具体的本地文件操作数。如果该绑定文件在审批后、执行前发生变化,则会拒绝执行,而不是执行已漂移的内容。 +- 这种文件绑定有意设计为尽力而为,并不是对每一种解释器 / 运行时加载路径的完整语义建模。如果审批模式无法识别出**恰好一个**可绑定的具体本地文件,它会拒绝签发基于审批的执行,而不是假装已经完全覆盖。 macOS 拆分: -- **node host service** 会通过本地 IPC 将 `system.run` 转发给 **macOS app**。 -- **macOS app** 负责强制执行审批并在 UI 上下文中执行命令。 +- **节点主机服务** 通过本地 IPC 将 `system.run` 转发给 **macOS 应用**。 +- **macOS 应用** 负责执行审批并在 UI 上下文中运行命令。 ## 设置与存储 -审批信息保存在执行主机本地的 JSON 文件中: +审批信息保存在执行主机上的本地 JSON 文件中: `~/.openclaw/exec-approvals.json` -示例 schema: +示例结构: ```json { @@ -96,34 +98,35 @@ macOS 拆分: } ``` -## 无审批 “YOLO” 模式 +## 无需审批的 “YOLO” 模式 -如果你希望主机执行在没有审批提示的情况下运行,就必须同时放开**两层**策略: +如果你希望主机执行在没有审批提示的情况下运行,你必须同时放开**两层**策略: - OpenClaw 配置中的请求执行策略(`tools.exec.*`) - `~/.openclaw/exec-approvals.json` 中的主机本地 approvals 策略 -这现在是默认的主机行为,除非你显式收紧它: +现在这已是默认主机行为,除非你显式收紧它: -- `tools.exec.security`: 在 `gateway`/`node` 上设为 `full` +- `tools.exec.security`: 在 `gateway` / `node` 上设为 `full` - `tools.exec.ask`: `off` - 主机 `askFallback`: `full` 重要区别: -- `tools.exec.host=auto` 用于选择执行运行位置:有沙箱时在沙箱中,否则在 gateway。 -- YOLO 用于选择主机执行如何获批:`security=full` 加 `ask=off`。 -- 暴露自身非交互权限模式的 CLI 后端 provider 可以遵循此策略。 - Claude CLI 会在 OpenClaw 请求的执行策略为 YOLO 时添加 `--permission-mode bypassPermissions`。你可以通过 - `agents.defaults.cliBackends.claude-cli.args` / `resumeArgs` 下的显式 Claude 参数覆盖该后端行为,例如 +- `tools.exec.host=auto` 选择执行运行的位置:有沙箱时在沙箱中,否则在 Gateway 网关上。 +- YOLO 选择的是主机执行的审批方式:`security=full` 加 `ask=off`。 +- 暴露自身非交互权限模式的基于 CLI 的提供商可以遵循此策略。 + Claude CLI 会在 OpenClaw 的请求执行策略为 + YOLO 时添加 `--permission-mode bypassPermissions`。你可以在 + `agents.defaults.cliBackends.claude-cli.args` / `resumeArgs` 下通过显式 Claude 参数覆盖该后端行为,例如 `--permission-mode default`、`acceptEdits` 或 `bypassPermissions`。 -- 在 YOLO 模式下,OpenClaw 不会在已配置的主机执行策略之上,再额外添加单独的启发式命令混淆审批门控或脚本预检拒绝层。 -- `auto` 不会让来自沙箱隔离会话的 gateway 路由请求变成可随意覆盖的“免费通行证”。每次调用的 `host=node` 请求在 `auto` 下是允许的,而 `host=gateway` 只有在没有活动沙箱运行时时才允许从 `auto` 使用。如果你想要稳定的非 auto 默认值,请设置 `tools.exec.host` 或显式使用 `/exec host=...`。 +- 在 YOLO 模式下,OpenClaw 不会在已配置的主机执行策略之上,再额外添加独立的启发式命令混淆审批门控或脚本预检拒绝层。 +- `auto` 不会让 Gateway 网关路由成为沙箱隔离会话中的免费覆盖选项。允许从 `auto` 发起单次调用的 `host=node` 请求,而只有在没有活动沙箱运行时时,才允许从 `auto` 发起 `host=gateway`。如果你希望获得稳定的非 auto 默认值,请设置 `tools.exec.host` 或显式使用 `/exec host=...`。 -如果你希望采用更保守的设置,可将任一层重新收紧为 `allowlist` / `on-miss` +如果你想使用更保守的设置,可以将任一层收紧回 `allowlist` / `on-miss` 或 `deny`。 -持久化 gateway host “永不提示” 配置: +持久化的 Gateway 网关主机 “永不提示” 设置: ```bash openclaw config set tools.exec.host gateway @@ -132,7 +135,7 @@ openclaw config set tools.exec.ask off openclaw gateway restart ``` -然后将主机 approvals 文件设为匹配值: +然后将主机 approvals 文件设置为匹配值: ```bash openclaw approvals set --stdin <<'EOF' @@ -147,7 +150,7 @@ openclaw approvals set --stdin <<'EOF' EOF ``` -在当前机器上为相同 gateway host 策略提供的本地快捷方式: +用于在当前机器上设置相同 Gateway 网关主机策略的本地快捷方式: ```bash openclaw exec-policy preset yolo @@ -158,7 +161,8 @@ openclaw exec-policy preset yolo - 本地 `tools.exec.host/security/ask` - 本地 `~/.openclaw/exec-approvals.json` 默认值 -它有意仅限本地使用。如果你需要远程更改 gateway host 或 node host 的审批,请继续使用 `openclaw approvals set --gateway` 或 +它有意仅在本地生效。如果你需要远程更改 Gateway 网关主机或节点主机审批, +请继续使用 `openclaw approvals set --gateway` 或 `openclaw approvals set --node `。 对于节点主机,请在该节点上应用相同的 approvals 文件: @@ -176,45 +180,45 @@ openclaw approvals set --node --stdin <<'EOF' EOF ``` -重要的仅限本地限制: +重要的仅本地限制: - `openclaw exec-policy` 不会同步节点审批 - `openclaw exec-policy set --host node` 会被拒绝 - 节点执行审批会在运行时从节点获取,因此面向节点的更新必须使用 `openclaw approvals --node ...` -仅会话快捷方式: +仅限当前会话的快捷方式: - `/exec security=full ask=off` 只会更改当前会话。 - `/elevated full` 是一个紧急放行快捷方式,也会跳过该会话的执行审批。 -如果主机 approvals 文件仍比配置更严格,则仍以更严格的主机策略为准。 +如果主机 approvals 文件仍然比配置更严格,那么更严格的主机策略依然会生效。 -## 策略开关 +## 策略旋钮 -### 安全级别(`exec.security`) +### 安全性(`exec.security`) - **deny**:阻止所有主机执行请求。 - **allowlist**:仅允许允许列表中的命令。 -- **full**:允许全部(等同于 elevated)。 +- **full**:允许所有内容(等同于 elevated)。 -### 询问方式(`exec.ask`) +### 询问(`exec.ask`) - **off**:从不提示。 -- **on-miss**:仅当允许列表未匹配时提示。 +- **on-miss**:仅在允许列表不匹配时提示。 - **always**:每条命令都提示。 -- 当生效的询问模式为 `always` 时,`allow-always` 的持久信任不会抑制提示 +- 当生效的 ask 模式为 `always` 时,`allow-always` 的持久信任不会抑制提示 -### 询问后备(`askFallback`) +### 询问回退(`askFallback`) -如果需要提示但没有可达 UI,则由 fallback 决定: +如果需要提示,但没有可达的 UI,则由 fallback 决定: - **deny**:阻止。 -- **allowlist**:仅当允许列表匹配时允许。 +- **allowlist**:仅在允许列表匹配时允许。 - **full**:允许。 -### 行内解释器 eval 加固(`tools.exec.strictInlineEval`) +### 行内解释器求值加固(`tools.exec.strictInlineEval`) -当 `tools.exec.strictInlineEval=true` 时,OpenClaw 会将行内代码 eval 形式视为“仅可通过审批执行”,即使解释器二进制本身已经在允许列表中。 +当 `tools.exec.strictInlineEval=true` 时,即使解释器二进制本身已在允许列表中,OpenClaw 也会将行内代码求值形式视为仅可通过审批执行。 示例: @@ -226,14 +230,14 @@ EOF - `lua -e` - `osascript -e` -这是针对无法干净映射到单一稳定文件操作数的解释器加载路径所做的纵深防御。在严格模式下: +这是针对无法清晰映射到单一稳定文件操作数的解释器加载路径所做的纵深防御。在严格模式下: - 这些命令仍然需要显式审批; - `allow-always` 不会自动为它们持久化新的允许列表条目。 -## 允许列表(按智能体区分) +## 允许列表(按智能体划分) -允许列表是**按智能体**划分的。如果存在多个智能体,请在 macOS 应用中切换你正在编辑的智能体。模式是**不区分大小写的 glob 匹配**。 +允许列表是**按智能体**划分的。如果存在多个智能体,请在 macOS 应用中切换你正在编辑的智能体。模式为**不区分大小写的 glob 匹配**。 模式应解析为**二进制路径**(仅文件名的条目会被忽略)。 旧版 `agents.default` 条目会在加载时迁移到 `agents.main`。 像 `echo ok && pwd` 这样的 shell 链式命令,仍然要求每个顶层片段都满足允许列表规则。 @@ -246,292 +250,87 @@ EOF 每个允许列表条目会跟踪: -- **id**:用于 UI 身份识别的稳定 UUID(可选) -- **last used**:上次使用时间戳 -- **last used command**:上次使用的命令 -- **last resolved path**:上次解析到的路径 +- **id**:用于 UI 标识的稳定 UUID(可选) +- **上次使用** +- **上次使用的命令** +- **上次解析的路径** -## 自动允许 Skill CLI +## 自动允许技能 CLI -启用 **Auto-allow skill CLIs** 后,已知 Skills 引用的可执行文件会在节点(macOS 节点或无头节点主机)上被视为已加入允许列表。此功能通过 Gateway RPC 使用 -`skills.bins` 获取 skill bin 列表。如果你希望采用严格的手动允许列表,请禁用该功能。 +当启用 **Auto-allow skill CLIs** 时,已知 Skills 引用的可执行文件会在节点上(macOS 节点或无头节点主机)被视为已加入允许列表。此功能会通过 Gateway 网关 RPC 使用 +`skills.bins` 获取 Skills 二进制列表。如果你希望严格使用手动允许列表,请禁用此项。 重要信任说明: -- 这是一个**隐式的便捷允许列表**,独立于手动路径允许列表条目。 -- 它适用于 Gateway 网关与节点处于同一信任边界内的受信任操作员环境。 +- 这是一个**隐式的便捷允许列表**,与手动路径允许列表条目分开。 +- 它适用于 Gateway 网关与节点位于同一信任边界内的受信任操作员环境。 - 如果你需要严格的显式信任,请保持 `autoAllowSkills: false`,并仅使用手动路径允许列表条目。 -## 安全 bin(仅 stdin) +## 安全二进制与审批转发 -`tools.exec.safeBins` 定义了一小组**仅限 stdin** 的二进制程序(例如 `cut`),它们在 allowlist 模式下**无需**显式允许列表条目即可运行。安全 bin 会拒绝位置文件参数和类似路径的 token,因此它们只能处理输入流。应将其视为流过滤器的狭窄快速通道,而不是通用信任列表。 +有关安全二进制(仅 stdin 的快速路径)、解释器绑定细节,以及如何将审批提示转发到 Slack/Discord/Telegram(或将它们作为原生审批客户端运行),请参阅 [Exec approvals — advanced](/zh-CN/tools/exec-approvals-advanced)。 - -**不要**将解释器或运行时二进制程序(例如 `python3`、`node`、 -`ruby`、`bash`、`sh`、`zsh`)添加到 `safeBins`。如果某条命令按设计就能执行代码、执行子命令或读取文件,应优先使用显式允许列表条目,并保持审批提示开启。自定义安全 bin 必须在 `tools.exec.safeBinProfiles.` 中定义显式 profile。 - + -默认安全 bin: +## Control UI 编辑 -[//]: # "SAFE_BIN_DEFAULTS:START" +使用 **Control UI → Nodes → Exec approvals** 卡片来编辑默认值、按智能体划分的覆盖项和允许列表。选择一个作用域(默认值或某个智能体),调整策略, +添加 / 删除允许列表模式,然后点击 **Save**。UI 会显示每个模式的**上次使用**元数据,方便你保持列表整洁。 -`cut`, `uniq`, `head`, `tail`, `tr`, `wc` - -[//]: # "SAFE_BIN_DEFAULTS:END" - -`grep` 和 `sort` 不在默认列表中。如果你选择启用它们,请继续为其非 stdin 工作流保留显式允许列表条目。对于处于安全 bin 模式的 `grep`, -请使用 `-e`/`--regexp` 提供模式;位置模式形式会被拒绝,以防文件操作数通过模糊的位置参数被偷偷带入。 - -### Argv 校验与被拒绝的标志 - -校验仅根据 argv 形态确定,且具有确定性(不检查主机文件系统中是否存在相关路径),这样可防止通过 allow/deny 差异形成文件存在性预言机行为。默认安全 bin 会拒绝面向文件的选项;长选项会按 fail-closed 方式校验(未知标志和含糊缩写都会被拒绝)。 - -按安全 bin profile 划分的被拒绝标志: - -[//]: # "SAFE_BIN_DENIED_FLAGS:START" - -- `grep`: `--dereference-recursive`, `--directories`, `--exclude-from`, `--file`, `--recursive`, `-R`, `-d`, `-f`, `-r` -- `jq`: `--argfile`, `--from-file`, `--library-path`, `--rawfile`, `--slurpfile`, `-L`, `-f` -- `sort`: `--compress-program`, `--files0-from`, `--output`, `--random-source`, `--temporary-directory`, `-T`, `-o` -- `wc`: `--files0-from` - -[//]: # "SAFE_BIN_DENIED_FLAGS:END" - -安全 bin 还会在执行时强制将 argv token 视为**字面文本**(不会进行 glob 展开,也不会展开 `$VARS`)用于仅 stdin 的片段,因此像 `*` 或 `$HOME/...` 这样的模式不能被用来偷偷读取文件。 - -### 受信任的二进制目录 - -安全 bin 必须从受信任的二进制目录解析(系统默认值加上可选的 `tools.exec.safeBinTrustedDirs`)。`PATH` 条目绝不会被自动视为受信任。默认受信任目录有意保持最小:`/bin`、`/usr/bin`。如果你的安全 bin 可执行文件位于包管理器 / 用户路径中(例如 -`/opt/homebrew/bin`、`/usr/local/bin`、`/opt/local/bin`、`/snap/bin`),请将它们显式添加到 `tools.exec.safeBinTrustedDirs`。 - -### Shell 链式调用、包装器和多路复用器 - -当每个顶层片段都满足允许列表要求时,shell 链式调用(`&&`、`||`、`;`)是允许的(包括安全 bin 或 Skills 自动允许)。重定向在 allowlist 模式下仍不受支持。命令替换(`$()` / 反引号)会在 allowlist 解析期间被拒绝,包括双引号内部;如果你需要字面量的 `$()` 文本,请使用单引号。 - -在 macOS 配套应用审批中,包含 shell 控制或展开语法(`&&`、`||`、`;`、`|`、`` ` ``、`$`、`<`、`>`、`(`、`)`)的原始 shell 文本会被视为允许列表未命中,除非 shell 二进制本身已在允许列表中。 - -对于 shell 包装器(`bash|sh|zsh ... -c/-lc`),请求作用域内的 env 覆盖会被缩减为一个小型显式允许列表(`TERM`、`LANG`、`LC_*`、`COLORTERM`、 -`NO_COLOR`、`FORCE_COLOR`)。 - -对于 allowlist 模式下的 `allow-always` 决策,已知分发包装器(`env`、 -`nice`、`nohup`、`stdbuf`、`timeout`)会持久化内部可执行文件路径,而不是包装器路径。Shell 多路复用器(`busybox`、`toybox`)也会以相同方式对 shell applet(`sh`、`ash` 等)进行解包。如果包装器或多路复用器无法被安全解包,则不会自动持久化任何允许列表条目。 - -如果你将 `python3` 或 `node` 等解释器加入允许列表,建议启用 -`tools.exec.strictInlineEval=true`,这样行内 eval 仍然需要显式审批。在严格模式下,`allow-always` 仍可持久化无害的解释器 / 脚本调用,但行内 eval 载体不会被自动持久化。 - -### 安全 bin 与 allowlist 的区别 - -| 主题 | `tools.exec.safeBins` | 允许列表(`exec-approvals.json`) | -| ---------------- | ------------------------------------------------------ | ------------------------------------------------------------ | -| 目标 | 自动允许范围狭窄的 stdin 过滤器 | 显式信任特定可执行文件 | -| 匹配类型 | 可执行文件名 + 安全 bin argv 策略 | 已解析可执行文件路径 glob 模式 | -| 参数范围 | 受安全 bin profile 和字面量 token 规则限制 | 仅匹配路径;其余参数由你自行负责 | -| 典型示例 | `head`、`tail`、`tr`、`wc` | `jq`、`python3`、`node`、`ffmpeg`、自定义 CLI | -| 最佳用途 | 管道中的低风险文本转换 | 任何行为更广泛或具有副作用的工具 | - -配置位置: - -- `safeBins` 来自配置(`tools.exec.safeBins` 或按智能体的 `agents.list[].tools.exec.safeBins`)。 -- `safeBinTrustedDirs` 来自配置(`tools.exec.safeBinTrustedDirs` 或按智能体的 `agents.list[].tools.exec.safeBinTrustedDirs`)。 -- `safeBinProfiles` 来自配置(`tools.exec.safeBinProfiles` 或按智能体的 `agents.list[].tools.exec.safeBinProfiles`)。按智能体的 profile 键会覆盖全局键。 -- allowlist 条目保存在主机本地 `~/.openclaw/exec-approvals.json` 的 `agents..allowlist` 下(或通过 Control UI / `openclaw approvals allowlist ...`)。 -- 当解释器 / 运行时 bin 出现在 `safeBins` 中但没有显式 profile 时,`openclaw security audit` 会发出 `tools.exec.safe_bins_interpreter_unprofiled` 警告。 -- `openclaw doctor --fix` 可以为缺失的自定义 `safeBinProfiles.` 条目生成为 `{}` 脚手架(之后请进行审查并收紧)。解释器 / 运行时 bin 不会被自动生成脚手架。 - -自定义 profile 示例: -__OC_I18N_900005__ -如果你显式选择将 `jq` 加入 `safeBins`,OpenClaw 在安全 bin 模式下仍会拒绝 -`env` 内建,因此 `jq -n env` 不能在没有显式 allowlist 路径或审批提示的情况下转储主机进程环境。 - -## 编辑 Control UI - -使用 **Control UI → Nodes → Exec approvals** 卡片来编辑默认值、按智能体的覆盖项以及允许列表。选择一个作用域(默认值或某个智能体),调整策略,添加 / 移除允许列表模式,然后点击 **Save**。UI 会显示每个模式的 **last used** 元数据,方便你保持列表整洁。 - -目标选择器可选择 **Gateway**(本地审批)或 **Node**。节点必须声明 `system.execApprovals.get/set`(macOS 应用或无头节点主机)。如果某个节点尚未声明执行审批,请直接编辑其本地 +目标选择器可选择 **Gateway**(本地审批)或 **Node**。节点必须声明 `system.execApprovals.get/set`(macOS 应用或无头节点主机)。 +如果某个节点尚未声明执行审批,请直接编辑其本地 `~/.openclaw/exec-approvals.json`。 -CLI:`openclaw approvals` 支持编辑 gateway 或节点(参见 [Approvals CLI](/cli/approvals))。 +CLI:`openclaw approvals` 支持编辑 gateway 或 node(参见 [Approvals CLI](/zh-CN/cli/approvals))。 ## 审批流程 -当需要提示时,gateway 会向操作员客户端广播 `exec.approval.requested`。 -Control UI 和 macOS 应用通过 `exec.approval.resolve` 进行处理,然后 gateway 会将已批准的请求转发到节点主机。 +当需要提示时,Gateway 网关会向操作员客户端广播 `exec.approval.requested`。 +Control UI 和 macOS 应用通过 `exec.approval.resolve` 处理它,然后 Gateway 网关将 +已批准的请求转发到节点主机。 -对于 `host=node`,审批请求会包含一个规范化的 `systemRunPlan` 负载。Gateway 网关在转发已批准的 `system.run` -请求时,会将该计划作为权威的命令 / cwd / 会话上下文。 +对于 `host=node`,审批请求包含规范化的 `systemRunPlan` 负载。Gateway 网关在转发已批准的 `system.run` +请求时,会将该计划作为权威的命令 / `cwd` / 会话上下文。 -这对于异步审批延迟很重要: +这对异步审批延迟很重要: -- 节点 exec 路径会预先准备一个规范计划 +- 节点执行路径会预先准备一个规范化计划 - 审批记录会存储该计划及其绑定元数据 - 一旦获批,最终转发的 `system.run` 调用会复用已存储的计划 - 而不是信任调用方之后的修改 -- 如果调用方在审批请求创建之后更改了 `command`、`rawCommand`、`cwd`、`agentId` 或 - `sessionKey`,Gateway 网关会将该转发执行拒绝为审批不匹配 - -## 解释器 / 运行时命令 - -基于审批的解释器 / 运行时执行有意保持保守: - -- 始终绑定精确的 argv/cwd/env 上下文。 -- 直接 shell 脚本和直接运行时文件形式会尽力绑定到一个具体的本地文件快照。 -- 仍然解析为单个直接本地文件的常见包管理器包装形式(例如 - `pnpm exec`、`pnpm node`、`npm exec`、`npx`)会在绑定前先解包。 -- 如果 OpenClaw 无法为某条解释器 / 运行时命令识别出**唯一一个**具体本地文件 - (例如包脚本、eval 形式、运行时特定的加载器链,或存在歧义的多文件形式), - 则会拒绝基于审批的执行,而不是声称自己覆盖了并不具备的语义。 -- 对于这些工作流,建议优先使用沙箱隔离、单独的主机边界,或显式的受信任 - allowlist/full 工作流,由操作员接受更广泛的运行时语义。 - -当需要审批时,exec 工具会立即返回一个审批 id。使用该 id 关联后续系统事件(`Exec finished` / `Exec denied`)。如果在超时前没有收到决定,请求会被视为审批超时,并作为拒绝原因呈现。 - -### 后续投递行为 - -批准后的异步 exec 完成后,OpenClaw 会向同一会话发送一个后续的 `agent` 轮次。 - -- 如果存在有效的外部投递目标(可投递渠道加目标 `to`),后续投递会使用该渠道。 -- 在仅 webchat 或无外部目标的内部会话流中,后续投递会保持为仅会话(`deliver: false`)。 -- 如果调用方显式请求严格外部投递,但没有可解析的外部渠道,请求会以 `INVALID_REQUEST` 失败。 -- 如果启用了 `bestEffortDeliver` 且无法解析出外部渠道,则投递会降级为仅会话,而不是失败。 - -确认对话框包含: - -- command + args -- cwd -- agent id -- 已解析的可执行文件路径 -- host + 策略元数据 - -操作: - -- **Allow once** → 立即运行 -- **Always allow** → 添加到允许列表 + 运行 -- **Deny** → 阻止 - -## 将审批转发到聊天渠道 - -你可以将 exec 审批提示转发到任意聊天渠道(包括渠道插件),并使用 `/approve` 进行审批。这会使用正常的出站投递流水线。 - -配置: -__OC_I18N_900006__ -在聊天中回复: -__OC_I18N_900007__ -`/approve` 命令同时处理 exec 审批和插件审批。如果该 ID 未匹配任何待处理 exec 审批,它会自动改为检查插件审批。 - -### 插件审批转发 - -插件审批转发使用与 exec 审批相同的投递流水线,但它有独立配置,位于 `approvals.plugin`。启用或禁用其中一个不会影响另一个。 -__OC_I18N_900008__ -配置结构与 `approvals.exec` 完全相同:`enabled`、`mode`、`agentFilter`、 -`sessionFilter` 和 `targets` 的工作方式都一样。 - -支持共享交互式回复的渠道,会为 exec 审批和插件审批渲染相同的审批按钮。不支持共享交互式 UI 的渠道,会回退为带有 `/approve` -说明的纯文本。 - -### 任意渠道中的同一聊天审批 - -当 exec 或插件审批请求来自可投递的聊天界面时,默认情况下,同一聊天现在就可以通过 `/approve` 对其进行审批。这适用于 Slack、Matrix 和 Microsoft Teams 等渠道,以及现有的 Web UI 和终端 UI 流程。 - -这种共享文本命令路径使用该会话的正常渠道认证模型。如果发起聊天本身已经可以发送命令并接收回复,那么审批请求就不再需要单独的原生投递适配器才能保持待处理状态。 - -Discord 和 Telegram 也支持在同一聊天中使用 `/approve`,但即使禁用了原生审批投递,这些渠道在授权时仍会使用其已解析的 approver 列表。 - -对于 Telegram 和其他直接调用 Gateway 网关的原生审批客户端, -这种回退被有意限制在“未找到审批”类失败上。真正的 exec 审批拒绝 / 错误不会被静默重试为插件审批。 - -### 原生审批投递 - -某些渠道还可以充当原生审批客户端。原生客户端会在共享的同一聊天 `/approve` -流程之上,增加 approver 私信、原始聊天扇出以及渠道特定的交互式审批 UX。 - -当原生审批卡片 / 按钮可用时,该原生 UI 是面向智能体的主要路径。 -除非工具结果表明聊天审批不可用,或手动审批是唯一剩余路径,否则智能体不应再额外回显重复的纯聊天 `/approve` 命令。 - -通用模型: - -- 主机 exec 策略仍决定是否需要 exec 审批 -- `approvals.exec` 控制是否将审批提示转发到其他聊天目标 -- `channels..execApprovals` 控制该渠道是否充当原生审批客户端 - -当以下条件全部满足时,原生审批客户端会自动启用“优先私信”投递: - -- 该渠道支持原生审批投递 -- 可以从显式 `execApprovals.approvers` 或该渠道文档记录的回退来源中解析出 approver -- `channels..execApprovals.enabled` 未设置或为 `"auto"` - -将 `enabled: false` 设为显式禁用某个原生审批客户端。将 `enabled: true` 设为在 approver 可解析时强制启用它。公开的原始聊天投递仍通过 -`channels..execApprovals.target` 显式控制。 - -常见问题:[为什么聊天审批会有两个 exec 审批配置?](/help/faq#why-are-there-two-exec-approval-configs-for-chat-approvals) - -- Discord:`channels.discord.execApprovals.*` -- Slack:`channels.slack.execApprovals.*` -- Telegram:`channels.telegram.execApprovals.*` - -这些原生审批客户端在共享的同一聊天 `/approve` 流程和共享审批按钮之上,增加了私信路由和可选的渠道扇出。 - -共享行为: - -- Slack、Matrix、Microsoft Teams 以及类似的可投递聊天,针对同一聊天中的 `/approve` 使用正常的渠道认证模型 -- 当原生审批客户端自动启用时,默认原生投递目标是 approver 私信 -- 对于 Discord 和 Telegram,只有已解析的 approver 才能批准或拒绝 -- Discord approver 可以是显式指定的(`execApprovals.approvers`),也可以从 `commands.ownerAllowFrom` 推断 -- Telegram approver 可以是显式指定的(`execApprovals.approvers`),也可以从现有 owner 配置推断(`allowFrom`,以及在支持时的私信 `defaultTo`) -- Slack approver 可以是显式指定的(`execApprovals.approvers`),也可以从 `commands.ownerAllowFrom` 推断 -- Slack 原生按钮会保留审批 id 类型,因此 `plugin:` id 可以解析到插件审批 - 而不需要第二层 Slack 本地回退逻辑 -- Matrix 原生私信 / 渠道路由和反应快捷方式同时处理 exec 审批和插件审批; - 插件授权仍来自 `channels.matrix.dm.allowFrom` -- 请求者本身不需要是 approver -- 当原始聊天已支持命令和回复时,原始聊天可以直接使用 `/approve` 进行审批 -- 原生 Discord 审批按钮会按审批 id 类型路由:`plugin:` id 会直接进入插件审批,其余全部进入 exec 审批 -- 原生 Telegram 审批按钮遵循与 `/approve` 相同的、受限的 exec 到插件回退逻辑 -- 当原生 `target` 启用原始聊天投递时,审批提示会包含命令文本 -- 待处理 exec 审批默认会在 30 分钟后过期 -- 如果没有操作员 UI 或已配置的审批客户端可以接受该请求,提示会回退到 `askFallback` - -Telegram 默认发送到 approver 私信(`target: "dm"`)。如果你希望审批提示也出现在原始 Telegram 聊天 / 话题中,可以切换为 `channel` 或 `both`。对于 Telegram 论坛话题,OpenClaw 会为审批提示和审批后的后续消息保留该话题。 - -参见: - -- [Discord](/channels/discord) -- [Telegram](/channels/telegram) - -### macOS IPC 流程 -__OC_I18N_900009__ -安全说明: - -- Unix socket 模式 `0600`,token 存储在 `exec-approvals.json` 中。 -- 同一 UID 对等方检查。 -- 质询 / 响应机制(nonce + HMAC token + 请求哈希)+ 短 TTL。 + 而不是信任调用方后续的编辑 +- 如果调用方在创建审批请求后更改了 `command`、`rawCommand`、`cwd`、`agentId` 或 + `sessionKey`,Gateway 网关会将转发执行拒绝为审批不匹配 ## 系统事件 -Exec 生命周期会以系统消息形式呈现: +执行生命周期会以系统消息的形式呈现: -- `Exec running`(仅当命令超过运行提示阈值时) +- `Exec running`(仅当命令超过运行中通知阈值时) - `Exec finished` - `Exec denied` 这些消息会在节点报告事件后发布到智能体的会话中。 -Gateway host 的 exec 审批在命令完成时(以及可选地在运行超过阈值时)会发出相同的生命周期事件。 -受审批门控的 exec 会在这些消息中复用审批 id 作为 `runId`,以便轻松关联。 +Gateway 网关主机执行审批在命令结束时也会发出相同的生命周期事件(如果运行时间超过阈值,也可选发出运行中事件)。 +受审批门控的执行会在这些消息中复用审批 id 作为 `runId`,以便轻松关联。 ## 审批被拒绝时的行为 -当异步 exec 审批被拒绝时,OpenClaw 会阻止智能体复用该会话中此前同一命令任意一次运行的输出。拒绝原因会附带明确说明,指出没有可用的命令输出,从而阻止智能体声称存在新的输出,或使用先前成功运行留下的陈旧结果来重复被拒绝的命令。 +当异步执行审批被拒绝时,OpenClaw 会阻止智能体在会话中复用同一命令任何更早一次运行的输出。拒绝原因会连同明确说明一起传递,指出没有可用的命令输出,从而阻止智能体声称存在新的输出,或在使用先前成功运行留下的陈旧结果时重复被拒绝的命令。 ## 影响 -- **full** 权限很强;尽可能优先使用 allowlist。 -- **ask** 让你保持在决策环路中,同时仍支持快速审批。 -- 按智能体划分的允许列表可防止某个智能体的审批泄漏到其他智能体。 -- 审批仅适用于来自**已授权发送者**的主机 exec 请求。未授权发送者不能发出 `/exec`。 -- `/exec security=full` 是面向已授权操作员的会话级便捷方式,并且按设计会跳过审批。若要硬性阻止主机 exec,请将 approvals security 设为 `deny`,或通过工具策略拒绝 `exec` 工具。 +- **full** 权限很强;尽可能优先使用允许列表。 +- **ask** 可以让你保持知情,同时仍支持快速审批。 +- 按智能体划分的允许列表可以防止某个智能体的审批泄漏到其他智能体。 +- 审批仅适用于来自**已授权发送方**的主机执行请求。未授权发送方无法发出 `/exec`。 +- `/exec security=full` 是面向已授权操作员的会话级便捷方式,并且按设计会跳过审批。要硬性阻止主机执行,请将 approvals security 设为 `deny`,或通过工具策略拒绝 `exec` 工具。 ## 相关内容 + + 安全二进制、解释器绑定,以及向聊天转发审批。 + Shell 命令执行工具。 @@ -539,15 +338,15 @@ Gateway host 的 exec 审批在命令完成时(以及可选地在运行超过 也会跳过审批的紧急放行路径。 - 沙箱模式和工作区访问。 + 沙箱模式与工作区访问。 安全模型与加固。 - 何时使用各类控制方式。 + 何时应使用各类控制方式。 - 基于 Skill 的自动允许行为。 + 基于 Skills 的自动允许行为。 diff --git a/docs/zh-CN/tools/exec.md b/docs/zh-CN/tools/exec.md index 8a8be86f0..cc9146909 100644 --- a/docs/zh-CN/tools/exec.md +++ b/docs/zh-CN/tools/exec.md @@ -5,17 +5,17 @@ read_when: summary: Exec 工具用法、stdin 模式和 TTY 支持 title: Exec 工具 x-i18n: - generated_at: "2026-04-23T23:04:39Z" + generated_at: "2026-04-23T23:21:50Z" model: gpt-5.4 provider: openai - source_hash: 4e2a7fc3b0570d59a6694d0a4ff9def1a5721c8a3d13abf7f947e7ea835535b3 + source_hash: 4cad17fecfaf7d6a523282ef4f0090e4ffaab89ab53945b5cd831e426f3fc3ac source_path: tools/exec.md workflow: 15 --- 在工作区中运行 shell 命令。通过 `process` 支持前台 + 后台执行。 -如果 `process` 被禁止,`exec` 会同步运行,并忽略 `yieldMs`/`background`。 -后台会话按智能体划分作用域;`process` 只能看到同一智能体下的会话。 +如果 `process` 被禁用,`exec` 会同步运行,并忽略 `yieldMs`/`background`。 +后台会话按智能体隔离;`process` 只能看到同一智能体的会话。 ## 参数 @@ -28,31 +28,31 @@ x-i18n: -键/值形式的环境变量覆盖,会合并到继承环境之上。 +叠加到继承环境之上的键/值环境变量覆盖。 -在该延迟(毫秒)后自动将命令转为后台运行。 +在这段延迟(毫秒)后自动将命令转入后台。 -立即将命令置于后台运行,而不是等待 `yieldMs`。 +立即将命令转入后台,而不是等待 `yieldMs`。 -在这么多秒后杀死命令。 +在这么多秒后终止该命令。 -在可用时于伪终端中运行。用于仅支持 TTY 的 CLI、编码智能体和终端 UI。 +在可用时于伪终端中运行。适用于仅支持 TTY 的 CLI、编码智能体和终端 UI。 -执行位置。`auto` 会在沙箱运行时处于活动状态时解析为 `sandbox`,否则解析为 `gateway`。 +执行位置。`auto` 会在当前会话启用了沙箱运行时时解析为 `sandbox`,否则解析为 `gateway`。 -`gateway` / `node` 执行的强制模式。 +`gateway` / `node` 执行的强制策略模式。 @@ -60,48 +60,50 @@ x-i18n: -当 `host=node` 时使用的节点 id/name。 +当 `host=node` 时使用的节点 id/名称。 -请求提权模式 —— 从沙箱逃逸到已配置的宿主路径。只有当 elevated 最终解析为 `full` 时,才会强制 `security=full`。 +请求提升模式——跳出沙箱并切换到已配置的主机路径。只有当 elevated 解析为 `full` 时,才会强制 `security=full`。 说明: -- `host` 默认为 `auto`:当会话的沙箱运行时处于活动状态时为 sandbox,否则为 gateway。 -- `auto` 是默认路由策略,不是通配符。单次调用时允许从 `auto` 切换到 `host=node`;只有在没有活动沙箱运行时时,才允许单次调用 `host=gateway`。 -- 在没有额外配置的情况下,`host=auto` 仍然“开箱即用”:没有沙箱时会解析为 `gateway`;有活动沙箱时则保持在沙箱内。 -- `elevated` 会从沙箱逃逸到已配置的宿主路径:默认是 `gateway`,或者当 `tools.exec.host=node`(或会话默认值为 `host=node`)时为 `node`。它仅在当前会话/provider 启用了提权访问时可用。 -- `gateway`/`node` 审批由 `~/.openclaw/exec-approvals.json` 控制。 -- `node` 需要一个已配对的节点(配套应用或无头节点宿主)。 +- `host` 默认为 `auto`:当会话启用了沙箱运行时时为 `sandbox`,否则为 `gateway`。 +- `auto` 是默认路由策略,不是通配符。在 `auto` 下,每次调用都允许 `host=node`;只有在当前没有启用沙箱运行时时,每次调用才允许 `host=gateway`。 +- 不做额外配置时,`host=auto` 依然能够“开箱即用”:没有沙箱时,它会解析为 `gateway`;存在活动沙箱时,它会保留在沙箱中。 +- `elevated` 会跳出沙箱并切换到已配置的主机路径:默认是 `gateway`,或者当 `tools.exec.host=node`(或会话默认值是 `host=node`)时为 `node`。只有当前会话/提供商启用了提升访问时,此选项才可用。 +- `gateway`/`node` 的审批由 `~/.openclaw/exec-approvals.json` 控制。 +- `node` 需要一个已配对的节点(配套应用或无头节点主机)。 - 如果有多个节点可用,请设置 `exec.node` 或 `tools.exec.node` 来选择其中一个。 - `exec host=node` 是节点唯一的 shell 执行路径;旧版 `nodes.run` 包装器已移除。 -- 在非 Windows 宿主上,exec 会在设置了 `SHELL` 时使用它;如果 `SHELL` 是 `fish`,它会优先使用 `PATH` 中的 `bash`(或 `sh`),以避免 fish 不兼容脚本,然后在两者都不存在时回退到 `SHELL`。 -- 在 Windows 宿主上,exec 会优先发现 PowerShell 7(依次检查 Program Files、ProgramW6432、然后 PATH),然后回退到 Windows PowerShell 5.1。 -- 宿主执行(`gateway`/`node`)会拒绝 `env.PATH` 和加载器覆盖(`LD_*`/`DYLD_*`),以防止二进制劫持或注入代码。 -- OpenClaw 会在生成的命令环境中设置 `OPENCLAW_SHELL=exec`(包括 PTY 和沙箱执行),以便 shell/profile 规则检测 exec 工具上下文。 -- 重要:沙箱隔离默认**关闭**。如果沙箱隔离关闭,隐式 `host=auto` 会解析为 `gateway`。显式 `host=sandbox` 仍会以失败关闭方式处理,而不是静默地在 gateway 宿主上运行。请启用沙箱隔离,或在审批下使用 `host=gateway`。 -- 脚本预检(用于检测常见 Python/Node shell 语法错误)只会检查有效 `workdir` 边界内的文件。如果脚本路径解析到 `workdir` 之外,则会跳过该文件的预检。 -- 对于从现在开始的长时间运行工作,请启动一次,然后依赖启用后的自动完成唤醒机制,当命令输出内容或失败时唤醒。日志、状态、输入或人工干预请使用 `process`;不要用 sleep 循环、timeout 循环或重复轮询来模拟调度。 -- 对于应在稍后执行或按计划执行的工作,请使用 cron,而不是 `exec` 的 sleep/延迟模式。 +- 在非 Windows 主机上,exec 会优先使用已设置的 `SHELL`;如果 `SHELL` 是 `fish`,它会优先从 `PATH` 中选择 `bash`(或 `sh`)以避免与 fish 不兼容的脚本问题;如果两者都不存在,才会回退到 `SHELL`。 +- 在 Windows 主机上,exec 会优先发现 PowerShell 7(Program Files、ProgramW6432,然后是 PATH),然后回退到 Windows PowerShell 5.1。 +- 主机执行(`gateway`/`node`)会拒绝 `env.PATH` 和加载器覆盖(`LD_*`/`DYLD_*`),以防止二进制劫持或注入代码。 +- OpenClaw 会在生成的命令环境中设置 `OPENCLAW_SHELL=exec`(包括 PTY 和沙箱执行),以便 shell/profile 规则识别 exec 工具上下文。 +- 重要:默认情况下,沙箱隔离是**关闭**的。如果沙箱隔离关闭,隐式 `host=auto` 会解析为 `gateway`。显式 `host=sandbox` 仍会以关闭失败的方式处理,而不是静默在 Gateway 网关主机上运行。请启用沙箱隔离,或结合审批使用 `host=gateway`。 +- 脚本预检(用于发现常见的 Python/Node shell 语法错误)只会检查有效 `workdir` 边界内的文件。如果脚本路径解析到 `workdir` 之外,则会跳过该文件的预检。 +- 对于现在开始的长时间运行任务,只需启动一次,并在启用了自动完成唤醒且命令输出内容或失败时依赖自动唤醒。 + 使用 `process` 处理日志、状态、输入或干预;不要用 sleep 循环、timeout 循环或重复轮询来模拟调度。 +- 对于应稍后执行或按计划执行的任务,请使用 cron,而不是 + `exec` 的 sleep/delay 模式。 ## 配置 -- `tools.exec.notifyOnExit`(默认:true):为 true 时,后台 exec 会话会在退出时排入一个系统事件并请求 heartbeat。 -- `tools.exec.approvalRunningNoticeMs`(默认:10000):当需要审批的 exec 运行时间超过该值时,发出一次“running”通知(设为 0 可禁用)。 +- `tools.exec.notifyOnExit`(默认:true):为 true 时,已后台化的 exec 会话在退出时会入队一个系统事件并请求一次 heartbeat。 +- `tools.exec.approvalRunningNoticeMs`(默认:10000):当需要审批的 exec 运行超过该时长时发出一次“正在运行”通知(设为 0 可禁用)。 - `tools.exec.host`(默认:`auto`;当沙箱运行时处于活动状态时解析为 `sandbox`,否则为 `gateway`) -- `tools.exec.security`(默认:sandbox 为 `deny`,gateway + node 在未设置时为 `full`) +- `tools.exec.security`(默认:沙箱为 `deny`,未设置时 gateway + node 为 `full`) - `tools.exec.ask`(默认:`off`) -- 无审批的宿主 exec 是 gateway + node 的默认行为。如果你希望启用审批/允许列表行为,请同时收紧 `tools.exec.*` 和宿主 `~/.openclaw/exec-approvals.json`;参见[Exec 审批](/zh-CN/tools/exec-approvals#no-approval-yolo-mode)。 -- YOLO 来自宿主策略默认值(`security=full`、`ask=off`),而不是来自 `host=auto`。如果你想强制使用 gateway 或 node 路由,请设置 `tools.exec.host` 或使用 `/exec host=...`。 -- 在 `security=full` 加 `ask=off` 模式下,宿主 exec 会直接遵循已配置策略;没有额外的启发式命令混淆预过滤器,也没有脚本预检拒绝层。 +- 对 gateway + node 来说,默认是无需审批的主机 exec。如果你想启用审批/allowlist 行为,请同时收紧 `tools.exec.*` 和主机上的 `~/.openclaw/exec-approvals.json`;参见 [Exec 审批](/zh-CN/tools/exec-approvals#no-approval-yolo-mode)。 +- YOLO 来自主机策略默认值(`security=full`、`ask=off`),而不是 `host=auto`。如果你想强制使用 gateway 或 node 路由,请设置 `tools.exec.host` 或使用 `/exec host=...`。 +- 在 `security=full` 加 `ask=off` 模式下,主机 exec 会直接遵循已配置的策略;不会额外增加启发式命令混淆预过滤器或脚本预检拒绝层。 - `tools.exec.node`(默认:未设置) -- `tools.exec.strictInlineEval`(默认:false):为 true 时,内联解释器 eval 形式,例如 `python -c`、`node -e`、`ruby -e`、`perl -e`、`php -r`、`lua -e` 和 `osascript -e`,始终需要显式审批。`allow-always` 仍可持久信任无害的解释器/脚本调用,但内联 eval 形式每次仍会提示。 -- `tools.exec.pathPrepend`:在 exec 运行前追加到 `PATH` 前部的目录列表(仅 gateway + sandbox)。 -- `tools.exec.safeBins`:无需显式允许列表条目的仅 stdin 安全二进制文件。有关行为细节,请参见[Safe bins](/zh-CN/tools/exec-approvals#safe-bins-stdin-only)。 -- `tools.exec.safeBinTrustedDirs`:为 `safeBins` 路径检查显式信任的额外目录。`PATH` 条目不会被自动信任。内置默认值为 `/bin` 和 `/usr/bin`。 -- `tools.exec.safeBinProfiles`:为自定义 safe bin 提供可选的 argv 策略(`minPositional`、`maxPositional`、`allowedValueFlags`、`deniedFlags`)。 +- `tools.exec.strictInlineEval`(默认:false):为 true 时,内联解释器求值形式,如 `python -c`、`node -e`、`ruby -e`、`perl -e`、`php -r`、`lua -e` 和 `osascript -e`,始终需要显式审批。`allow-always` 仍可持久放行无害的解释器/脚本调用,但内联求值形式每次仍会提示。 +- `tools.exec.pathPrepend`:在 exec 运行时预置到 `PATH` 前部的目录列表(仅 gateway + sandbox)。 +- `tools.exec.safeBins`:仅通过 stdin 使用、可在无需显式 allowlist 条目的情况下运行的安全二进制。有关行为细节,请参见 [Safe bins](/zh-CN/tools/exec-approvals-advanced#safe-bins-stdin-only)。 +- `tools.exec.safeBinTrustedDirs`:用于 `safeBins` 路径检查的额外显式可信目录。`PATH` 条目永远不会被自动信任。内置默认值为 `/bin` 和 `/usr/bin`。 +- `tools.exec.safeBinProfiles`:可选的每个 safe bin 自定义 argv 策略(`minPositional`、`maxPositional`、`allowedValueFlags`、`deniedFlags`)。 示例: @@ -117,11 +119,13 @@ x-i18n: ### PATH 处理 -- `host=gateway`:将你的登录 shell `PATH` 合并到 exec 环境中。宿主执行会拒绝 `env.PATH` 覆盖。守护进程本身仍以最小化 `PATH` 运行: +- `host=gateway`:将你的登录 shell `PATH` 合并进 exec 环境。主机执行会拒绝 `env.PATH` 覆盖。守护进程本身仍以最小化 `PATH` 运行: - macOS:`/opt/homebrew/bin`、`/usr/local/bin`、`/usr/bin`、`/bin` - Linux:`/usr/local/bin`、`/usr/bin`、`/bin` -- `host=sandbox`:在容器内运行 `sh -lc`(登录 shell),因此 `/etc/profile` 可能会重置 `PATH`。OpenClaw 会在 profile sourcing 之后通过内部环境变量将 `env.PATH` 追加到前面(不使用 shell 插值);`tools.exec.pathPrepend` 在这里同样生效。 -- `host=node`:只有你传入的未被阻止的环境变量覆盖会发送到节点。宿主执行会拒绝 `env.PATH` 覆盖,节点宿主也会忽略它。如果你需要在节点上添加更多 PATH 条目,请配置节点宿主服务环境(systemd/launchd),或将工具安装到标准位置。 +- `host=sandbox`:在容器内运行 `sh -lc`(登录 shell),因此 `/etc/profile` 可能会重置 `PATH`。 + OpenClaw 会在 profile 加载之后通过内部环境变量将 `env.PATH` 预置到前部(不进行 shell 插值);`tools.exec.pathPrepend` 在这里同样适用。 +- `host=node`:只有你传入的、未被拦截的环境覆盖会被发送到节点。主机执行会拒绝 `env.PATH` 覆盖,而节点主机也会忽略它。如果你需要在节点上添加额外的 PATH 条目, + 请配置节点主机服务环境(systemd/launchd),或将工具安装到标准位置。 按智能体绑定节点(在配置中使用智能体列表索引): @@ -130,12 +134,12 @@ openclaw config get agents.list openclaw config set agents.list[0].tools.exec.node "node-id-or-name" ``` -控制 UI:Nodes 标签页中包含一个小型“Exec 节点绑定”面板,用于配置相同设置。 +控制 UI:Nodes 选项卡包含一个小型“Exec 节点绑定”面板,用于设置相同的配置。 ## 会话覆盖(`/exec`) -使用 `/exec` 为 `host`、`security`、`ask` 和 `node` 设置**按会话**默认值。 -不带参数发送 `/exec` 可显示当前值。 +使用 `/exec` 设置**按会话生效**的 `host`、`security`、`ask` 和 `node` 默认值。 +发送不带参数的 `/exec` 可显示当前值。 示例: @@ -145,62 +149,69 @@ openclaw config set agents.list[0].tools.exec.node "node-id-or-name" ## 授权模型 -`/exec` 仅对**已授权发送者**生效(渠道允许列表/配对加上 `commands.useAccessGroups`)。 -它只会更新**会话状态**,不会写入配置。若要硬禁用 exec,请通过工具策略拒绝它(`tools.deny: ["exec"]` 或按智能体配置)。 -除非你显式设置 `security=full` 且 `ask=off`,否则宿主审批仍会生效。 +`/exec` 仅对**已授权的发送方**生效(渠道 allowlist/配对 + `commands.useAccessGroups`)。 +它只更新**会话状态**,不会写入配置。若要彻底禁用 exec,请通过工具 +策略拒绝它(`tools.deny: ["exec"]` 或按智能体配置)。除非你显式设置 +`security=full` 且 `ask=off`,否则主机审批仍然适用。 -## Exec 审批(配套应用 / 节点宿主) +## Exec 审批(配套应用 / 节点主机) -沙箱隔离智能体可以要求在 `exec` 于 gateway 或节点宿主上运行前进行逐次请求审批。 -有关策略、允许列表和 UI 流程,请参见[Exec 审批](/zh-CN/tools/exec-approvals)。 +处于沙箱隔离中的智能体可以要求在 exec 在 Gateway 网关或节点主机上运行前进行逐次请求审批。 +有关策略、allowlist 和 UI 流程,请参见 [Exec 审批](/zh-CN/tools/exec-approvals)。 当需要审批时,exec 工具会立即返回, -`status: "approval-pending"` 和一个审批 id。一旦审批通过(或被拒绝 / 超时),Gateway 网关会发出系统事件(`Exec finished` / `Exec denied`)。如果命令在 `tools.exec.approvalRunningNoticeMs` 之后仍在运行,则会发出一次 `Exec running` 通知。 -在支持原生审批卡片/按钮的渠道上,智能体应首先依赖该原生 UI,仅当工具结果明确说明聊天审批不可用,或手动审批是唯一途径时,才附带手动 `/approve` 命令。 +其中包含 `status: "approval-pending"` 和一个审批 id。一旦获得批准(或被拒绝 / 超时), +Gateway 网关会发出系统事件(`Exec finished` / `Exec denied`)。如果命令在 +`tools.exec.approvalRunningNoticeMs` 之后仍在运行,则会发出一次 `Exec running` 通知。 +在原生支持审批卡片/按钮的渠道上,智能体应优先依赖该 +原生 UI,只有当工具结果明确指出聊天审批不可用或手动审批是唯一 +途径时,才应包含手动 `/approve` 命令。 ## Allowlist + safe bins -手动允许列表强制只匹配**解析后的二进制路径**(不支持仅按 basename 匹配)。当 -`security=allowlist` 时,只有在每个管道片段都在允许列表中或属于 safe bin 的情况下,shell 命令才会被自动允许。链式命令(`;`、`&&`、`||`)和重定向在 -allowlist 模式下会被拒绝,除非每个顶层片段都满足允许列表条件(包括 safe bin)。 -重定向仍然不受支持。 -持久化的 `allow-always` 信任也不会绕过此规则:链式命令仍要求每个顶层片段都匹配。 +手动 allowlist 强制仅匹配**解析后的二进制路径**(不匹配 basename)。当 +`security=allowlist` 时,只有当管道中的每个片段都在 +allowlist 中或属于 safe bin 时,shell 命令才会被自动允许。 +在 allowlist 模式下,链式命令(`;`、`&&`、`||`)和重定向会被拒绝,除非每个顶层片段都满足 allowlist 要求(包括 safe bins)。 +重定向仍不受支持。 +持久化的 `allow-always` 信任也不会绕过这条规则:链式命令仍然要求每个 +顶层片段都匹配。 -`autoAllowSkills` 是 exec 审批中的一条单独的便捷路径。它不同于 -手动路径允许列表条目。若要实现严格的显式信任,请保持 -`autoAllowSkills` 关闭。 +`autoAllowSkills` 是 exec 审批中的另一种便捷路径。它不同于 +手动路径 allowlist 条目。若要实行严格的显式信任,请保持 +`autoAllowSkills` 为禁用状态。 -请将这两个控制项用于不同任务: +请将这两种控制分别用于不同场景: -- `tools.exec.safeBins`:小型、仅 stdin 的流过滤二进制文件。 -- `tools.exec.safeBinTrustedDirs`:为 safe-bin 可执行路径显式信任的额外目录。 -- `tools.exec.safeBinProfiles`:为自定义 safe bin 提供显式 argv 策略。 +- `tools.exec.safeBins`:小型、仅 stdin 的流过滤二进制。 +- `tools.exec.safeBinTrustedDirs`:用于 safe-bin 可执行路径的显式额外可信目录。 +- `tools.exec.safeBinProfiles`:用于自定义 safe bin 的显式 argv 策略。 - allowlist:对可执行路径的显式信任。 -不要将 `safeBins` 视为通用允许列表,也不要添加解释器/运行时二进制文件(例如 `python3`、`node`、`ruby`、`bash`)。如果你需要这些,请使用显式允许列表条目,并保持审批提示开启。 -当解释器/运行时 `safeBins` 条目缺少显式 profiles 时,`openclaw security audit` 会发出警告,而 `openclaw doctor --fix` 可为缺失的自定义 `safeBinProfiles` 条目生成脚手架。 -当你显式将 `jq` 这类宽行为二进制文件重新加入 `safeBins` 时,`openclaw security audit` 和 `openclaw doctor` 也会发出警告。 -如果你显式允许列表解释器,请启用 `tools.exec.strictInlineEval`,以便内联代码 eval 形式仍需重新审批。 +不要把 `safeBins` 当作通用 allowlist,也不要添加解释器/运行时二进制(例如 `python3`、`node`、`ruby`、`bash`)。如果你需要这些,请使用显式 allowlist 条目,并保持审批提示启用。 +当解释器/运行时的 `safeBins` 条目缺少显式 profile 时,`openclaw security audit` 会发出警告,`openclaw doctor --fix` 可以为缺失的自定义 `safeBinProfiles` 条目生成脚手架。 +如果你明确将像 `jq` 这样行为范围较广的二进制重新加入 `safeBins`,`openclaw security audit` 和 `openclaw doctor` 也会发出警告。 +如果你显式 allowlist 了解释器,请启用 `tools.exec.strictInlineEval`,这样内联代码求值形式仍然需要新的审批。 -有关完整策略细节和示例,请参见[Exec 审批](/zh-CN/tools/exec-approvals#safe-bins-stdin-only)和[Safe bins versus allowlist](/zh-CN/tools/exec-approvals#safe-bins-versus-allowlist)。 +有关完整策略细节和示例,请参见 [Exec 审批](/zh-CN/tools/exec-approvals-advanced#safe-bins-stdin-only) 和 [Safe bins 与 allowlist 的区别](/zh-CN/tools/exec-approvals-advanced#safe-bins-versus-allowlist)。 ## 示例 -前台: +前台执行: ```json { "tool": "exec", "command": "ls -la" } ``` -后台 + 轮询: +后台执行 + 轮询: ```json {"tool":"exec","command":"npm run build","yieldMs":1000} {"tool":"process","action":"poll","sessionId":""} ``` -轮询用于按需查看状态,而不是等待循环。如果启用了自动完成唤醒, -命令可以在输出内容或失败时唤醒会话。 +轮询用于按需查看状态,而不是用于等待循环。如果启用了自动完成唤醒, +当命令输出内容或失败时,它可以唤醒会话。 发送按键(tmux 风格): @@ -225,7 +236,7 @@ allowlist 模式下会被拒绝,除非每个顶层片段都满足允许列表 ## apply_patch `apply_patch` 是 `exec` 的一个子工具,用于结构化的多文件编辑。 -对于 OpenAI 和 OpenAI Codex 模型,它默认启用。只有在你想禁用它或将其限制为特定模型时,才需要使用配置: +对于 OpenAI 和 OpenAI Codex 模型,它默认启用。只有在你想禁用它或将其限制到特定模型时,才需要使用配置: ```json5 { @@ -242,12 +253,12 @@ allowlist 模式下会被拒绝,除非每个顶层片段都满足允许列表 - 仅适用于 OpenAI/OpenAI Codex 模型。 - 工具策略仍然适用;`allow: ["write"]` 会隐式允许 `apply_patch`。 - 配置位于 `tools.exec.applyPatch` 下。 -- `tools.exec.applyPatch.enabled` 默认值为 `true`;设置为 `false` 可为 OpenAI 模型禁用该工具。 -- `tools.exec.applyPatch.workspaceOnly` 默认值为 `true`(仅限工作区内)。只有在你明确希望 `apply_patch` 在工作区目录之外写入/删除时,才将其设为 `false`。 +- `tools.exec.applyPatch.enabled` 默认为 `true`;如果要为 OpenAI 模型禁用该工具,请将其设为 `false`。 +- `tools.exec.applyPatch.workspaceOnly` 默认为 `true`(限制在工作区内)。只有当你明确希望 `apply_patch` 在工作区目录之外执行写入/删除时,才将其设为 `false`。 ## 相关内容 -- [Exec 审批](/zh-CN/tools/exec-approvals) — shell 命令的审批门禁 +- [Exec 审批](/zh-CN/tools/exec-approvals) — shell 命令的审批门控 - [沙箱隔离](/zh-CN/gateway/sandboxing) — 在沙箱隔离环境中运行命令 - [后台进程](/zh-CN/gateway/background-process) — 长时间运行的 exec 和 process 工具 -- [安全性](/zh-CN/gateway/security) — 工具策略和提权访问 +- [安全](/zh-CN/gateway/security) — 工具策略和提升访问 diff --git a/docs/zh-CN/tools/image-generation.md b/docs/zh-CN/tools/image-generation.md index 7fc1035c4..9f3181f2b 100644 --- a/docs/zh-CN/tools/image-generation.md +++ b/docs/zh-CN/tools/image-generation.md @@ -6,23 +6,23 @@ read_when: summary: 使用已配置的提供商生成和编辑图像(OpenAI、OpenAI Codex OAuth、Google Gemini、fal、MiniMax、ComfyUI、Vydra、xAI) title: 图像生成 x-i18n: - generated_at: "2026-04-23T23:04:52Z" + generated_at: "2026-04-23T23:22:30Z" model: gpt-5.4 provider: openai - source_hash: 820829a009d48ccb23fbd9ee256bae27f6d7d9539fd75c2b0a7cef4b91c5c873 + source_hash: 81d06d2be0d347be2aec54b02037c85fa4dcf71ccbc3c1b5d0aacac0b58892da source_path: tools/image-generation.md workflow: 15 --- -`image_generate` 工具允许智能体使用你已配置的提供商来生成和编辑图像。生成的图像会自动作为媒体附件附加在智能体的回复中。 +`image_generate` 工具允许智能体使用你已配置的提供商来创建和编辑图像。生成的图像会作为媒体附件自动随智能体的回复一起发送。 -只有当至少有一个图像生成提供商可用时,该工具才会出现。如果你在智能体工具中看不到 `image_generate`,请配置 `agents.defaults.imageGenerationModel`、设置提供商 API 密钥,或使用 OpenAI Codex OAuth 登录。 +只有在至少有一个图像生成提供商可用时,该工具才会显示。如果你在智能体工具中看不到 `image_generate`,请配置 `agents.defaults.imageGenerationModel`、设置提供商 API key,或使用 OpenAI Codex OAuth 登录。 ## 快速开始 -1. 为至少一个提供商设置 API 密钥(例如 `OPENAI_API_KEY` 或 `GEMINI_API_KEY`),或使用 OpenAI Codex OAuth 登录。 +1. 为至少一个提供商设置 API key(例如 `OPENAI_API_KEY` 或 `GEMINI_API_KEY`),或使用 OpenAI Codex OAuth 登录。 2. 可选:设置你偏好的模型: ```json5 @@ -37,26 +37,26 @@ x-i18n: } ``` -Codex OAuth 使用相同的 `openai/gpt-image-2` 模型引用。当 -配置了 `openai-codex` OAuth 配置文件时,OpenClaw 会通过该 OAuth 配置文件路由图像请求,而不是优先尝试 `OPENAI_API_KEY`。 -如果显式配置了自定义 `models.providers.openai` 图像设置,例如 API 密钥或 -自定义 / Azure base URL,则会重新切换回直接 OpenAI Images API 路径。 +Codex OAuth 使用相同的 `openai/gpt-image-2` 模型引用。当配置了 +`openai-codex` OAuth 配置文件时,OpenClaw 会通过该 OAuth 配置文件路由图像请求,而不是优先尝试 `OPENAI_API_KEY`。 +显式配置自定义的 `models.providers.openai` 图像设置(例如 API key 或 +自定义 / Azure base URL)会切回直接使用 OpenAI Images API 路由。 -3. 让智能体执行:_“生成一个友好的机器人吉祥物图像。”_ +3. 向智能体发出请求:_“生成一张友好机器人吉祥物的图像。”_ -智能体会自动调用 `image_generate`。不需要工具允许列表——当提供商可用时它默认启用。 +智能体会自动调用 `image_generate`。无需设置工具允许列表——只要有可用提供商,它默认启用。 ## 支持的提供商 -| 提供商 | 默认模型 | 编辑支持 | Auth | -| -------- | -------------------------------- | ---------------------------------- | ----------------------------------------------------- | -| OpenAI | `gpt-image-2` | 是(最多 4 张图像) | `OPENAI_API_KEY` 或 OpenAI Codex OAuth | -| Google | `gemini-3.1-flash-image-preview` | 是 | `GEMINI_API_KEY` 或 `GOOGLE_API_KEY` | -| fal | `fal-ai/flux/dev` | 是 | `FAL_KEY` | -| MiniMax | `image-01` | 是(主体参考) | `MINIMAX_API_KEY` 或 MiniMax OAuth(`minimax-portal`) | -| ComfyUI | `workflow` | 是(1 张图像,由工作流配置) | `COMFY_API_KEY` 或云端环境下的 `COMFY_CLOUD_API_KEY` | -| Vydra | `grok-imagine` | 否 | `VYDRA_API_KEY` | -| xAI | `grok-imagine-image` | 是(最多 5 张图像) | `XAI_API_KEY` | +| 提供商 | 默认模型 | 编辑支持 | 认证方式 | +| ------ | -------------------------------- | ---------------------------------- | ------------------------------------------------------- | +| OpenAI | `gpt-image-2` | 是(最多 4 张图像) | `OPENAI_API_KEY` 或 OpenAI Codex OAuth | +| Google | `gemini-3.1-flash-image-preview` | 是 | `GEMINI_API_KEY` 或 `GOOGLE_API_KEY` | +| fal | `fal-ai/flux/dev` | 是 | `FAL_KEY` | +| MiniMax | `image-01` | 是(主体参考) | `MINIMAX_API_KEY` 或 MiniMax OAuth(`minimax-portal`) | +| ComfyUI | `workflow` | 是(1 张图像,由 workflow 配置) | 云端使用 `COMFY_API_KEY` 或 `COMFY_CLOUD_API_KEY` | +| Vydra | `grok-imagine` | 否 | `VYDRA_API_KEY` | +| xAI | `grok-imagine-image` | 是(最多 5 张图像) | `XAI_API_KEY` | 使用 `action: "list"` 可在运行时检查可用的提供商和模型: @@ -79,11 +79,11 @@ Codex OAuth 使用相同的 `openai/gpt-image-2` 模型引用。当 -用于编辑模式的单个参考图像路径或 URL。 +编辑模式下的单个参考图像路径或 URL。 -用于编辑模式的多个参考图像(最多 5 个)。 +编辑模式下的多个参考图像(最多 5 张)。 @@ -98,17 +98,33 @@ Codex OAuth 使用相同的 `openai/gpt-image-2` 模型引用。当 分辨率提示。 + +当提供商支持时使用的质量提示。 + + + +当提供商支持时使用的输出格式提示。 + + 要生成的图像数量(1–4)。 + +可选的提供商请求超时时间(毫秒)。 + + 输出文件名提示。 -并非所有提供商都支持所有参数。当某个回退提供商支持接近的几何选项,但不支持你精确请求的值时,OpenClaw 会在提交前重映射到最接近的受支持尺寸、宽高比或分辨率。真正不受支持的覆盖项仍会在工具结果中报告。 + +仅适用于 OpenAI 的提示:`background`、`moderation`、`outputCompression` 和 `user`。 + -工具结果会报告实际应用的设置。当 OpenClaw 在提供商回退期间重映射几何参数时,返回的 `size`、`aspectRatio` 和 `resolution` 值会反映实际发送的内容,而 `details.normalization` 会记录从请求值到应用值的转换。 +并非所有提供商都支持所有参数。当回退提供商支持接近的几何选项而不是精确请求值时,OpenClaw 会在提交前重新映射到最接近的受支持尺寸、宽高比或分辨率。不受支持的输出提示(如 `quality` 或 `outputFormat`)会在不声明支持这些能力的提供商中被丢弃,并在工具结果中报告。 + +工具结果会报告实际应用的设置。当 OpenClaw 在提供商回退期间重映射几何参数时,返回的 `size`、`aspectRatio` 和 `resolution` 值反映的是实际发送的内容,而 `details.normalization` 会记录从请求值到应用值的转换。 ## 配置 @@ -131,52 +147,71 @@ Codex OAuth 使用相同的 `openai/gpt-image-2` 模型引用。当 生成图像时,OpenClaw 会按以下顺序尝试提供商: -1. 工具调用中的 **`model` 参数**(如果智能体指定了它) +1. 工具调用中的 **`model` 参数**(如果智能体指定了) 2. 配置中的 **`imageGenerationModel.primary`** -3. 按顺序尝试 **`imageGenerationModel.fallbacks`** -4. **自动检测**——仅使用带 auth 支持的提供商默认值: - - 先尝试当前默认提供商 - - 然后按提供商 ID 顺序尝试其余已注册图像生成提供商 +3. 按顺序使用 **`imageGenerationModel.fallbacks`** +4. **自动检测**——仅使用有认证支持的提供商默认值: + - 当前默认提供商优先 + - 其余已注册的图像生成提供商按 provider-id 顺序排列 -如果某个提供商失败(auth 错误、速率限制等),系统会自动尝试下一个候选项。如果全部失败,错误信息中会包含每次尝试的详细信息。 +如果某个提供商失败(认证错误、速率限制等),系统会自动尝试下一个候选项。如果全部失败,错误信息会包含每次尝试的详细信息。 说明: -- 自动检测具备 auth 感知能力。只有当 OpenClaw 实际可以对某个提供商进行身份验证时,该提供商默认值才会进入候选列表。 -- 默认启用自动检测。如果你希望图像生成只使用显式的 `model`、`primary` 和 `fallbacks` 条目,请设置 +- 自动检测具备认证感知能力。只有当 OpenClaw 实际能够对某个提供商完成认证时,该提供商默认值才会进入候选列表。 +- 自动检测默认启用。如果你希望图像生成仅使用显式的 `model`、`primary` 和 `fallbacks` 条目,请设置 `agents.defaults.mediaGenerationAutoProviderFallback: false`。 -- 使用 `action: "list"` 可以检查当前已注册的提供商、它们的默认模型以及 auth 环境变量提示。 +- 使用 `action: "list"` 可检查当前注册的提供商、它们的默认模型以及认证环境变量提示。 ### 图像编辑 OpenAI、Google、fal、MiniMax、ComfyUI 和 xAI 支持编辑参考图像。传入参考图像路径或 URL: ``` -"Generate a watercolor version of this photo" + image: "/path/to/photo.jpg" +"把这张照片生成为水彩风格版本" + image: "/path/to/photo.jpg" ``` OpenAI、Google 和 xAI 通过 `images` 参数最多支持 5 张参考图像。fal、MiniMax 和 ComfyUI 支持 1 张。 ### OpenAI `gpt-image-2` -OpenAI 图像生成默认使用 `openai/gpt-image-2`。如果配置了 -`openai-codex` OAuth 配置文件,OpenClaw 会复用与 Codex 订阅聊天模型相同的 OAuth 配置文件,并通过 Codex Responses 后端发送图像请求;它不会为该请求静默回退到 `OPENAI_API_KEY`。 -如需强制使用直接 OpenAI Images API 路由,请显式配置 -`models.providers.openai`,并设置 API 密钥、自定义 base URL -或 Azure 端点。较旧的 +OpenAI 图像生成默认使用 `openai/gpt-image-2`。如果已配置 +`openai-codex` OAuth 配置文件,OpenClaw 会复用 Codex 订阅聊天模型所使用的同一 OAuth 配置文件,并通过 Codex Responses 后端发送图像请求;它不会在该请求中静默回退到 +`OPENAI_API_KEY`。如需强制使用直接的 OpenAI Images API 路由,请显式配置 +`models.providers.openai`,例如设置 API key、自定义 base URL 或 Azure endpoint。较旧的 `openai/gpt-image-1` 模型仍可显式选择,但新的 OpenAI 图像生成和图像编辑请求应使用 `gpt-image-2`。 `gpt-image-2` 通过同一个 `image_generate` 工具同时支持文生图生成和参考图像编辑。OpenClaw 会将 `prompt`、 -`count`、`size` 和参考图像转发给 OpenAI。OpenAI 不会直接接收 -`aspectRatio` 或 `resolution`;在可能的情况下,OpenClaw 会将它们映射为受支持的 `size`,否则工具会将它们报告为被忽略的覆盖项。 +`count`、`size`、`quality`、`outputFormat` 和参考图像转发给 OpenAI。 +OpenAI 不会直接接收 `aspectRatio` 或 `resolution`;在可能的情况下, +OpenClaw 会将它们映射为受支持的 `size`,否则工具会将其报告为被忽略的覆盖项。 -生成一张 4K 横版图像: +OpenAI 专用选项位于 `openai` 对象下: + +```json +{ + "quality": "low", + "outputFormat": "jpeg", + "openai": { + "background": "opaque", + "moderation": "low", + "outputCompression": 60, + "user": "end-user-42" + } +} +``` + +`openai.background` 接受 `transparent`、`opaque` 或 `auto`;透明输出要求 +`outputFormat` 为 `png` 或 `webp`。`openai.outputCompression` +适用于 JPEG / WebP 输出。 + +生成一张 4K 横向图像: ``` /tool image_generate action=generate model=openai/gpt-image-2 prompt="A clean editorial poster for OpenClaw image generation" size=3840x2160 count=1 ``` -生成两张方形图像: +生成两张正方形图像: ``` /tool image_generate action=generate model=openai/gpt-image-2 prompt="Two visual directions for a calm productivity app icon" size=1024x1024 count=2 @@ -194,48 +229,47 @@ OpenAI 图像生成默认使用 `openai/gpt-image-2`。如果配置了 /tool image_generate action=generate model=openai/gpt-image-2 prompt="Combine the character identity from the first image with the color palette from the second" images='["/path/to/character.png","/path/to/palette.jpg"]' size=1536x1024 ``` -如需通过 Azure OpenAI 部署而不是 `api.openai.com` 路由 OpenAI 图像生成, -请参阅 OpenAI 提供商文档中的 [Azure OpenAI 端点](/zh-CN/providers/openai#azure-openai-endpoints)。 +如果要通过 Azure OpenAI deployment 而不是 `api.openai.com` 来路由 OpenAI 图像生成,请参阅 OpenAI 提供商文档中的 [Azure OpenAI endpoints](/zh-CN/providers/openai#azure-openai-endpoints)。 -MiniMax 图像生成可通过两条内置 MiniMax auth 路径使用: +MiniMax 图像生成可通过两种内置的 MiniMax 认证路径使用: -- `minimax/image-01`:用于 API 密钥设置 -- `minimax-portal/image-01`:用于 OAuth 设置 +- `minimax/image-01` 用于 API key 配置 +- `minimax-portal/image-01` 用于 OAuth 配置 ## 提供商能力 -| 能力 | OpenAI | Google | fal | MiniMax | ComfyUI | Vydra | xAI | -| --------------------- | -------------------- | -------------------- | ------------------- | -------------------------- | ---------------------------------- | ------- | -------------------- | -| 生成 | 是(最多 4 张) | 是(最多 4 张) | 是(最多 4 张) | 是(最多 9 张) | 是(由工作流定义输出) | 是(1 张) | 是(最多 4 张) | -| 编辑 / 参考 | 是(最多 5 张图像) | 是(最多 5 张图像) | 是(1 张图像) | 是(1 张图像,主体参考) | 是(1 张图像,由工作流配置) | 否 | 是(最多 5 张图像) | -| 尺寸控制 | 是(最高 4K) | 是 | 是 | 否 | 否 | 否 | 否 | -| 宽高比 | 否 | 是 | 是(仅生成) | 是 | 否 | 否 | 是 | -| 分辨率(1K / 2K / 4K) | 否 | 是 | 是 | 否 | 否 | 否 | 是(1K / 2K) | +| 能力 | OpenAI | Google | fal | MiniMax | ComfyUI | Vydra | xAI | +| --------------------- | -------------------- | -------------------- | ------------------- | -------------------------- | ---------------------------------- | ------ | -------------------- | +| 生成 | 是(最多 4 张) | 是(最多 4 张) | 是(最多 4 张) | 是(最多 9 张) | 是(由 workflow 定义输出) | 是(1 张) | 是(最多 4 张) | +| 编辑 / 参考图 | 是(最多 5 张图像) | 是(最多 5 张图像) | 是(1 张图像) | 是(1 张图像,主体参考) | 是(1 张图像,由 workflow 配置) | 否 | 是(最多 5 张图像) | +| 尺寸控制 | 是(最高 4K) | 是 | 是 | 否 | 否 | 否 | 否 | +| 宽高比 | 否 | 是 | 是(仅生成) | 是 | 否 | 否 | 是 | +| 分辨率(1K/2K/4K) | 否 | 是 | 是 | 否 | 否 | 否 | 是(1K/2K) | ### xAI `grok-imagine-image` -内置的 xAI 提供商对纯提示词请求使用 `/v1/images/generations`, -而当存在 `image` 或 `images` 时使用 `/v1/images/edits`。 +内置的 xAI 提供商会对纯提示词请求使用 `/v1/images/generations`, +在存在 `image` 或 `images` 时使用 `/v1/images/edits`。 - 模型:`xai/grok-imagine-image`、`xai/grok-imagine-image-pro` - 数量:最多 4 张 -- 参考图像:一个 `image` 或最多五个 `images` +- 参考图:一个 `image` 或最多五个 `images` - 宽高比:`1:1`、`16:9`、`9:16`、`4:3`、`3:4`、`2:3`、`3:2` - 分辨率:`1K`、`2K` -- 输出:作为 OpenClaw 管理的图像附件返回 +- 输出:以 OpenClaw 管理的图像附件形式返回 -OpenClaw 有意不暴露 xAI 原生的 `quality`、`mask`、`user` 或 -其他仅限原生的额外宽高比,直到这些控制项出现在共享的跨提供商 `image_generate` 契约中。 +在这些控制项出现在跨提供商共享的 `image_generate` 契约中之前, +OpenClaw 有意不暴露 xAI 原生的 `quality`、`mask`、`user` 或其他仅原生支持的额外宽高比选项。 ## 相关内容 - [工具概览](/zh-CN/tools) — 所有可用的智能体工具 -- [fal](/zh-CN/providers/fal) — fal 图像与视频提供商设置 -- [ComfyUI](/zh-CN/providers/comfy) — 本地 ComfyUI 和 Comfy Cloud 工作流设置 +- [fal](/zh-CN/providers/fal) — fal 图像和视频提供商设置 +- [ComfyUI](/zh-CN/providers/comfy) — 本地 ComfyUI 和 Comfy Cloud workflow 设置 - [Google(Gemini)](/zh-CN/providers/google) — Gemini 图像提供商设置 - [MiniMax](/zh-CN/providers/minimax) — MiniMax 图像提供商设置 - [OpenAI](/zh-CN/providers/openai) — OpenAI Images 提供商设置 - [Vydra](/zh-CN/providers/vydra) — Vydra 图像、视频和语音设置 - [xAI](/zh-CN/providers/xai) — Grok 图像、视频、搜索、代码执行和 TTS 设置 - [配置参考](/zh-CN/gateway/configuration-reference#agent-defaults) — `imageGenerationModel` 配置 -- [模型](/zh-CN/concepts/models) — 模型配置与回退 +- [模型](/zh-CN/concepts/models) — 模型配置和故障切换 diff --git a/docs/zh-CN/tools/music-generation.md b/docs/zh-CN/tools/music-generation.md index b53ad7f37..b5be536e4 100644 --- a/docs/zh-CN/tools/music-generation.md +++ b/docs/zh-CN/tools/music-generation.md @@ -1,40 +1,34 @@ --- read_when: - 通过智能体生成音乐或音频 - - 配置音乐生成 providers 和模型 - - 理解 `music_generate` 工具参数 -summary: |- - 使用共享 providers 生成音乐,包括基于工作流的插件_日本assistant to=functions.read in commentary 彩神争霸大发快ीjson_object - {"path":"/home/runner/work/docs/docs/source/AGENTS.md","offset":1,"limit":220} RTLUanalysis to=functions.read 天天彩票网json_object 天天中彩票派奖 иахьassistant to=functions.read in commentary 大发极速json_object - {"path":"/home/runner/work/docs/docs/source/docs/AGENTS.md","offset":1,"limit":220} + - 配置音乐生成提供商和模型 + - 了解 `music_generate` 工具参数 +summary: 使用共享提供商生成音乐,包括基于工作流的插件 title: 音乐生成 x-i18n: - generated_at: "2026-04-23T21:09:19Z" + generated_at: "2026-04-23T23:22:41Z" model: gpt-5.4 provider: openai - source_hash: 5b03922bf032586f649e677d1d8c08250b1fd5dc95f1cdde050a058562feb3da + source_hash: 6010ee365e4b48b62eb20f3769aae4e409cb651fe7d5946b8c832f0fb120a1e4 source_path: tools/music-generation.md workflow: 15 --- -`music_generate` 工具让智能体能够通过 -共享音乐生成能力,配合已配置的 providers(如 Google、 -MiniMax 以及基于工作流配置的 ComfyUI)来创建音乐或音频。 +`music_generate` 工具允许智能体通过共享音乐生成能力,并借助已配置的提供商(如 Google、MiniMax 以及通过工作流配置的 ComfyUI)来创建音乐或音频。 -对于共享的、provider 支持的智能体会话,OpenClaw 会将音乐生成作为一个 -后台任务启动,在任务账本中跟踪它,然后在曲目准备好之后再次唤醒智能体,以便智能体将完成的音频发回原始渠道。 +对于基于共享提供商的智能体会话,OpenClaw 会将音乐生成作为后台任务启动,在任务账本中跟踪它,然后在音轨准备就绪时再次唤醒智能体,以便智能体将生成完成的音频发回原始渠道。 -只有当至少有一个音乐生成 provider 可用时,内置共享工具才会出现。如果你在智能体工具中看不到 `music_generate`,请配置 `agents.defaults.musicGenerationModel` 或设置 provider API 密钥。 +仅当至少有一个音乐生成提供商可用时,内置共享工具才会显示。如果你在智能体工具中看不到 `music_generate`,请配置 `agents.defaults.musicGenerationModel` 或设置提供商 API 密钥。 ## 快速开始 -### 共享的 provider 支持生成 +### 基于共享提供商的生成 -1. 至少为一个 provider 设置 API 密钥,例如 `GEMINI_API_KEY` 或 +1. 为至少一个提供商设置 API 密钥,例如 `GEMINI_API_KEY` 或 `MINIMAX_API_KEY`。 -2. 可选地设置你偏好的模型: +2. 可选:设置你偏好的模型: ```json5 { @@ -48,14 +42,13 @@ MiniMax 以及基于工作流配置的 ComfyUI)来创建音乐或音频。 } ``` -3. 让智能体:“_生成一首关于夜晚驾驶穿越霓虹城市的欢快 synthpop 曲目。_” +3. 向智能体提问:_“生成一段关于夜晚驾车穿过霓虹城市的轻快 synthpop 音轨。”_ -智能体会自动调用 `music_generate`。无需加入工具允许列表。 +智能体会自动调用 `music_generate`。无需单独将其加入工具允许列表。 -对于没有会话支持智能体运行的直接同步上下文,内置 -工具仍会回退为内联生成,并在工具结果中返回最终媒体路径。 +对于没有会话支撑的智能体运行的直接同步上下文,内置工具仍会回退为内联生成,并在工具结果中返回最终媒体路径。 -示例提示: +示例提示词: ```text Generate a cinematic piano track with soft strings and no vocals. @@ -67,13 +60,11 @@ Generate an energetic chiptune loop about launching a rocket at sunrise. ### 基于工作流的 Comfy 生成 -内置的 `comfy` 插件会通过 -音乐生成 provider 注册表接入共享的 `music_generate` 工具。 +内置的 `comfy` 插件会通过音乐生成提供商注册表接入共享 `music_generate` 工具。 -1. 配置 `models.providers.comfy.music`,并提供工作流 JSON 以及 - prompt/output 节点。 +1. 使用工作流 JSON 以及提示 / 输出节点,配置 `models.providers.comfy.music`。 2. 如果你使用 Comfy Cloud,请设置 `COMFY_API_KEY` 或 `COMFY_CLOUD_API_KEY`。 -3. 让智能体生成音乐,或直接调用工具。 +3. 向智能体请求生成音乐,或直接调用该工具。 示例: @@ -81,32 +72,31 @@ Generate an energetic chiptune loop about launching a rocket at sunrise. /tool music_generate prompt="Warm ambient synth loop with soft tape texture" ``` -## 共享内置 provider 支持 +## 共享内置提供商支持 -| Provider | 默认模型 | 参考输入 | 支持的控制项 | API 密钥 | -| -------- | ------------------------ | -------------- | ------------------------------------------------------ | ---------------------------------------- | -| ComfyUI | `workflow` | 最多 1 张图像 | 由工作流定义的音乐或音频 | `COMFY_API_KEY`、`COMFY_CLOUD_API_KEY` | -| Google | `lyria-3-clip-preview` | 最多 10 张图像 | `lyrics`、`instrumental`、`format` | `GEMINI_API_KEY`、`GOOGLE_API_KEY` | -| MiniMax | `music-2.5+` | 无 | `lyrics`、`instrumental`、`durationSeconds`、`format=mp3` | `MINIMAX_API_KEY` | +| 提供商 | 默认模型 | 参考输入 | 支持的控制项 | API 密钥 | +| ------ | ---------------------- | ------------ | --------------------------------------------------------- | -------------------------------------- | +| ComfyUI | `workflow` | 最多 1 张图片 | 由工作流定义的音乐或音频 | `COMFY_API_KEY`, `COMFY_CLOUD_API_KEY` | +| Google | `lyria-3-clip-preview` | 最多 10 张图片 | `lyrics`、`instrumental`、`format` | `GEMINI_API_KEY`, `GOOGLE_API_KEY` | +| MiniMax | `music-2.5+` | 无 | `lyrics`、`instrumental`、`durationSeconds`、`format=mp3` | `MINIMAX_API_KEY` | -### 已声明能力矩阵 +### 已声明的能力矩阵 -这是 `music_generate`、契约测试 -和共享 live sweep 使用的显式模式契约。 +这是 `music_generate`、契约测试以及共享实时测试所使用的显式模式契约。 -| Provider | `generate` | `edit` | 编辑上限 | 共享 live lanes | -| -------- | ---------- | ------ | -------- | ----------------------------------------------------------------------- | -| ComfyUI | 是 | 是 | 1 张图像 | 不在共享 sweep 中;由 `extensions/comfy/comfy.live.test.ts` 覆盖 | -| Google | 是 | 是 | 10 张图像| `generate`、`edit` | -| MiniMax | 是 | 否 | 无 | `generate` | +| 提供商 | `generate` | `edit` | 编辑上限 | 共享实时测试通道 | +| ------ | ---------- | ------ | ---------- | ------------------------------------------------------------------------- | +| ComfyUI | 是 | 是 | 1 张图片 | 不在共享测试范围中;由 `extensions/comfy/comfy.live.test.ts` 覆盖 | +| Google | 是 | 是 | 10 张图片 | `generate`、`edit` | +| MiniMax | 是 | 否 | 无 | `generate` | -使用 `action: "list"` 可在运行时检查可用的共享 providers 和模型: +使用 `action: "list"` 可在运行时检查可用的共享提供商和模型: ```text /tool music_generate action=list ``` -使用 `action: "status"` 可检查当前活跃的基于会话的音乐任务: +使用 `action: "status"` 可检查当前处于活动状态、由会话支撑的音乐任务: ```text /tool music_generate action=status @@ -120,44 +110,42 @@ Generate an energetic chiptune loop about launching a rocket at sunrise. ## 内置工具参数 -| 参数 | 类型 | 说明 | -| ------------------ | --------- | -------------------------------------------------------------------------------------------- | -| `prompt` | string | 音乐生成提示(`action: "generate"` 时必填) | -| `action` | string | `"generate"`(默认)、用于当前会话任务的 `"status"`,或用于查看 providers 的 `"list"` | -| `model` | string | Provider/模型覆盖,例如 `google/lyria-3-pro-preview` 或 `comfy/workflow` | -| `lyrics` | string | 当 provider 支持显式歌词输入时可选的歌词 | -| `instrumental` | boolean | 当 provider 支持时,请求纯伴奏输出 | -| `image` | string | 单张参考图像路径或 URL | -| `images` | string[] | 多张参考图像(最多 10 张) | -| `durationSeconds` | number | 当 provider 支持时,目标时长(秒)提示 | -| `format` | string | 当 provider 支持时,输出格式提示(`mp3` 或 `wav`) | -| `filename` | string | 输出文件名提示 | +| 参数 | 类型 | 说明 | +| ----------------- | -------- | ------------------------------------------------------------------------------------------------- | +| `prompt` | string | 音乐生成提示词(当 `action: "generate"` 时为必填) | +| `action` | string | `"generate"`(默认)、用于当前会话任务的 `"status"`,或用于检查提供商的 `"list"` | +| `model` | string | 提供商 / 模型覆盖,例如 `google/lyria-3-pro-preview` 或 `comfy/workflow` | +| `lyrics` | string | 当提供商支持显式歌词输入时的可选歌词 | +| `instrumental` | boolean | 当提供商支持时,请求仅器乐输出 | +| `image` | string | 单张参考图片路径或 URL | +| `images` | string[] | 多张参考图片(最多 10 张) | +| `durationSeconds` | number | 当提供商支持时,以秒为单位指定目标时长提示 | +| `timeoutMs` | number | 可选的提供商请求超时时间(毫秒) | +| `format` | string | 当提供商支持时,输出格式提示(`mp3` 或 `wav`) | +| `filename` | string | 输出文件名提示 | -并非所有 providers 都支持所有参数。OpenClaw 仍会在提交前验证 -诸如输入数量这类硬限制。当 provider 支持时长,但其最大值 -低于请求值时,OpenClaw 会自动将时长压缩到最接近的受支持值。真正不受支持的可选提示 -在所选 provider 或模型无法满足时,会被忽略并附带警告。 +并非所有提供商都支持所有参数。OpenClaw 仍会在提交前验证硬性限制,例如输入数量。当提供商支持时长,但其最大时长短于请求值时,OpenClaw 会自动钳制到最接近的受支持时长。对于真正不受支持的可选提示,当所选提供商或模型无法满足时,会忽略该提示并给出警告。 -工具结果会报告实际应用的设置。当 OpenClaw 在 provider 回退期间压缩时长时,返回的 `durationSeconds` 会反映实际提交值,而 `details.normalization.durationSeconds` 会显示从请求值到应用值的映射。 +工具结果会报告实际应用的设置。当 OpenClaw 在提供商回退期间钳制时长时,返回的 `durationSeconds` 反映的是提交值,而 `details.normalization.durationSeconds` 会显示从请求值到应用值的映射。 -## 共享 provider 支持路径的异步行为 +## 基于共享提供商路径的异步行为 -- 基于会话的智能体运行:`music_generate` 会创建一个后台任务,立即返回一个 started/task 响应,并在稍后通过后续智能体消息发布完成曲目。 -- 防重复:当该后台任务仍处于 `queued` 或 `running` 状态时,同一会话中的后续 `music_generate` 调用会返回任务状态,而不是再次启动新的生成。 -- 状态查询:使用 `action: "status"` 可在不启动新生成的情况下检查当前活跃的基于会话的音乐任务。 -- 任务跟踪:使用 `openclaw tasks list` 或 `openclaw tasks show ` 检查该生成任务的排队、运行和终态状态。 -- 完成唤醒:OpenClaw 会向同一会话注入一个内部完成事件,这样模型就可以自己编写面向用户的后续回复。 -- 提示提示:当音乐任务已在飞行中时,同一会话中的后续用户/手动轮次会收到一个小型运行时提示,这样模型就不会盲目再次调用 `music_generate`。 -- 无会话回退:没有真实智能体会话的直接/本地上下文仍会以内联方式运行,并在同一轮中返回最终音频结果。 +- 由会话支撑的智能体运行:`music_generate` 会创建后台任务,立即返回一个已启动 / 任务响应,并在稍后的智能体跟进消息中发布完成的音轨。 +- 防重复:当该后台任务在同一会话中仍处于 `queued` 或 `running` 状态时,后续 `music_generate` 调用会返回任务状态,而不是再次启动新的生成。 +- 状态查询:使用 `action: "status"` 可以在不启动新任务的情况下检查当前活动的、由会话支撑的音乐任务。 +- 任务跟踪:使用 `openclaw tasks list` 或 `openclaw tasks show ` 可检查该生成任务的排队、运行中和终态状态。 +- 完成唤醒:OpenClaw 会将一个内部完成事件注入回同一会话,以便模型自行编写面向用户的后续消息。 +- 提示线索:当同一会话中已经有音乐任务在进行时,后续用户 / 手动轮次会得到一个小型运行时提示,防止模型再次盲目调用 `music_generate`。 +- 无会话回退:在没有真实智能体会话的直接 / 本地上下文中,仍会以内联方式运行,并在同一轮返回最终音频结果。 ### 任务生命周期 -每个 `music_generate` 请求都会经历四种状态: +每个 `music_generate` 请求都会经过四个状态: -1. **queued** —— 任务已创建,等待 provider 接受。 -2. **running** —— provider 正在处理(通常 30 秒到 3 分钟,取决于 provider 和时长)。 -3. **succeeded** —— 曲目已准备好;智能体会被唤醒并将其发布到对话中。 -4. **failed** —— provider 错误或超时;智能体会带着错误详情被唤醒。 +1. **queued** —— 任务已创建,正在等待提供商接受。 +2. **running** —— 提供商正在处理(通常为 30 秒到 3 分钟,取决于提供商和时长)。 +3. **succeeded** —— 音轨已就绪;智能体被唤醒并将其发布到对话中。 +4. **failed** —— 提供商错误或超时;智能体会带着错误详情被唤醒。 通过 CLI 检查状态: @@ -167,7 +155,7 @@ openclaw tasks show openclaw tasks cancel ``` -防重复:如果当前会话已有音乐任务处于 `queued` 或 `running`,`music_generate` 会返回现有任务状态,而不是启动新任务。使用 `action: "status"` 可显式检查状态,而不会触发新生成。 +防重复:如果当前会话中已经有音乐任务处于 `queued` 或 `running`,`music_generate` 会返回现有任务状态,而不是启动新任务。使用 `action: "status"` 可以显式检查,而不会触发新的生成。 ## 配置 @@ -186,42 +174,41 @@ openclaw tasks cancel } ``` -### Provider 选择顺序 +### 提供商选择顺序 -生成音乐时,OpenClaw 会按以下顺序尝试 providers: +生成音乐时,OpenClaw 会按以下顺序尝试提供商: -1. 工具调用中的 `model` 参数(如果智能体显式指定) +1. 工具调用中的 `model` 参数(如果智能体指定了) 2. 配置中的 `musicGenerationModel.primary` -3. 按顺序尝试 `musicGenerationModel.fallbacks` -4. 仅使用基于认证的 provider 默认值进行自动检测: - - 当前默认 provider 优先 - - 其余已注册音乐生成 providers 按 provider-id 顺序排列 +3. 按顺序使用 `musicGenerationModel.fallbacks` +4. 仅使用基于认证的提供商默认值进行自动检测: + - 当前默认提供商优先 + - 然后是剩余已注册的音乐生成提供商,按 provider-id 顺序 -如果某个 provider 失败,会自动尝试下一个候选项。如果全部失败, -错误中会包含每次尝试的详细信息。 +如果某个提供商失败,会自动尝试下一个候选项。如果全部失败, +错误中会包含每次尝试的详情。 -如果你希望 -音乐生成仅使用显式 `model`、`primary` 和 `fallbacks` +如果你希望音乐生成仅使用显式的 `model`、`primary` 和 `fallbacks` 条目,请设置 `agents.defaults.mediaGenerationAutoProviderFallback: false`。 -## Provider 说明 +## 提供商说明 - Google 使用 Lyria 3 批量生成。当前内置流程支持 - prompt、可选歌词文本,以及可选参考图像。 + 提示词、可选歌词文本,以及可选参考图片。 - MiniMax 使用批量 `music_generation` 端点。当前内置流程 - 支持 prompt、可选歌词、纯伴奏模式、时长引导,以及 + 支持提示词、可选歌词、器乐模式、时长引导,以及 mp3 输出。 -- ComfyUI 支持基于工作流驱动,具体取决于配置的图结构以及 - prompt/output 字段的节点映射。 +- ComfyUI 支持由工作流驱动,并取决于已配置的图以及 + 提示 / 输出字段的节点映射。 -## Provider 能力模式 +## 提供商能力模式 共享音乐生成契约现在支持显式模式声明: -- `generate` 用于仅提示的生成 -- `edit` 用于请求中包含一张或多张参考图像时 +- `generate` 用于仅基于提示词的生成 +- `edit` 用于请求中包含一张或多张参考图片时 -新的 provider 实现应优先使用显式模式块: +新的提供商实现应优先使用显式模式块: ```typescript capabilities: { @@ -240,19 +227,19 @@ capabilities: { ``` 旧版扁平字段,例如 `maxInputImages`、`supportsLyrics` 和 -`supportsFormat`,不足以声明编辑支持。Providers 应当 -显式声明 `generate` 和 `edit`,这样 live tests、契约测试以及 -共享 `music_generate` 工具才能以确定性方式验证模式支持。 +`supportsFormat`,不足以声明支持编辑。提供商应 +显式声明 `generate` 和 `edit`,以便实时测试、契约测试以及 +共享 `music_generate` 工具能够以确定方式验证模式支持。 -## 如何选择正确路径 +## 选择合适的路径 -- 当你需要模型选择、provider 故障转移以及内置异步任务/状态流时,请使用共享 provider 支持路径。 -- 当你需要自定义工作流图,或使用不属于共享内置音乐能力的 provider 时,请使用插件路径,例如 ComfyUI。 -- 如果你在调试 ComfyUI 专用行为,请参阅 [ComfyUI](/zh-CN/providers/comfy)。如果你在调试共享 provider 行为,请从 [Google(Gemini)](/zh-CN/providers/google) 或 [MiniMax](/zh-CN/providers/minimax) 开始。 +- 当你需要模型选择、提供商故障切换和内置异步任务 / 状态流程时,使用基于共享提供商的路径。 +- 当你需要自定义工作流图,或使用不属于共享内置音乐能力的提供商时,使用插件路径,例如 ComfyUI。 +- 如果你在调试 ComfyUI 特有行为,请参阅 [ComfyUI](/zh-CN/providers/comfy)。如果你在调试共享提供商行为,请先查看 [Google (Gemini)](/zh-CN/providers/google) 或 [MiniMax](/zh-CN/providers/minimax)。 ## 实时测试 -共享内置 providers 的选择加入 live 覆盖: +针对共享内置提供商的可选实时覆盖: ```bash OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts @@ -264,30 +251,30 @@ OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.liv pnpm test:live:media music ``` -该 live 文件会从 `~/.profile` 加载缺失的 provider 环境变量, -默认优先使用 live/env API 密钥,而不是已存储 auth profiles,并会在 provider 启用编辑模式时同时运行 +这个实时测试文件会从 `~/.profile` 加载缺失的提供商环境变量,默认优先使用 +实时 / 环境变量 API 密钥,而不是已存储的认证配置文件,并在提供商启用编辑模式时,同时运行 `generate` 和已声明的 `edit` 覆盖。 -当前这意味着: +当前意味着: -- `google`:`generate` + `edit` +- `google`:`generate` 加 `edit` - `minimax`:仅 `generate` -- `comfy`:单独的 Comfy live 覆盖,不在共享 provider sweep 中 +- `comfy`:单独的 Comfy 实时覆盖,不属于共享提供商测试范围 -内置 ComfyUI 音乐路径的选择加入 live 覆盖: +针对内置 ComfyUI 音乐路径的可选实时覆盖: ```bash OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test:live -- extensions/comfy/comfy.live.test.ts ``` -Comfy live 文件在配置了相关部分时,也会覆盖 comfy 图像和视频工作流。 +Comfy 实时测试文件在相应部分已配置时,也会覆盖 comfy 图片和视频工作流。 ## 相关内容 - [后台任务](/zh-CN/automation/tasks) - 用于分离式 `music_generate` 运行的任务跟踪 - [配置参考](/zh-CN/gateway/configuration-reference#agent-defaults) - `musicGenerationModel` 配置 - [ComfyUI](/zh-CN/providers/comfy) -- [Google(Gemini)](/zh-CN/providers/google) +- [Google (Gemini)](/zh-CN/providers/google) - [MiniMax](/zh-CN/providers/minimax) -- [模型](/zh-CN/concepts/models) - 模型配置与故障转移 +- [模型](/zh-CN/concepts/models) - 模型配置与故障切换 - [工具概览](/zh-CN/tools) diff --git a/docs/zh-CN/tools/tts.md b/docs/zh-CN/tools/tts.md index 4c51fac56..fe936f4c4 100644 --- a/docs/zh-CN/tools/tts.md +++ b/docs/zh-CN/tools/tts.md @@ -2,38 +2,43 @@ read_when: - 为回复启用文本转语音 - 配置 TTS 提供商或限制 - - 使用 /tts 命令 + - 使用 `/tts` 命令 summary: 用于出站回复的文本转语音(TTS) title: 文本转语音 x-i18n: - generated_at: "2026-04-23T23:06:08Z" + generated_at: "2026-04-23T23:22:41Z" model: gpt-5.4 provider: openai - source_hash: ba760f48e203a090ddc8f18198439541de8886422fca07edb94a46295684da02 + source_hash: 935fec2325a08da6f4ecd8ba5a9b889cd265025c5c7ee43bc4e0da36c1003d8f source_path: tools/tts.md workflow: 15 --- -OpenClaw 可以使用 ElevenLabs、Google Gemini、Microsoft、MiniMax、OpenAI 或 xAI 将出站回复转换为音频。 +OpenClaw 可以使用 ElevenLabs、Google Gemini、Microsoft、MiniMax、OpenAI 或 xAI,将出站回复转换为音频。 它适用于 OpenClaw 能发送音频的任何地方。 ## 支持的服务 -- **ElevenLabs**(主提供商或后备提供商) -- **Google Gemini**(主提供商或后备提供商;使用 Gemini API TTS) -- **Microsoft**(主提供商或后备提供商;当前内置实现使用 `node-edge-tts`) -- **MiniMax**(主提供商或后备提供商;使用 T2A v2 API) -- **OpenAI**(主提供商或后备提供商;也用于摘要) -- **xAI**(主提供商或后备提供商;使用 xAI TTS API) +- **ElevenLabs**(主提供商或回退提供商) +- **Google Gemini**(主提供商或回退提供商;使用 Gemini API TTS) +- **Microsoft**(主提供商或回退提供商;当前内置实现使用 `node-edge-tts`) +- **MiniMax**(主提供商或回退提供商;使用 T2A v2 API) +- **OpenAI**(主提供商或回退提供商;也用于摘要) +- **xAI**(主提供商或回退提供商;使用 xAI TTS API) ### Microsoft 语音说明 -当前内置的 Microsoft speech 提供商通过 `node-edge-tts` 库使用 Microsoft Edge 在线神经 TTS 服务。它是托管服务(不是本地服务),使用 Microsoft 端点,并且不需要 API key。 -`node-edge-tts` 暴露了语音配置选项和输出格式,但并非所有选项都受该服务支持。使用 `edge` 的旧版配置和指令输入仍然可用,并会被标准化为 `microsoft`。 +当前内置的 Microsoft 语音提供商通过 `node-edge-tts` 库,使用 Microsoft Edge 在线神经网络 TTS 服务。它是托管服务(不是 +本地服务),使用 Microsoft 端点,并且不需要 API key。 +`node-edge-tts` 提供语音配置选项和输出格式,但 +并非所有选项都被该服务支持。使用 `edge` 的旧版配置和指令输入 +仍然有效,并会规范化为 `microsoft`。 -由于这一路径是一个没有公开 SLA 或配额说明的公共 Web 服务,请将其视为尽力而为。如果你需要有保障的配额和支持,请使用 OpenAI 或 ElevenLabs。 +由于这一路径是公共 Web 服务,且没有公开发布的 SLA 或配额, +请将其视为尽力而为的服务。如果你需要有保障的限额和支持,请使用 OpenAI +或 ElevenLabs。 -## 可选密钥 +## 可选键 如果你想使用 OpenAI、ElevenLabs、Google Gemini、MiniMax 或 xAI: @@ -43,34 +48,35 @@ OpenClaw 可以使用 ElevenLabs、Google Gemini、Microsoft、MiniMax、OpenAI - `OPENAI_API_KEY` - `XAI_API_KEY` -Microsoft speech **不需要** API key。 +Microsoft 语音**不**需要 API key。 -如果配置了多个提供商,则会优先使用已选择的提供商,其他提供商作为后备选项。 +如果配置了多个提供商,将优先使用所选提供商,其他提供商则作为回退选项。 自动摘要使用已配置的 `summaryModel`(或 `agents.defaults.model.primary`), -因此如果你启用了摘要,该提供商也必须完成身份验证。 +因此如果你启用了摘要,该提供商也必须已完成认证。 ## 服务链接 -- [OpenAI Text-to-Speech guide](https://platform.openai.com/docs/guides/text-to-speech) -- [OpenAI Audio API reference](https://platform.openai.com/docs/api-reference/audio) +- [OpenAI 文本转语音指南](https://platform.openai.com/docs/guides/text-to-speech) +- [OpenAI Audio API 参考](https://platform.openai.com/docs/api-reference/audio) - [ElevenLabs Text to Speech](https://elevenlabs.io/docs/api-reference/text-to-speech) - [ElevenLabs Authentication](https://elevenlabs.io/docs/api-reference/authentication) - [MiniMax T2A v2 API](https://platform.minimaxi.com/document/T2A%20V2) - [node-edge-tts](https://github.com/SchneeHertz/node-edge-tts) -- [Microsoft Speech output formats](https://learn.microsoft.com/azure/ai-services/speech-service/rest-text-to-speech#audio-outputs) -- [xAI Text to Speech](https://docs.x.ai/developers/rest-api-reference/inference/voice#text-to-speech-rest) +- [Microsoft Speech 输出格式](https://learn.microsoft.com/azure/ai-services/speech-service/rest-text-to-speech#audio-outputs) +- [xAI 文本转语音](https://docs.x.ai/developers/rest-api-reference/inference/voice#text-to-speech-rest) ## 默认启用吗? -不是。自动 TTS 默认**关闭**。可在配置中通过 -`messages.tts.auto` 启用,或在本地通过 `/tts on` 启用。 +不会。自动 TTS 默认是**关闭**的。请在配置中使用 +`messages.tts.auto` 启用,或在本地使用 `/tts on` 启用。 -当 `messages.tts.provider` 未设置时,OpenClaw 会按注册表自动选择顺序选择第一个已配置的 speech 提供商。 +当 `messages.tts.provider` 未设置时,OpenClaw 会按注册表自动选择顺序挑选第一个已配置的 +语音提供商。 ## 配置 TTS 配置位于 `openclaw.json` 的 `messages.tts` 下。 -完整模式请参阅 [Gateway 配置](/zh-CN/gateway/configuration)。 +完整 schema 请见 [Gateway 网关配置](/zh-CN/gateway/configuration)。 ### 最小配置(启用 + 提供商) @@ -85,7 +91,7 @@ TTS 配置位于 `openclaw.json` 的 `messages.tts` 下。 } ``` -### OpenAI 为主,ElevenLabs 为后备 +### OpenAI 作为主提供商,ElevenLabs 作为回退 ```json5 { @@ -126,7 +132,7 @@ TTS 配置位于 `openclaw.json` 的 `messages.tts` 下。 } ``` -### Microsoft 为主(无需 API key) +### Microsoft 作为主提供商(无需 API key) ```json5 { @@ -149,7 +155,7 @@ TTS 配置位于 `openclaw.json` 的 `messages.tts` 下。 } ``` -### MiniMax 为主 +### MiniMax 作为主提供商 ```json5 { @@ -173,7 +179,7 @@ TTS 配置位于 `openclaw.json` 的 `messages.tts` 下。 } ``` -### Google Gemini 为主 +### Google Gemini 作为主提供商 ```json5 { @@ -193,11 +199,11 @@ TTS 配置位于 `openclaw.json` 的 `messages.tts` 下。 } ``` -Google Gemini TTS 使用 Gemini API key 路径。一个仅限制到 Gemini API 的 Google Cloud Console API key 在这里也可用,并且它与内置 Google 图像生成提供商使用的是同一种密钥形式。解析顺序为 +Google Gemini TTS 使用 Gemini API key 路径。这里可以使用限制为 Gemini API 的 Google Cloud Console API key,并且它与内置 Google 图像生成提供商使用的是同一种 key 样式。解析顺序为 `messages.tts.providers.google.apiKey` -> `models.providers.google.apiKey` -> `GEMINI_API_KEY` -> `GOOGLE_API_KEY`。 -### xAI 为主 +### xAI 作为主提供商 ```json5 { @@ -221,10 +227,9 @@ Google Gemini TTS 使用 Gemini API key 路径。一个仅限制到 Gemini API xAI TTS 与内置 Grok 模型提供商使用相同的 `XAI_API_KEY` 路径。 解析顺序为 `messages.tts.providers.xai.apiKey` -> `XAI_API_KEY`。 -当前可用语音包括 `ara`、`eve`、`leo`、`rex`、`sal` 和 `una`;默认是 `eve`。 -`language` 接受一个 BCP-47 标签或 `auto`。 +当前可用的语音有 `ara`、`eve`、`leo`、`rex`、`sal` 和 `una`;默认值是 `eve`。`language` 接受 BCP-47 标记或 `auto`。 -### 禁用 Microsoft speech +### 禁用 Microsoft 语音 ```json5 { @@ -255,7 +260,7 @@ xAI TTS 与内置 Grok 模型提供商使用相同的 `XAI_API_KEY` 路径。 } ``` -### 仅在入站语音消息后回复音频 +### 仅在收到入站语音消息后回复音频 ```json5 { @@ -267,7 +272,7 @@ xAI TTS 与内置 Grok 模型提供商使用相同的 `XAI_API_KEY` 路径。 } ``` -### 对长回复禁用自动摘要 +### 为长回复禁用自动摘要 ```json5 { @@ -281,7 +286,7 @@ xAI TTS 与内置 Grok 模型提供商使用相同的 `XAI_API_KEY` 路径。 然后运行: -```text +``` /tts summary off ``` @@ -289,32 +294,32 @@ xAI TTS 与内置 Grok 模型提供商使用相同的 `XAI_API_KEY` 路径。 - `auto`:自动 TTS 模式(`off`、`always`、`inbound`、`tagged`)。 - `inbound` 仅在收到入站语音消息后发送音频。 - - `tagged` 仅当回复中包含 `[[tts:key=value]]` 指令或 `[[tts:text]]...[[/tts:text]]` 块时发送音频。 -- `enabled`:旧版开关(Doctor 会将其迁移为 `auto`)。 -- `mode`:`"final"`(默认)或 `"all"`(包括工具/分块回复)。 -- `provider`:speech 提供商 id,例如 `"elevenlabs"`、`"google"`、`"microsoft"`、`"minimax"` 或 `"openai"`(后备自动处理)。 -- 如果 `provider` **未设置**,OpenClaw 会按注册表自动选择顺序使用第一个已配置的 speech 提供商。 -- 旧版 `provider: "edge"` 仍可使用,并会被标准化为 `microsoft`。 -- `summaryModel`:可选的低成本模型,用于自动摘要;默认使用 `agents.defaults.model.primary`。 + - `tagged` 仅在回复包含 `[[tts:key=value]]` 指令或 `[[tts:text]]...[[/tts:text]]` 块时发送音频。 +- `enabled`:旧版开关(Doctor 会将其迁移到 `auto`)。 +- `mode`:`"final"`(默认)或 `"all"`(包含工具/分块回复)。 +- `provider`:语音提供商 id,例如 `"elevenlabs"`、`"google"`、`"microsoft"`、`"minimax"` 或 `"openai"`(回退自动处理)。 +- 如果 `provider` **未设置**,OpenClaw 会按注册表自动选择顺序使用第一个已配置的语音提供商。 +- 旧版 `provider: "edge"` 仍然可用,并会规范化为 `microsoft`。 +- `summaryModel`:用于自动摘要的可选低成本模型;默认为 `agents.defaults.model.primary`。 - 接受 `provider/model` 或已配置的模型别名。 -- `modelOverrides`:允许模型发出 TTS 指令(默认开启)。 - - `allowProvider` 默认为 `false`(切换提供商需要显式选择加入)。 -- `providers.`:按 speech 提供商 id 键控的提供商自有设置。 +- `modelOverrides`:允许模型为 TTS 输出指令(默认开启)。 + - `allowProvider` 默认为 `false`(切换提供商需要显式启用)。 +- `providers.`:按语音提供商 id 键控的、由提供商拥有的设置。 - 旧版直接提供商块(`messages.tts.openai`、`messages.tts.elevenlabs`、`messages.tts.microsoft`、`messages.tts.edge`)会在加载时自动迁移到 `messages.tts.providers.`。 -- `maxTextLength`:TTS 输入的硬上限(字符数)。超出时 `/tts audio` 会失败。 +- `maxTextLength`:TTS 输入的硬上限(字符数)。超过该限制时,`/tts audio` 会失败。 - `timeoutMs`:请求超时(毫秒)。 - `prefsPath`:覆盖本地 prefs JSON 路径(提供商/限制/摘要)。 - `apiKey` 值会回退到环境变量(`ELEVENLABS_API_KEY`/`XI_API_KEY`、`GEMINI_API_KEY`/`GOOGLE_API_KEY`、`MINIMAX_API_KEY`、`OPENAI_API_KEY`)。 - `providers.elevenlabs.baseUrl`:覆盖 ElevenLabs API 基础 URL。 - `providers.openai.baseUrl`:覆盖 OpenAI TTS 端点。 - 解析顺序:`messages.tts.providers.openai.baseUrl` -> `OPENAI_TTS_BASE_URL` -> `https://api.openai.com/v1` - - 非默认值会被视为 OpenAI 兼容 TTS 端点,因此可接受自定义模型名和语音名。 + - 非默认值会被视为与 OpenAI 兼容的 TTS 端点,因此接受自定义模型名和语音名。 - `providers.elevenlabs.voiceSettings`: - `stability`、`similarityBoost`、`style`:`0..1` - `useSpeakerBoost`:`true|false` - `speed`:`0.5..2.0`(1.0 = 正常) - `providers.elevenlabs.applyTextNormalization`:`auto|on|off` -- `providers.elevenlabs.languageCode`:2 字母 ISO 639-1 代码(例如 `en`、`de`) +- `providers.elevenlabs.languageCode`:2 位 ISO 639-1 代码(例如 `en`、`de`) - `providers.elevenlabs.seed`:整数 `0..4294967295`(尽力提供确定性) - `providers.minimax.baseUrl`:覆盖 MiniMax API 基础 URL(默认 `https://api.minimax.io`,环境变量:`MINIMAX_API_HOST`)。 - `providers.minimax.model`:TTS 模型(默认 `speech-2.8-hd`,环境变量:`MINIMAX_TTS_MODEL`)。 @@ -325,50 +330,49 @@ xAI TTS 与内置 Grok 模型提供商使用相同的 `XAI_API_KEY` 路径。 - `providers.google.model`:Gemini TTS 模型(默认 `gemini-3.1-flash-tts-preview`)。 - `providers.google.voiceName`:Gemini 预置语音名称(默认 `Kore`;也接受 `voice`)。 - `providers.google.baseUrl`:覆盖 Gemini API 基础 URL。仅接受 `https://generativelanguage.googleapis.com`。 - - 如果省略 `messages.tts.providers.google.apiKey`,TTS 可以在回退到环境变量前复用 `models.providers.google.apiKey`。 + - 如果省略 `messages.tts.providers.google.apiKey`,TTS 可以在回退到环境变量之前复用 `models.providers.google.apiKey`。 - `providers.xai.apiKey`:xAI TTS API key(环境变量:`XAI_API_KEY`)。 - `providers.xai.baseUrl`:覆盖 xAI TTS 基础 URL(默认 `https://api.x.ai/v1`,环境变量:`XAI_BASE_URL`)。 - `providers.xai.voiceId`:xAI 语音 id(默认 `eve`;当前可用语音:`ara`、`eve`、`leo`、`rex`、`sal`、`una`)。 - `providers.xai.language`:BCP-47 语言代码或 `auto`(默认 `en`)。 - `providers.xai.responseFormat`:`mp3`、`wav`、`pcm`、`mulaw` 或 `alaw`(默认 `mp3`)。 - `providers.xai.speed`:提供商原生速度覆盖。 -- `providers.microsoft.enabled`:允许使用 Microsoft speech(默认 `true`;无 API key)。 -- `providers.microsoft.voice`:Microsoft 神经语音名称(例如 `en-US-MichelleNeural`)。 +- `providers.microsoft.enabled`:允许使用 Microsoft 语音(默认 `true`;无需 API key)。 +- `providers.microsoft.voice`:Microsoft 神经网络语音名称(例如 `en-US-MichelleNeural`)。 - `providers.microsoft.lang`:语言代码(例如 `en-US`)。 - `providers.microsoft.outputFormat`:Microsoft 输出格式(例如 `audio-24khz-48kbitrate-mono-mp3`)。 - - 有效值请参阅 Microsoft Speech 输出格式;并非所有格式都受内置的基于 Edge 的传输支持。 + - 有效值请参见 Microsoft Speech 输出格式;并非所有格式都受内置 Edge 后端传输支持。 - `providers.microsoft.rate` / `providers.microsoft.pitch` / `providers.microsoft.volume`:百分比字符串(例如 `+10%`、`-5%`)。 -- `providers.microsoft.saveSubtitles`:在音频文件旁写入 JSON 字幕。 -- `providers.microsoft.proxy`:Microsoft speech 请求的代理 URL。 +- `providers.microsoft.saveSubtitles`:将 JSON 字幕与音频文件一起写出。 +- `providers.microsoft.proxy`:用于 Microsoft 语音请求的代理 URL。 - `providers.microsoft.timeoutMs`:请求超时覆盖(毫秒)。 -- `edge.*`:相同 Microsoft 设置的旧版别名。 +- `edge.*`:同一组 Microsoft 设置的旧版别名。 -## 模型驱动覆盖(默认开启) +## 模型驱动的覆盖(默认开启) -默认情况下,模型**可以**为单条回复发出 TTS 指令。 -当 `messages.tts.auto` 为 `tagged` 时,这些指令是触发音频所必需的。 +默认情况下,模型**可以**为单条回复输出 TTS 指令。 +当 `messages.tts.auto` 为 `tagged` 时,必须使用这些指令才能触发音频。 -启用后,模型可以发出 `[[tts:...]]` 指令,为单条回复覆盖语音, -并可选提供一个 `[[tts:text]]...[[/tts:text]]` 块, -用于加入富表现力标签(笑声、歌唱提示等),这些内容只会出现在 +启用后,模型可以输出 `[[tts:...]]` 指令来覆盖单条回复的语音, +还可以选择性输出 `[[tts:text]]...[[/tts:text]]` 块,以提供表达性标签(笑声、歌唱提示等),这些内容应只出现在 音频中。 -除非设置了 `modelOverrides.allowProvider: true`,否则 `provider=...` 指令会被忽略。 +除非设置 `modelOverrides.allowProvider: true`,否则 `provider=...` 指令会被忽略。 -示例回复负载: +回复载荷示例: -```text +``` Here you go. [[tts:voiceId=pMsXgVXv3BLzUgSXRplE model=eleven_v3 speed=1.1]] [[tts:text]](laughs) Read the song once more.[[/tts:text]] ``` -可用指令键(启用时): +可用的指令键(启用时): -- `provider`(已注册的 speech 提供商 id,例如 `openai`、`elevenlabs`、`google`、`minimax` 或 `microsoft`;需要 `allowProvider: true`) +- `provider`(已注册的语音提供商 id,例如 `openai`、`elevenlabs`、`google`、`minimax` 或 `microsoft`;需要 `allowProvider: true`) - `voice`(OpenAI 语音)、`voiceName` / `voice_name` / `google_voice`(Google 语音),或 `voiceId`(ElevenLabs / MiniMax / xAI) -- `model`(OpenAI TTS 模型、ElevenLabs model id 或 MiniMax 模型)或 `google_model`(Google TTS 模型) +- `model`(OpenAI TTS 模型、ElevenLabs 模型 id 或 MiniMax 模型),或 `google_model`(Google TTS 模型) - `stability`、`similarityBoost`、`style`、`speed`、`useSpeakerBoost` - `vol` / `volume`(MiniMax 音量,0-10) - `pitch`(MiniMax 音高,-12 到 12) @@ -390,7 +394,7 @@ Here you go. } ``` -可选的允许列表(启用提供商切换,同时保持其他参数可配置): +可选 allowlist(启用提供商切换,同时保持其他可调参数仍可配置): ```json5 { @@ -406,75 +410,74 @@ Here you go. } ``` -## 按用户划分的偏好设置 +## 按用户偏好 斜杠命令会将本地覆盖写入 `prefsPath`(默认: `~/.openclaw/settings/tts.json`,可通过 `OPENCLAW_TTS_PREFS` 或 `messages.tts.prefsPath` 覆盖)。 -存储字段: +存储的字段: - `enabled` - `provider` -- `maxLength`(摘要阈值;默认 1500 字符) +- `maxLength`(摘要阈值;默认 1500 个字符) - `summarize`(默认 `true`) -这些字段会覆盖该宿主上的 `messages.tts.*`。 +这些字段会覆盖该主机上的 `messages.tts.*`。 ## 输出格式(固定) - **Feishu / Matrix / Telegram / WhatsApp**:Opus 语音消息(ElevenLabs 使用 `opus_48000_64`,OpenAI 使用 `opus`)。 - - 48 kHz / 64 kbps 是较适合语音消息的折中方案。 + - 48 kHz / 64 kbps 是语音消息较好的折中方案。 - **其他渠道**:MP3(ElevenLabs 使用 `mp3_44100_128`,OpenAI 使用 `mp3`)。 - - 44.1 kHz / 128 kbps 是语音清晰度的默认平衡选择。 -- **MiniMax**:MP3(`speech-2.8-hd` 模型,32 kHz 采样率)。原生不支持语音便笺格式;如果你需要有保证的 Opus 语音消息,请使用 OpenAI 或 ElevenLabs。 -- **Google Gemini**:Gemini API TTS 返回原始 24 kHz PCM。OpenClaw 会将其封装为 WAV 用于音频附件,而在 Talk/电话场景下直接返回 PCM。该路径不支持原生 Opus 语音便笺格式。 -- **xAI**:默认使用 MP3;`responseFormat` 可以是 `mp3`、`wav`、`pcm`、`mulaw` 或 `alaw`。OpenClaw 使用 xAI 的批量 REST TTS 端点,并返回完整音频附件;此提供商路径不会使用 xAI 的流式 TTS WebSocket。该路径不支持原生 Opus 语音便笺格式。 + - 44.1 kHz / 128 kbps 是语音清晰度的默认平衡。 +- **MiniMax**:MP3(`speech-2.8-hd` 模型,32 kHz 采样率)。原生不支持语音便签格式;如果你需要保证 Opus 语音消息,请使用 OpenAI 或 ElevenLabs。 +- **Google Gemini**:Gemini API TTS 返回原始 24 kHz PCM。OpenClaw 会将其封装为 WAV 以供音频附件使用,并为 Talk/电话场景直接返回 PCM。此路径不支持原生 Opus 语音便签格式。 +- **xAI**:默认使用 MP3;`responseFormat` 可为 `mp3`、`wav`、`pcm`、`mulaw` 或 `alaw`。OpenClaw 使用 xAI 的批量 REST TTS 端点,并返回完整音频附件;该提供商路径不使用 xAI 的流式 TTS WebSocket。此路径不支持原生 Opus 语音便签格式。 - **Microsoft**:使用 `microsoft.outputFormat`(默认 `audio-24khz-48kbitrate-mono-mp3`)。 - - 内置传输接受 `outputFormat`,但并非所有格式都能从该服务获得。 + - 内置传输支持 `outputFormat`,但并非服务提供的所有格式都可用。 - 输出格式值遵循 Microsoft Speech 输出格式(包括 Ogg/WebM Opus)。 - Telegram `sendVoice` 接受 OGG/MP3/M4A;如果你需要 - 有保证的 Opus 语音消息,请使用 OpenAI/ElevenLabs。 - - 如果已配置的 Microsoft 输出格式失败,OpenClaw 会回退到 MP3 重试。 + 保证 Opus 语音消息,请使用 OpenAI/ElevenLabs。 + - 如果配置的 Microsoft 输出格式失败,OpenClaw 会回退重试 MP3。 -OpenAI/ElevenLabs 输出格式按渠道固定(见上文)。 +OpenAI/ElevenLabs 输出格式会根据渠道固定(见上文)。 ## 自动 TTS 行为 启用后,OpenClaw 会: -- 如果回复已包含媒体或 `MEDIA:` 指令,则跳过 TTS。 +- 如果回复已经包含媒体或 `MEDIA:` 指令,则跳过 TTS。 - 跳过非常短的回复(少于 10 个字符)。 -- 在启用时使用 `agents.defaults.model.primary`(或 `summaryModel`)对长回复生成摘要。 +- 在启用时,使用 `agents.defaults.model.primary`(或 `summaryModel`)对长回复进行摘要。 - 将生成的音频附加到回复中。 -如果回复超过 `maxLength` 且摘要已关闭(或摘要模型没有 API key),则会跳过音频, -仅发送普通文本回复。 +如果回复超过 `maxLength` 且摘要关闭(或摘要模型没有 API key),则会跳过音频,并发送普通文本回复。 ## 流程图 -```text -Reply -> TTS enabled? - no -> send text - yes -> has media / MEDIA: / short? - yes -> send text - no -> length > limit? - no -> TTS -> attach audio - yes -> summary enabled? - no -> send text - yes -> summarize (summaryModel or agents.defaults.model.primary) - -> TTS -> attach audio +``` +回复 -> 是否启用 TTS? + 否 -> 发送文本 + 是 -> 是否有媒体 / MEDIA: / 太短? + 是 -> 发送文本 + 否 -> 长度 > 限制? + 否 -> TTS -> 附加音频 + 是 -> 是否启用摘要? + 否 -> 发送文本 + 是 -> 摘要(summaryModel 或 agents.defaults.model.primary) + -> TTS -> 附加音频 ``` ## 斜杠命令用法 只有一个命令:`/tts`。 -启用细节请参阅 [Slash commands](/zh-CN/tools/slash-commands)。 +启用细节请参见 [斜杠命令](/zh-CN/tools/slash-commands)。 -Discord 说明:`/tts` 是 Discord 的内置命令,因此 OpenClaw 会 -在该平台上注册 `/voice` 作为原生命令。文本形式的 `/tts ...` 仍然可用。 +Discord 说明:`/tts` 是 Discord 内置命令,因此 OpenClaw 会在该平台上注册 +`/voice` 作为原生命令。文本形式的 `/tts ...` 仍然可用。 -```text +``` /tts off /tts on /tts status @@ -486,26 +489,28 @@ Discord 说明:`/tts` 是 Discord 的内置命令,因此 OpenClaw 会 说明: -- 命令要求发送者已获授权(允许列表/所有者规则仍然适用)。 +- 命令要求发送方已获授权(allowlist/所有者规则仍然适用)。 - 必须启用 `commands.text` 或原生命令注册。 - 配置 `messages.tts.auto` 接受 `off|always|inbound|tagged`。 - `/tts on` 会将本地 TTS 偏好写为 `always`;`/tts off` 会写为 `off`。 - 当你希望默认值为 `inbound` 或 `tagged` 时,请使用配置。 -- `limit` 和 `summary` 存储在本地偏好中,而不是主配置中。 -- `/tts audio` 会生成一次性音频回复(不会将 TTS 切换为开启)。 -- `/tts status` 包含最近一次尝试的后备可见性: - - 成功后备:`Fallback: -> ` 加上 `Attempts: ...` - - 失败:`Error: ...` 加上 `Attempts: ...` +- `limit` 和 `summary` 存储在本地 prefs 中,而不是主配置中。 +- `/tts audio` 会生成一次性音频回复(不会开启 TTS)。 +- `/tts status` 包含最近一次尝试的回退可见性: + - 成功回退:`Fallback: -> ` 加 `Attempts: ...` + - 失败:`Error: ...` 加 `Attempts: ...` - 详细诊断:`Attempt details: provider:outcome(reasonCode) latency` -- OpenAI 和 ElevenLabs API 失败现在会包含已解析的提供商错误详情和请求 id(如果提供商返回),这些信息会显示在 TTS 错误/日志中。 +- OpenAI 和 ElevenLabs API 失败现在会包含已解析的提供商错误细节和请求 id(当提供商返回时),并会显示在 TTS 错误/日志中。 ## 智能体工具 `tts` 工具会将文本转换为语音,并返回一个用于回复投递的音频附件。 -当渠道为 Feishu、Matrix、Telegram 或 WhatsApp 时, -音频会作为语音消息投递,而不是文件附件。 +当渠道是 Feishu、Matrix、Telegram 或 WhatsApp 时, +音频会以语音消息而不是文件附件的形式发送。 +它接受可选的 `channel` 和 `timeoutMs` 字段;`timeoutMs` 是 +按次调用的提供商请求超时,单位为毫秒。 -## Gateway RPC +## Gateway 网关 RPC Gateway 网关方法: diff --git a/docs/zh-CN/tools/video-generation.md b/docs/zh-CN/tools/video-generation.md index 49e04f90f..e46a04d84 100644 --- a/docs/zh-CN/tools/video-generation.md +++ b/docs/zh-CN/tools/video-generation.md @@ -1,76 +1,76 @@ --- read_when: - 通过智能体生成视频 - - 配置视频生成 provider 和模型 +#+#+#+#+#+analysis to=functions.read 早点加盟_input={"path":"/home/runner/work/docs/docs/source/.agents/skills/openclaw-qa-testing/SKILL.md"} code + - 配置视频生成提供商和模型 - 了解 `video_generate` 工具参数 -summary: 使用 14 个 provider 后端,通过文本、图像或现有视频生成视频 +summary: 使用 14 个提供商后端,根据文本、图像或现有视频生成视频 title: 视频生成 x-i18n: - generated_at: "2026-04-23T21:10:46Z" + generated_at: "2026-04-23T23:22:42Z" model: gpt-5.4 provider: openai - source_hash: 67b3b0c669489dca7c0903dbd2ddd7b0f3438a3a722c5cb2b78850ecd1906866 + source_hash: 4fb4053d417e62d6145f6cd2bc2717ae120ca9a7cff34089ba65d4ba79ec8c75 source_path: tools/video-generation.md workflow: 15 --- -OpenClaw 智能体可以根据文本提示词、参考图像或现有视频生成视频。当前支持 14 个 provider 后端,每个后端都有不同的模型选项、输入模式和功能集。智能体会根据你的配置和可用的 API key 自动选择合适的 provider。 +OpenClaw 智能体可以根据文本提示、参考图像或现有视频生成视频。支持 14 个提供商后端,每个后端都有不同的模型选项、输入模式和功能集。智能体会根据你的配置和可用的 API key 自动选择合适的提供商。 -`video_generate` 工具只有在至少有一个视频生成 provider 可用时才会出现。如果你在智能体工具中看不到它,请设置 provider API key,或配置 `agents.defaults.videoGenerationModel`。 +只有在至少有一个视频生成提供商可用时,`video_generate` 工具才会出现。如果你在智能体工具中看不到它,请设置提供商 API key 或配置 `agents.defaults.videoGenerationModel`。 OpenClaw 将视频生成视为三种运行时模式: -- `generate`:用于不带参考媒体的文生视频请求 -- `imageToVideo`:当请求中包含一个或多个参考图像时使用 -- `videoToVideo`:当请求中包含一个或多个参考视频时使用 +- `generate`:用于没有参考媒体的文生视频请求 +- `imageToVideo`:当请求包含一个或多个参考图像时使用 +- `videoToVideo`:当请求包含一个或多个参考视频时使用 -Providers 可以支持这些模式中的任意子集。工具会在提交前校验当前模式,并在 `action=list` 中报告支持的模式。 +提供商可以支持这些模式中的任意子集。工具会在提交前验证当前模式,并在 `action=list` 中报告支持的模式。 ## 快速开始 -1. 为任意支持的 provider 设置 API key: +1. 为任一受支持的提供商设置 API key: ```bash export GEMINI_API_KEY="your-key" ``` -2. 可选地固定一个默认模型: +2. 可选:固定默认模型: ```bash openclaw config set agents.defaults.videoGenerationModel.primary "google/veo-3.1-fast-generate-preview" ``` -3. 向智能体发出请求: +3. 向智能体提出请求: -> Generate a 5-second cinematic video of a friendly lobster surfing at sunset. +> 生成一段 5 秒钟、电影感十足的视频,内容是一只友善的龙虾在日落时分冲浪。 -智能体会自动调用 `video_generate`。不需要工具 allowlist。 +智能体会自动调用 `video_generate`。无需将该工具加入允许列表。 ## 生成视频时会发生什么 -视频生成是异步的。当智能体在会话中调用 `video_generate` 时: +视频生成是异步的。当智能体在一个会话中调用 `video_generate` 时: -1. OpenClaw 将请求提交给 provider,并立即返回一个任务 ID。 -2. Provider 在后台处理该作业(通常需要 30 秒到 5 分钟,具体取决于 provider 和分辨率)。 -3. 当视频准备就绪后,OpenClaw 会通过一个内部完成事件唤醒同一会话。 -4. 智能体会将完成的视频发回原始对话中。 +1. OpenClaw 将请求提交给提供商,并立即返回一个任务 ID。 +2. 提供商在后台处理该任务(通常需要 30 秒到 5 分钟,具体取决于提供商和分辨率)。 +3. 当视频准备就绪时,OpenClaw 会通过一个内部完成事件唤醒同一个会话。 +4. 智能体会将生成完成的视频发布回原始对话中。 -当某个作业正在进行时,同一会话中的重复 `video_generate` 调用会返回当前任务状态,而不是启动新的生成任务。你可以使用 `openclaw tasks list` 或 `openclaw tasks show ` 在 CLI 中查看进度。 +当任务正在进行时,如果同一会话中再次调用 `video_generate`,将返回当前任务状态,而不是启动另一个生成任务。使用 `openclaw tasks list` 或 `openclaw tasks show ` 可以通过 CLI 检查进度。 -在没有会话支持的智能体运行场景之外(例如直接工具调用),该工具会回退为内联生成,并在同一轮中返回最终媒体路径。 +在非会话支持的智能体运行之外(例如直接调用工具),该工具会回退为内联生成,并在同一轮返回最终媒体路径。 ### 任务生命周期 -每个 `video_generate` 请求会经历四个状态: +每个 `video_generate` 请求会经历四种状态: -1. **queued** —— 任务已创建,等待 provider 接收。 -2. **running** —— provider 正在处理(通常需要 30 秒到 5 分钟,具体取决于 provider 和分辨率)。 -3. **succeeded** —— 视频已准备就绪;智能体被唤醒并将其发布回对话。 -4. **failed** —— provider 错误或超时;智能体被唤醒并附带错误详情。 +1. **queued** —— 任务已创建,正在等待提供商接受。 +2. **running** —— 提供商正在处理(通常需要 30 秒到 5 分钟,具体取决于提供商和分辨率)。 +3. **succeeded** —— 视频已准备好;智能体被唤醒并将其发布到对话中。 +4. **failed** —— 提供商错误或超时;智能体被唤醒并附带错误详情。 -从 CLI 查看状态: +通过 CLI 检查状态: ```bash openclaw tasks list @@ -78,153 +78,139 @@ openclaw tasks show openclaw tasks cancel ``` -防止重复:如果当前会话中已有一个 `queued` 或 `running` 状态的视频任务,`video_generate` 会返回现有任务状态,而不是启动新任务。若要显式检查状态而不触发新生成,请使用 `action: "status"`。 +防止重复:如果当前会话中已经有一个视频任务处于 `queued` 或 `running` 状态,`video_generate` 会返回现有任务状态,而不是启动新任务。使用 `action: "status"` 可以显式检查状态,而不会触发新的生成任务。 -## 支持的 providers +## 支持的提供商 -| Provider | 默认模型 | 文本 | 图像参考 | 视频参考 | API key | +| 提供商 | 默认模型 | 文本 | 图像参考 | 视频参考 | API key | | --------------------- | ------------------------------- | ---- | ---------------------------------------------------- | ---------------- | ---------------------------------------- | | Alibaba | `wan2.6-t2v` | 是 | 是(远程 URL) | 是(远程 URL) | `MODELSTUDIO_API_KEY` | -| BytePlus 1.0 | `seedance-1-0-pro-250528` | 是 | 最多 2 张图(仅 I2V 模型;首帧 + 末帧) | 否 | `BYTEPLUS_API_KEY` | -| BytePlus Seedance 1.5 | `seedance-1-5-pro-251215` | 是 | 最多 2 张图(通过角色指定首帧 + 末帧) | 否 | `BYTEPLUS_API_KEY` | -| BytePlus Seedance 2.0 | `dreamina-seedance-2-0-260128` | 是 | 最多 9 张参考图 | 最多 3 个视频 | `BYTEPLUS_API_KEY` | -| ComfyUI | `workflow` | 是 | 1 张图 | 否 | `COMFY_API_KEY` 或 `COMFY_CLOUD_API_KEY` | -| fal | `fal-ai/minimax/video-01-live` | 是 | 1 张图 | 否 | `FAL_KEY` | -| Google | `veo-3.1-fast-generate-preview` | 是 | 1 张图 | 1 个视频 | `GEMINI_API_KEY` | -| MiniMax | `MiniMax-Hailuo-2.3` | 是 | 1 张图 | 否 | `MINIMAX_API_KEY` | -| OpenAI | `sora-2` | 是 | 1 张图 | 1 个视频 | `OPENAI_API_KEY` | +| BytePlus(1.0) | `seedance-1-0-pro-250528` | 是 | 最多 2 张图像(仅 I2V 模型;首帧 + 末帧) | 否 | `BYTEPLUS_API_KEY` | +| BytePlus Seedance 1.5 | `seedance-1-5-pro-251215` | 是 | 最多 2 张图像(通过 role 指定首帧 + 末帧) | 否 | `BYTEPLUS_API_KEY` | +| BytePlus Seedance 2.0 | `dreamina-seedance-2-0-260128` | 是 | 最多 9 张参考图像 | 最多 3 个视频 | `BYTEPLUS_API_KEY` | +| ComfyUI | `workflow` | 是 | 1 张图像 | 否 | `COMFY_API_KEY` 或 `COMFY_CLOUD_API_KEY` | +| fal | `fal-ai/minimax/video-01-live` | 是 | 1 张图像 | 否 | `FAL_KEY` | +| Google | `veo-3.1-fast-generate-preview` | 是 | 1 张图像 | 1 个视频 | `GEMINI_API_KEY` | +| MiniMax | `MiniMax-Hailuo-2.3` | 是 | 1 张图像 | 否 | `MINIMAX_API_KEY` | +| OpenAI | `sora-2` | 是 | 1 张图像 | 1 个视频 | `OPENAI_API_KEY` | | Qwen | `wan2.6-t2v` | 是 | 是(远程 URL) | 是(远程 URL) | `QWEN_API_KEY` | -| Runway | `gen4.5` | 是 | 1 张图 | 1 个视频 | `RUNWAYML_API_SECRET` | -| Together | `Wan-AI/Wan2.2-T2V-A14B` | 是 | 1 张图 | 否 | `TOGETHER_API_KEY` | -| Vydra | `veo3` | 是 | 1 张图(`kling`) | 否 | `VYDRA_API_KEY` | -| xAI | `grok-imagine-video` | 是 | 1 张图 | 1 个视频 | `XAI_API_KEY` | +| Runway | `gen4.5` | 是 | 1 张图像 | 1 个视频 | `RUNWAYML_API_SECRET` | +| Together | `Wan-AI/Wan2.2-T2V-A14B` | 是 | 1 张图像 | 否 | `TOGETHER_API_KEY` | +| Vydra | `veo3` | 是 | 1 张图像(`kling`) | 否 | `VYDRA_API_KEY` | +| xAI | `grok-imagine-video` | 是 | 1 张图像 | 1 个视频 | `XAI_API_KEY` | -某些 provider 接受额外或替代的 API key 环境变量。详情请参阅各个[provider 页面](#related)。 +某些提供商接受其他附加或替代的 API key 环境变量。详情请参见各个[提供商页面](#related)。 -运行 `video_generate action=list` 可在运行时查看可用的 provider、模型和运行时模式。 +运行 `video_generate action=list` 可在运行时查看可用提供商、模型和运行时模式。 -### 声明式能力矩阵 +### 声明的能力矩阵 -这是 `video_generate`、契约测试和共享实时 sweep 所使用的显式模式契约。 +这是 `video_generate`、契约测试以及共享实时扫描所使用的显式模式契约。 -| Provider | `generate` | `imageToVideo` | `videoToVideo` | 当前共享实时 lanes | +| 提供商 | `generate` | `imageToVideo` | `videoToVideo` | 当前共享实时通道 | | -------- | ---------- | -------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -| Alibaba | 是 | 是 | 是 | `generate`、`imageToVideo`;`videoToVideo` 被跳过,因为该 provider 需要远程 `http(s)` 视频 URL | +| Alibaba | 是 | 是 | 是 | `generate`、`imageToVideo`;`videoToVideo` 已跳过,因为该提供商需要远程 `http(s)` 视频 URL | | BytePlus | 是 | 是 | 否 | `generate`、`imageToVideo` | -| ComfyUI | 是 | 是 | 否 | 不在共享 sweep 中;工作流专用覆盖位于 Comfy 测试中 | +| ComfyUI | 是 | 是 | 否 | 不在共享扫描中;特定于 workflow 的覆盖范围由 Comfy 测试负责 | | fal | 是 | 是 | 否 | `generate`、`imageToVideo` | -| Google | 是 | 是 | 是 | `generate`、`imageToVideo`;共享 `videoToVideo` 被跳过,因为当前基于缓冲区的 Gemini/Veo sweep 不接受该输入 | +| Google | 是 | 是 | 是 | `generate`、`imageToVideo`;共享的 `videoToVideo` 已跳过,因为当前基于缓冲区的 Gemini/Veo 扫描不接受该输入 | | MiniMax | 是 | 是 | 否 | `generate`、`imageToVideo` | -| OpenAI | 是 | 是 | 是 | `generate`、`imageToVideo`;共享 `videoToVideo` 被跳过,因为当前该组织/输入路径需要 provider 侧的 inpaint/remix 访问 | -| Qwen | 是 | 是 | 是 | `generate`、`imageToVideo`;`videoToVideo` 被跳过,因为该 provider 需要远程 `http(s)` 视频 URL | -| Runway | 是 | 是 | 是 | `generate`、`imageToVideo`;只有当所选模型为 `runway/gen4_aleph` 时才运行 `videoToVideo` | +| OpenAI | 是 | 是 | 是 | `generate`、`imageToVideo`;共享的 `videoToVideo` 已跳过,因为此组织/输入路径当前需要提供商侧的 inpaint/remix 访问 | +| Qwen | 是 | 是 | 是 | `generate`、`imageToVideo`;`videoToVideo` 已跳过,因为该提供商需要远程 `http(s)` 视频 URL | +| Runway | 是 | 是 | 是 | `generate`、`imageToVideo`;仅当所选模型为 `runway/gen4_aleph` 时才运行 `videoToVideo` | | Together | 是 | 是 | 否 | `generate`、`imageToVideo` | -| Vydra | 是 | 是 | 否 | `generate`;共享 `imageToVideo` 被跳过,因为内置 `veo3` 仅支持文本,而内置 `kling` 需要远程图像 URL | -| xAI | 是 | 是 | 是 | `generate`、`imageToVideo`;`videoToVideo` 被跳过,因为该 provider 当前需要远程 MP4 URL | +| Vydra | 是 | 是 | 否 | `generate`;共享的 `imageToVideo` 已跳过,因为内置 `veo3` 仅支持文本,而内置 `kling` 需要远程图像 URL | +| xAI | 是 | 是 | 是 | `generate`、`imageToVideo`;`videoToVideo` 已跳过,因为该提供商当前需要远程 MP4 URL | ## 工具参数 ### 必填 -| 参数 | 类型 | 描述 | +| 参数 | 类型 | 说明 | | --------- | ------ | ----------------------------------------------------------------------------- | | `prompt` | string | 要生成的视频文本描述(`action: "generate"` 时必填) | ### 内容输入 -| 参数 | 类型 | 描述 | +| 参数 | 类型 | 说明 | | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `image` | string | 单个参考图像(路径或 URL) | -| `images` | string[] | 多个参考图像(最多 9 张) | -| `imageRoles` | string[] | 与合并后的图像列表一一对应的可选位置角色提示。规范值:`first_frame`、`last_frame`、`reference_image` | +| `images` | string[] | 多个参考图像(最多 9 个) | +| `imageRoles` | string[] | 与合并后的图像列表按位置对应的可选角色提示。规范值:`first_frame`、`last_frame`、`reference_image` | | `video` | string | 单个参考视频(路径或 URL) | | `videos` | string[] | 多个参考视频(最多 4 个) | -| `videoRoles` | string[] | 与合并后的视频列表一一对应的可选位置角色提示。规范值:`reference_video` | -| `audioRef` | string | 单个参考音频(路径或 URL)。当 provider 支持音频输入时,可用于背景音乐或语音参考等 | +| `videoRoles` | string[] | 与合并后的视频列表按位置对应的可选角色提示。规范值:`reference_video` | +| `audioRef` | string | 单个参考音频(路径或 URL)。当提供商支持音频输入时,可用于例如背景音乐或语音参考 | | `audioRefs` | string[] | 多个参考音频(最多 3 个) | -| `audioRoles` | string[] | 与合并后的音频列表一一对应的可选位置角色提示。规范值:`reference_audio` | +| `audioRoles` | string[] | 与合并后的音频列表按位置对应的可选角色提示。规范值:`reference_audio` | -角色提示会按原样转发给 provider。规范值来自 -`VideoGenerationAssetRole` 联合类型,但 providers 也可能接受额外的 -角色字符串。`*Roles` 数组的条目数不能超过对应参考列表; -一旦出现 off-by-one 错误,就会返回清晰错误。 -使用空字符串可使某个槽位保持未设置。 +角色提示会按原样转发给提供商。规范值来自 `VideoGenerationAssetRole` 联合类型,但提供商也可能接受额外的角色字符串。`*Roles` 数组的条目数不得多于对应的参考列表;这类 off-by-one 错误会以清晰的错误信息失败。使用空字符串可以将某个位置留空不设值。 ### 风格控制 -| 参数 | 类型 | 描述 | +| 参数 | 类型 | 说明 | | ----------------- | ------- | --------------------------------------------------------------------------------------- | | `aspectRatio` | string | `1:1`、`2:3`、`3:2`、`3:4`、`4:3`、`4:5`、`5:4`、`9:16`、`16:9`、`21:9` 或 `adaptive` | | `resolution` | string | `480P`、`720P`、`768P` 或 `1080P` | -| `durationSeconds` | number | 目标时长(秒),会四舍五入到最接近的 provider 支持值 | -| `size` | string | 当 provider 支持时使用的尺寸提示 | -| `audio` | boolean | 当支持时,在输出中启用生成音频。它与 `audioRef*`(输入)不同 | -| `watermark` | boolean | 当支持时,切换 provider 的水印功能 | +| `durationSeconds` | number | 目标时长(秒)(会四舍五入到提供商支持的最接近值) | +| `size` | string | 当提供商支持时使用的尺寸提示 | +| `audio` | boolean | 在支持时为输出启用生成音频。它不同于 `audioRef*`(输入) | +| `watermark` | boolean | 在支持时切换提供商水印 | -`adaptive` 是一个 provider 专用哨兵值:对于在其能力中声明了 -`adaptive` 的 provider,会原样转发该值(例如 BytePlus -Seedance 使用它根据输入图像尺寸自动检测比例)。未声明该值的 -provider 会通过工具结果中的 `details.ignoredOverrides` 报告该值, -从而让该忽略行为可见。 +`adaptive` 是一个提供商特定的哨兵值:它会原样转发给在其能力中声明 `adaptive` 的提供商(例如 BytePlus Seedance 会用它根据输入图像尺寸自动检测比例)。未声明该能力的提供商会通过工具结果中的 `details.ignoredOverrides` 暴露该值,以便明确看到该值已被忽略。 ### 高级 -| 参数 | 类型 | 描述 | +| 参数 | 类型 | 说明 | | ----------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `action` | string | `"generate"`(默认)、`"status"` 或 `"list"` | -| `model` | string | provider/模型覆盖值(例如 `runway/gen4.5`) | +| `model` | string | 提供商/模型覆盖(例如 `runway/gen4.5`) | | `filename` | string | 输出文件名提示 | -| `providerOptions` | object | 作为 JSON 对象传递的 provider 专用选项(例如 `{"seed": 42, "draft": true}`)。如果 provider 声明了类型化 schema,则会校验键和值类型;未知键或不匹配项会导致该候选项在回退时被跳过。未声明 schema 的 provider 会按原样接收这些选项。运行 `video_generate action=list` 可查看每个 provider 接受哪些选项 | +| `timeoutMs` | number | 可选的提供商请求超时时间(毫秒) | +| `providerOptions` | object | 以 JSON 对象形式提供的提供商特定选项(例如 `{"seed": 42, "draft": true}`)。声明了类型化 schema 的提供商会验证键名和值类型;未知键或不匹配会在回退时跳过该候选项。未声明 schema 的提供商会原样接收这些选项。运行 `video_generate action=list` 可查看各个提供商接受哪些选项 | -并非所有 provider 都支持所有参数。OpenClaw 已经会将时长规范化到最接近的 provider 支持值;同时,当某个回退 provider 暴露不同的控制界面时,它还会重新映射诸如 size 到 aspect-ratio 之类的几何提示。真正不支持的覆盖项会尽最大努力被忽略,并在工具结果中以警告方式报告。硬性能力限制(例如参考输入过多)会在提交前直接失败。 +并非所有提供商都支持所有参数。OpenClaw 已经会将时长规范化为提供商支持的最接近值,并且在回退提供商暴露不同控制界面时,也会重新映射像尺寸到纵横比这样的几何提示。真正不受支持的覆盖项会尽最大努力被忽略,并在工具结果中作为警告报告。硬性能力限制(例如参考输入过多)会在提交前失败。 -工具结果会报告实际应用的设置。当 OpenClaw 在 provider 回退期间重新映射时长或几何参数时,返回的 `durationSeconds`、`size`、`aspectRatio` 和 `resolution` 值会反映实际提交的内容,而 `details.normalization` 则会记录从请求值到应用值的转换。 +工具结果会报告已应用的设置。当 OpenClaw 在提供商回退期间重新映射时长或几何参数时,返回的 `durationSeconds`、`size`、`aspectRatio` 和 `resolution` 值会反映实际提交的内容,而 `details.normalization` 会记录从请求值到应用值的转换。 -参考输入也会选择运行时模式: +参考输入也会决定运行时模式: -- 无参考媒体:`generate` +- 没有参考媒体:`generate` - 任意图像参考:`imageToVideo` - 任意视频参考:`videoToVideo` -- 参考音频输入不会改变解析后的模式;它们会叠加在图像/视频参考所选的模式之上,并且仅对声明了 `maxInputAudios` 的 provider 生效 +- 参考音频输入不会改变解析出的模式;它们会叠加在图像/视频参考所选定的模式之上,并且仅对声明了 `maxInputAudios` 的提供商有效 -图像和视频参考混用并不是稳定的共享能力界面。 -每次请求最好只使用一种参考类型。 +图像和视频参考混用不是稳定的共享能力界面。 +建议每个请求只使用一种参考类型。 #### 回退与类型化选项 -某些能力检查是在回退层而不是工具边界上应用的,这样即使请求超出了主 provider 的限制,也仍有机会在一个有能力的回退 provider 上运行: +某些能力检查是在回退层而不是工具边界执行的,这样即使请求超出了主提供商的限制,也仍然可以在支持该能力的回退提供商上运行: -- 如果当前候选项未声明 `maxInputAudios`(或声明为 - `0`),那么当请求中包含音频参考时,它会被跳过,并尝试下一个候选项。 -- 如果当前候选项的 `maxDurationSeconds` 小于请求的 - `durationSeconds`,并且候选项未声明 - `supportedDurationSeconds` 列表,则该候选项会被跳过。 -- 如果请求中包含 `providerOptions`,而当前候选项 - 显式声明了一个类型化 `providerOptions` schema,则当提供的键不在 schema 中,或值类型不匹配时,该候选项会被跳过。尚未声明 schema 的 provider 会按原样接收这些选项(向后兼容透传)。provider 还可以通过声明一个空 schema - (`capabilities.providerOptions: {}`)来显式拒绝所有 provider 选项,这种情况会产生与类型不匹配相同的跳过结果。 +- 如果当前候选项未声明 `maxInputAudios`(或将其声明为 `0`),那么当请求包含音频参考时,该候选项会被跳过,并尝试下一个候选项。 +- 如果当前候选项的 `maxDurationSeconds` 低于请求的 `durationSeconds`,并且该候选项未声明 `supportedDurationSeconds` 列表,则会被跳过。 +- 如果请求包含 `providerOptions`,且当前候选项显式声明了类型化的 `providerOptions` schema,那么当提供的键不在 schema 中或值类型不匹配时,该候选项会被跳过。尚未声明 schema 的提供商会原样接收这些选项(向后兼容的透传)。提供商可以通过声明空 schema(`capabilities.providerOptions: {}`)来显式选择不接受任何提供商选项,这会产生与类型不匹配相同的跳过行为。 -请求中的第一个跳过原因会以 `warn` 级别写入日志,以便运维人员看到 -其主 provider 被跳过;后续跳过则以 `debug` 级别记录,以保持长回退链安静。如果所有候选项都被跳过,聚合错误会包含每个候选项的跳过原因。 +请求中的第一个跳过原因会以 `warn` 级别记录,以便操作员看到主提供商为何被跳过;后续跳过会以 `debug` 级别记录,以避免冗长的回退链产生过多噪音。如果所有候选项都被跳过,聚合错误会包含每个候选项的跳过原因。 -## 动作 +## 操作 - **generate**(默认)—— 根据给定提示词和可选参考输入创建视频。 -- **status** —— 检查当前会话中正在进行的视频任务状态,而不启动新的生成。 -- **list** —— 显示可用的 providers、模型及其能力。 +- **status** —— 检查当前会话中正在进行的视频任务状态,而不启动新的生成任务。 +- **list** —— 显示可用提供商、模型及其能力。 ## 模型选择 -生成视频时,OpenClaw 会按以下顺序解析模型: +生成视频时,OpenClaw 按以下顺序解析模型: -1. **`model` 工具参数** —— 如果智能体在调用中显式指定了它。 +1. **`model` 工具参数** —— 如果智能体在调用中指定了它。 2. **`videoGenerationModel.primary`** —— 来自配置。 3. **`videoGenerationModel.fallbacks`** —— 按顺序尝试。 -4. **自动检测** —— 使用那些具有有效认证的 providers,先从当前默认 provider 开始,然后按字母顺序尝试剩余 providers。 +4. **自动检测** —— 使用拥有有效身份验证的提供商,从当前默认提供商开始,然后按字母顺序尝试其余提供商。 -如果某个 provider 失败,会自动尝试下一个候选项。如果所有候选项都失败,错误中会包含每次尝试的详细信息。 +如果某个提供商失败,会自动尝试下一个候选项。如果所有候选项都失败,错误中会包含每次尝试的详细信息。 -如果你希望视频生成仅使用显式的 `model`、`primary` 和 `fallbacks` -条目,请设置 `agents.defaults.mediaGenerationAutoProviderFallback: false`。 +如果你希望视频生成仅使用显式的 `model`、`primary` 和 `fallbacks` 条目,请设置 `agents.defaults.mediaGenerationAutoProviderFallback: false`。 ```json5 { @@ -239,30 +225,28 @@ provider 会通过工具结果中的 `details.ignoredOverrides` 报告该值, } ``` -## Provider 说明 +## 提供商说明 -| Provider | 说明 | +| 提供商 | 说明 | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Alibaba | 使用 DashScope/Model Studio 异步端点。参考图像和视频必须是远程 `http(s)` URL。 | -| BytePlus 1.0 | Provider id 为 `byteplus`。模型包括:`seedance-1-0-pro-250528`(默认)、`seedance-1-0-pro-t2v-250528`、`seedance-1-0-pro-fast-251015`、`seedance-1-0-lite-t2v-250428`、`seedance-1-0-lite-i2v-250428`。T2V 模型(`*-t2v-*`)不接受图像输入;I2V 模型和通用 `*-pro-*` 模型支持单张参考图像(首帧)。你可以按位置传入图像,或设置 `role: "first_frame"`。当提供了图像时,T2V 模型 ID 会自动切换到对应的 I2V 变体。支持的 `providerOptions` 键:`seed`(number)、`draft`(boolean,会强制 480p)、`camera_fixed`(boolean)。 | -| BytePlus Seedance 1.5 | 需要 [`@openclaw/byteplus-modelark`](https://www.npmjs.com/package/@openclaw/byteplus-modelark) 插件。Provider id 为 `byteplus-seedance15`。模型:`seedance-1-5-pro-251215`。使用统一的 `content[]` API。最多支持 2 张输入图像(first_frame + last_frame)。所有输入都必须是远程 `https://` URL。请在每张图像上设置 `role: "first_frame"` / `"last_frame"`,或按位置传入图像。`aspectRatio: "adaptive"` 会根据输入图像自动检测比例。`audio: true` 会映射到 `generate_audio`。`providerOptions.seed`(number)会被转发。 | -| BytePlus Seedance 2.0 | 需要 [`@openclaw/byteplus-modelark`](https://www.npmjs.com/package/@openclaw/byteplus-modelark) 插件。Provider id 为 `byteplus-seedance2`。模型:`dreamina-seedance-2-0-260128`、`dreamina-seedance-2-0-fast-260128`。使用统一的 `content[]` API。最多支持 9 张参考图像、3 个参考视频和 3 个参考音频。所有输入都必须是远程 `https://` URL。请为每个资源设置 `role` —— 支持值包括:`"first_frame"`、`"last_frame"`、`"reference_image"`、`"reference_video"`、`"reference_audio"`。`aspectRatio: "adaptive"` 会根据输入图像自动检测比例。`audio: true` 会映射到 `generate_audio`。`providerOptions.seed`(number)会被转发。 | -| ComfyUI | 由工作流驱动的本地或云执行。通过已配置图形支持文生视频和图生视频。 | -| fal | 对长时间运行作业使用基于队列的流程。仅支持单张图像参考。 | -| Google | 使用 Gemini/Veo。支持一张图像或一个视频参考。 | -| MiniMax | 仅支持单张图像参考。 | -| OpenAI | 仅会转发 `size` 覆盖值。其他风格覆盖值(`aspectRatio`、`resolution`、`audio`、`watermark`)会被忽略,并附带警告。 | -| Qwen | 与 Alibaba 使用相同的 DashScope 后端。参考输入必须是远程 `http(s)` URL;本地文件会被提前拒绝。 | -| Runway | 支持通过 data URI 使用本地文件。视频转视频需要 `runway/gen4_aleph`。纯文本运行支持 `16:9` 和 `9:16` 宽高比。 | -| Together | 仅支持单张图像参考。 | -| Vydra | 直接使用 `https://www.vydra.ai/api/v1`,以避免认证被重定向丢失。内置 `veo3` 仅支持文生视频;`kling` 需要远程图像 URL。 | +| BytePlus(1.0) | 提供商 id 为 `byteplus`。模型:`seedance-1-0-pro-250528`(默认)、`seedance-1-0-pro-t2v-250528`、`seedance-1-0-pro-fast-251015`、`seedance-1-0-lite-t2v-250428`、`seedance-1-0-lite-i2v-250428`。T2V 模型(`*-t2v-*`)不接受图像输入;I2V 模型和通用 `*-pro-*` 模型支持单张参考图像(首帧)。可按位置传递图像,或设置 `role: "first_frame"`。当提供图像时,T2V 模型 ID 会自动切换到对应的 I2V 变体。支持的 `providerOptions` 键:`seed`(number)、`draft`(boolean,会强制 480p)、`camera_fixed`(boolean)。 | +| BytePlus Seedance 1.5 | 需要 [`@openclaw/byteplus-modelark`](https://www.npmjs.com/package/@openclaw/byteplus-modelark) 插件。提供商 id 为 `byteplus-seedance15`。模型:`seedance-1-5-pro-251215`。使用统一的 `content[]` API。最多支持 2 张输入图像(`first_frame` + `last_frame`)。所有输入都必须是远程 `https://` URL。为每张图像设置 `role: "first_frame"` / `"last_frame"`,或按位置传递图像。`aspectRatio: "adaptive"` 会根据输入图像自动检测比例。`audio: true` 会映射为 `generate_audio`。`providerOptions.seed`(number)会被转发。 | +| BytePlus Seedance 2.0 | 需要 [`@openclaw/byteplus-modelark`](https://www.npmjs.com/package/@openclaw/byteplus-modelark) 插件。提供商 id 为 `byteplus-seedance2`。模型:`dreamina-seedance-2-0-260128`、`dreamina-seedance-2-0-fast-260128`。使用统一的 `content[]` API。最多支持 9 张参考图像、3 个参考视频和 3 个参考音频。所有输入都必须是远程 `https://` URL。为每个资源设置 `role`——支持的值有:`"first_frame"`、`"last_frame"`、`"reference_image"`、`"reference_video"`、`"reference_audio"`。`aspectRatio: "adaptive"` 会根据输入图像自动检测比例。`audio: true` 会映射为 `generate_audio`。`providerOptions.seed`(number)会被转发。 | +| ComfyUI | 由 workflow 驱动的本地或云端执行。通过已配置的图形支持文生视频和图生视频。 | +| fal | 对长时间运行任务使用基于队列的流程。仅支持单张参考图像。 | +| Google | 使用 Gemini/Veo。支持一张图像参考或一个视频参考。 | +| MiniMax | 仅支持单张参考图像。 | +| OpenAI | 只会转发 `size` 覆盖项。其他风格覆盖项(`aspectRatio`、`resolution`、`audio`、`watermark`)会被忽略,并附带警告。 | +| Qwen | 与 Alibaba 使用相同的 DashScope 后端。参考输入必须是远程 `http(s)` URL;本地文件会被预先拒绝。 | +| Runway | 通过 data URI 支持本地文件。视频转视频需要 `runway/gen4_aleph`。纯文本运行公开 `16:9` 和 `9:16` 两种纵横比。 | +| Together | 仅支持单张参考图像。 | +| Vydra | 直接使用 `https://www.vydra.ai/api/v1`,以避免身份验证在重定向中丢失。内置 `veo3` 仅支持文生视频;`kling` 需要远程图像 URL。 | | xAI | 支持文生视频、图生视频,以及远程视频编辑/扩展流程。 | -## Provider 能力模式 +## 提供商能力模式 -共享视频生成契约现在允许 provider 声明按模式区分的 -能力,而不仅仅是扁平的聚合限制。新的 provider -实现应优先使用显式模式块: +共享的视频生成契约现在允许提供商声明按模式划分的能力,而不仅仅是扁平化的聚合限制。新的提供商实现应优先使用显式模式块: ```typescript capabilities: { @@ -286,47 +270,43 @@ capabilities: { } ``` -像 `maxInputImages` 和 `maxInputVideos` 这样的扁平聚合字段,并不足以声明变换模式支持。Providers 应显式声明 -`generate`、`imageToVideo` 和 `videoToVideo`,这样实时测试、 -契约测试以及共享的 `video_generate` 工具才能确定性地校验模式支持。 +像 `maxInputImages` 和 `maxInputVideos` 这样的扁平聚合字段,不足以声明转换模式支持。提供商应显式声明 `generate`、`imageToVideo` 和 `videoToVideo`,这样实时测试、契约测试以及共享的 `video_generate` 工具才能以确定性方式验证模式支持。 ## 实时测试 -对共享内置 provider 的按需实时覆盖: +为共享内置提供商启用实时覆盖(可选): ```bash OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts ``` -仓库包装器: +仓库包装命令: ```bash pnpm test:live:media video ``` -该实时测试文件会从 `~/.profile` 中加载缺失的 provider 环境变量,默认优先使用 -实时/环境变量 API key,而不是已存储的认证配置档案,并默认运行一个适合发布的 smoke 测试: +这个实时测试文件会从 `~/.profile` 加载缺失的提供商环境变量,默认优先使用实时/环境 API key 而不是已存储的身份验证配置档案,并默认运行适合发布的烟雾测试: -- 对 sweep 中每个非 FAL provider 执行 `generate` -- 使用一秒钟的 lobster 提示词 -- 每个 provider 的操作上限由 `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` 控制 - (默认 `180000`) +- 对扫描中的每个非 FAL 提供商运行 `generate` +- 使用一秒钟的龙虾提示词 +- 每个提供商的操作上限来自 `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` + (默认值为 `180000`) -由于 provider 侧队列延迟可能主导发布时间,FAL 为按需启用: +FAL 需要显式启用,因为提供商侧的队列延迟可能主导发布时间: ```bash pnpm test:live:media video --video-providers fal ``` -设置 `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1` 还会运行共享 sweep 能够通过本地媒体安全执行的已声明变换模式: +设置 `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1`,还可以运行共享扫描能够使用本地媒体安全执行的已声明转换模式: - 当 `capabilities.imageToVideo.enabled` 时运行 `imageToVideo` -- 当 `capabilities.videoToVideo.enabled` 且该 provider/模型 - 在共享 sweep 中接受基于 buffer 的本地视频输入时运行 `videoToVideo` +- 当 `capabilities.videoToVideo.enabled` 且提供商/模型在共享扫描中接受基于缓冲区的本地视频输入时运行 `videoToVideo` -当前共享的 `videoToVideo` 实时 lane 覆盖: +目前共享的 `videoToVideo` 实时通道覆盖: -- 仅当你选择 `runway/gen4_aleph` 时覆盖 `runway` +- 仅 `runway`,并且只有在你选择 `runway/gen4_aleph` 时 ## 配置 @@ -353,13 +333,13 @@ openclaw config set agents.defaults.videoGenerationModel.primary "qwen/wan2.6-t2 ## 相关内容 -- [工具概览](/zh-CN/tools) -- [后台任务](/zh-CN/automation/tasks) —— 异步视频生成的任务跟踪 +- [Tools Overview](/zh-CN/tools) +- [Background Tasks](/zh-CN/automation/tasks) —— 异步视频生成的任务跟踪 - [Alibaba Model Studio](/zh-CN/providers/alibaba) -- [BytePlus(国际版)](/zh-CN/concepts/model-providers#byteplus-international) +- [BytePlus](/zh-CN/concepts/model-providers#byteplus-international) - [ComfyUI](/zh-CN/providers/comfy) - [fal](/zh-CN/providers/fal) -- [Google(Gemini)](/zh-CN/providers/google) +- [Google (Gemini)](/zh-CN/providers/google) - [MiniMax](/zh-CN/providers/minimax) - [OpenAI](/zh-CN/providers/openai) - [Qwen](/zh-CN/providers/qwen) @@ -367,5 +347,5 @@ openclaw config set agents.defaults.videoGenerationModel.primary "qwen/wan2.6-t2 - [Together AI](/zh-CN/providers/together) - [Vydra](/zh-CN/providers/vydra) - [xAI](/zh-CN/providers/xai) -- [配置参考](/zh-CN/gateway/configuration-reference#agent-defaults) -- [模型](/zh-CN/concepts/models) +- [Configuration Reference](/zh-CN/gateway/configuration-reference#agent-defaults) +- [Models](/zh-CN/concepts/models)