From 692b5508ecee356e675a2fff5cac21d2498a4bba Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Thu, 23 Apr 2026 08:17:47 +0000 Subject: [PATCH] chore(i18n): refresh zh-CN translations --- docs/zh-CN/gateway/configuration.md | 381 +++++------ docs/zh-CN/plugins/architecture.md | 992 ++++++++++++---------------- 2 files changed, 582 insertions(+), 791 deletions(-) diff --git a/docs/zh-CN/gateway/configuration.md b/docs/zh-CN/gateway/configuration.md index 98cbf2344..10984cb2f 100644 --- a/docs/zh-CN/gateway/configuration.md +++ b/docs/zh-CN/gateway/configuration.md @@ -2,36 +2,35 @@ read_when: - 首次设置 OpenClaw - 查找常见配置模式 - - 导航到特定配置章节 + - 跳转到特定配置章节 summary: 配置概览:常见任务、快速设置,以及完整参考的链接 title: 配置 x-i18n: - generated_at: "2026-04-23T07:25:07Z" + generated_at: "2026-04-23T08:14:07Z" model: gpt-5.4 provider: openai - source_hash: 6a68c5e4d375e0910b65fa4da2bcfc6fa560cbcba750778605420dc1b83eeb15 + source_hash: a674bbc73f3a501ffd47ef9396d55d6087806921cfb24ef576398022dd0248c3 source_path: gateway/configuration.md workflow: 15 --- # 配置 -OpenClaw 会从 `~/.openclaw/openclaw.json` 读取可选的 **JSON5** 配置。 -当前生效的配置路径必须是一个常规文件。对于由符号链接指向的 `openclaw.json` -布局,OpenClaw 自身发起的写入操作不提供支持;原子写入可能会替换该路径, -而不是保留符号链接。如果你将配置保存在默认状态目录之外, -请将 `OPENCLAW_CONFIG_PATH` 直接指向真实文件。 +OpenClaw 会从 `~/.openclaw/openclaw.json` 读取一个可选的 **JSON5** 配置。 +当前使用的配置路径必须是一个常规文件。对于由 OpenClaw 管理的写入操作,不支持将 `openclaw.json` +布局为符号链接;原子写入可能会替换该路径, +而不是保留符号链接。如果你将配置保存在默认状态目录之外,请将 `OPENCLAW_CONFIG_PATH` 直接指向真实文件。 -如果文件不存在,OpenClaw 会使用安全默认值。常见的添加配置原因包括: +如果该文件不存在,OpenClaw 会使用安全默认值。添加配置的常见原因包括: -- 连接渠道,并控制谁可以向机器人发送消息 +- 连接渠道并控制谁可以向机器人发消息 - 设置模型、工具、沙箱隔离或自动化(cron、hooks) - 调整会话、媒体、网络或 UI -查看[完整参考](/zh-CN/gateway/configuration-reference)以了解每个可用字段。 +请参阅[完整参考](/zh-CN/gateway/configuration-reference)了解所有可用字段。 -**刚开始接触配置?** 可以先运行 `openclaw onboard` 进行交互式设置,或者查看[配置示例](/zh-CN/gateway/configuration-examples)指南,获取可直接复制粘贴的完整配置。 +**刚接触配置?** 可先运行 `openclaw onboard` 进行交互式设置,或查看[配置示例](/zh-CN/gateway/configuration-examples)指南,获取可直接复制粘贴的完整配置。 ## 最小配置 @@ -61,43 +60,30 @@ OpenClaw 会从 `~/.openclaw/openclaw.json` 读取可选的 - 打开 [http://127.0.0.1:18789](http://127.0.0.1:18789),并使用 **配置** 标签页。 - Control UI 会根据实时配置 schema 渲染表单,其中包括字段 - `title` / `description` 文档元数据,以及在可用时提供的插件和渠道 schema, - 同时还提供一个 **原始 JSON** 编辑器作为兜底方式。对于下钻式 - UI 和其他工具,Gateway 网关 还会公开 `config.schema.lookup`,用于 - 获取单个路径范围内的 schema 节点及其直接子项摘要。 + 打开 [http://127.0.0.1:18789](http://127.0.0.1:18789) 并使用 **配置** 标签页。 + 控制 UI 会根据实时配置 schema 渲染表单,其中包括字段 + `title` / `description` 文档元数据,以及可用时的插件和渠道 schema, + 同时提供 **原始 JSON** 编辑器作为兜底方式。对于逐层下钻 + UI 和其他工具,Gateway 网关 还暴露了 `config.schema.lookup`, + 用于获取单个按路径限定的 schema 节点及其直接子项摘要。 - 直接编辑 `~/.openclaw/openclaw.json`。Gateway 网关 会监视该文件并自动应用更改(参见[热重载](#config-hot-reload))。 + 直接编辑 `~/.openclaw/openclaw.json`。Gateway 网关 会监视该文件并自动应用更改(请参阅[热重载](#config-hot-reload))。 ## 严格校验 -OpenClaw 只接受与 schema 完全匹配的配置。未知键名、格式错误的类型或无效值都会导致 Gateway 网关 **拒绝启动**。唯一的根级例外是 `$schema`(字符串),这样编辑器就可以附加 JSON Schema 元数据。 +OpenClaw 只接受完全符合 schema 的配置。未知键名、类型格式错误或无效值都会导致 Gateway 网关 **拒绝启动**。唯一的根级例外是 `$schema`(字符串),这样编辑器就可以附加 JSON Schema 元数据。 -Schema 工具说明: - -- `openclaw config schema` 会输出与 Control UI - 以及配置校验所使用的同一套 JSON Schema。 -- 请将该 schema 输出视为 `openclaw.json` 的权威机器可读契约; - 本概览和配置参考只是对其进行总结。 -- 字段 `title` 和 `description` 的值会被带入 schema 输出, - 供编辑器和表单工具使用。 -- 当存在匹配的字段文档时,嵌套对象、通配符(`*`)和数组项(`[]`)条目 - 会继承相同的文档元数据。 -- `anyOf` / `oneOf` / `allOf` 组合分支也会继承相同的文档 - 元数据,因此联合 / 交叉变体也能保留相同的字段帮助信息。 -- `config.schema.lookup` 会返回一个标准化的配置路径,以及一个浅层 - schema 节点(`title`、`description`、`type`、`enum`、`const`、常见边界 - 以及类似的校验字段)、匹配的 UI 提示元数据,以及直接子项 - 摘要,供下钻式工具使用。 -- 当 Gateway 网关 能够加载当前 manifest 注册表时,会合并运行时插件 / 渠道 schema。 -- `pnpm config:docs:check` 会检测面向文档的配置基线产物 - 与当前 schema 表面之间的漂移。 +`openclaw config schema` 会输出控制 UI +和校验所使用的规范 JSON Schema。`config.schema.lookup` 会获取单个按路径限定的节点以及 +子项摘要,用于逐层下钻工具。字段 `title`/`description` 文档元数据 +会传递到嵌套对象、通配符(`*`)、数组项(`[]`)以及 `anyOf`/ +`oneOf`/`allOf` 分支。加载 manifest 注册表后, +运行时插件和渠道 schema 也会合并进来。 当校验失败时: @@ -106,28 +92,19 @@ Schema 工具说明: - 运行 `openclaw doctor` 查看具体问题 - 运行 `openclaw doctor --fix`(或 `--yes`)应用修复 -Gateway 网关 在成功启动后还会保留一份可信的“最近一次已知良好”副本。如果 -`openclaw.json` 之后在 OpenClaw 外部被修改,并且不再通过校验,启动 -和热重载会将损坏文件保留为带时间戳的 `.clobbered.*` 快照, -恢复“最近一次已知良好”的副本,并记录一条醒目的警告日志说明恢复原因。 -启动读取恢复还会将配置大小突然显著下降、缺少配置元数据,以及 -缺少 `gateway.mode` 视为关键的 clobber 特征,前提是“最近一次已知良好” -副本中原本包含这些字段。 -如果一行状态 / 日志内容被意外追加到原本有效的 JSON -配置前面,Gateway 网关 启动和 `openclaw doctor --fix` 可以移除该前缀, -将被污染的文件保留为 `.clobbered.*`,并继续使用恢复后的 -JSON。 -下一次主智能体回合还会收到一条系统事件警告,告诉它配置已被 -恢复,且不得盲目重写。最近一次已知良好副本的提升会在已通过校验的启动后更新, -也会在接受的热重载后更新,包括由 OpenClaw 自身发起、且持久化文件哈希仍与已接受写入一致的配置写入。 -当候选配置包含被打码的密钥占位符, -例如 `***` 或缩短后的令牌值时,将跳过提升。 +每次成功启动后,Gateway 网关 都会保留一份可信的“最后已知正常”副本。 +如果之后 `openclaw.json` 未通过校验(或丢失 `gateway.mode`、体积 +明显缩小,或前面误加了一行日志),OpenClaw 会将损坏的文件 +保存为 `.clobbered.*`,恢复最后已知正常的副本,并记录恢复 +原因。下一次智能体回合也会收到系统事件警告,这样主 +智能体就不会盲目重写已恢复的配置。当候选配置包含已脱敏的密钥占位符(例如 `***`)时, +将其提升为最后已知正常副本的操作会被跳过。 ## 常见任务 - 每个渠道在 `channels.` 下都有自己的配置段。设置步骤请参阅对应的渠道页面: + 每个渠道在 `channels.` 下都有自己的配置段。请查看对应渠道页面了解设置步骤: - [WhatsApp](/zh-CN/channels/whatsapp) — `channels.whatsapp` - [Telegram](/zh-CN/channels/telegram) — `channels.telegram` @@ -140,7 +117,7 @@ JSON。 - [iMessage](/zh-CN/channels/imessage) — `channels.imessage` - [Mattermost](/zh-CN/channels/mattermost) — `channels.mattermost` - 所有渠道都共享相同的私信策略模式: + 所有渠道都遵循相同的私信策略模式: ```json5 { @@ -149,7 +126,7 @@ JSON。 enabled: true, botToken: "123:abc", dmPolicy: "pairing", // pairing | allowlist | open | disabled - allowFrom: ["tg:123"], // only for allowlist/open + allowFrom: ["tg:123"], // 仅用于 allowlist/open }, }, } @@ -158,7 +135,7 @@ JSON。 - 设置主模型和可选的回退模型: + 设置主模型以及可选的回退模型: ```json5 { @@ -177,31 +154,31 @@ JSON。 } ``` - - `agents.defaults.models` 定义模型目录,并作为 `/model` 的允许列表。 - - 使用 `openclaw config set agents.defaults.models '' --strict-json --merge` 可在不移除现有模型的情况下添加允许列表条目。如果普通替换会删除现有条目,则会被拒绝,除非你传入 `--replace`。 + - `agents.defaults.models` 用于定义模型目录,同时也是 `/model` 的允许列表。 + - 使用 `openclaw config set agents.defaults.models '' --strict-json --merge` 可在不移除现有模型的情况下添加允许列表条目。如果普通替换会移除条目,则会被拒绝,除非你传入 `--replace`。 - 模型引用使用 `provider/model` 格式(例如 `anthropic/claude-opus-4-6`)。 - - `agents.defaults.imageMaxDimensionPx` 控制转录 / 工具图像的缩放下限(默认值为 `1200`);在大量截图场景下,较低的值通常可减少视觉 token 使用量。 - - 请参阅[模型 CLI](/zh-CN/concepts/models) 了解如何在聊天中切换模型,参阅[模型故障转移](/zh-CN/concepts/model-failover) 了解凭证轮换和回退行为。 - - 对于自定义 / 自托管提供商,请参阅参考中的[自定义提供商](/zh-CN/gateway/configuration-reference#custom-providers-and-base-urls)。 + - `agents.defaults.imageMaxDimensionPx` 控制转录/工具图像的缩放上限(默认 `1200`);在大量使用截图的运行中,较低的值通常会减少视觉 token 的使用量。 + - 请参阅[模型 CLI](/zh-CN/concepts/models)了解如何在聊天中切换模型,并参阅[模型故障切换](/zh-CN/concepts/model-failover)了解凭证轮换和回退行为。 + - 对于自定义/自托管提供商,请参阅参考中的[自定义提供商](/zh-CN/gateway/configuration-reference#custom-providers-and-base-urls)。 - - 私信访问权限通过每个渠道的 `dmPolicy` 控制: + + 私信访问按渠道通过 `dmPolicy` 控制: - - `"pairing"`(默认):未知发送者会收到一次性配对码用于授权 - - `"allowlist"`:仅允许 `allowFrom` 中的发送者(或已配对的允许存储) - - `"open"`:允许所有传入私信(要求 `allowFrom: ["*"]`) + - `"pairing"`(默认):未知发送者会收到一次性配对码以供批准 + - `"allowlist"`:仅允许 `allowFrom` 中的发送者(或已配对允许存储中的发送者) + - `"open"`:允许所有入站私信(需要 `allowFrom: ["*"]`) - `"disabled"`:忽略所有私信 - 对于群组,请使用 `groupPolicy` + `groupAllowFrom` 或渠道特定的允许列表。 + 对于群组,请使用 `groupPolicy` + `groupAllowFrom` 或渠道专用允许列表。 - 有关各渠道的详细说明,请参阅[完整参考](/zh-CN/gateway/configuration-reference#dm-and-group-access)。 + 请参阅[完整参考](/zh-CN/gateway/configuration-reference#dm-and-group-access)了解各渠道的详细信息。 - 群组消息默认 **要求提及**。可按智能体配置模式: + 群组消息默认 **需要提及**。可按智能体配置模式: ```json5 { @@ -223,15 +200,15 @@ JSON。 } ``` - - **元数据提及**:原生 @ 提及(WhatsApp 点击提及、Telegram @bot 等) + - **元数据提及**:原生 @ 提及(WhatsApp 点按提及、Telegram @bot 等) - **文本模式**:`mentionPatterns` 中的安全正则模式 - - 有关各渠道覆盖项和自聊模式,请参阅[完整参考](/zh-CN/gateway/configuration-reference#group-chat-mention-gating)。 + - 请参阅[完整参考](/zh-CN/gateway/configuration-reference#group-chat-mention-gating)了解各渠道覆盖项和 self-chat 模式。 - 使用 `agents.defaults.skills` 作为共享基线,然后通过 - `agents.list[].skills` 覆盖特定智能体: + 使用 `agents.defaults.skills` 作为共享基线,然后通过 `agents.list[].skills` 覆盖特定 + 智能体: ```json5 { @@ -240,9 +217,9 @@ JSON。 skills: ["github", "weather"], }, list: [ - { id: "writer" }, // inherits github, weather - { id: "docs", skills: ["docs-search"] }, // replaces defaults - { id: "locked-down", skills: [] }, // no skills + { id: "writer" }, // 继承 github、weather + { id: "docs", skills: ["docs-search"] }, // 替换默认值 + { id: "locked-down", skills: [] }, // 不启用任何 Skills ], }, } @@ -257,7 +234,7 @@ JSON。 - 控制 Gateway 网关 对看起来已失活的渠道执行重启的激进程度: + 控制 Gateway 网关 对看起来已卡住的渠道进行重启的激进程度: ```json5 { @@ -279,10 +256,10 @@ JSON。 } ``` - - 设置 `gateway.channelHealthCheckMinutes: 0` 可全局禁用健康监控重启。 + - 将 `gateway.channelHealthCheckMinutes: 0` 设为 0 可在全局禁用健康监控重启。 - `channelStaleEventThresholdMinutes` 应大于或等于检查间隔。 - - 使用 `channels..healthMonitor.enabled` 或 `channels..accounts..healthMonitor.enabled`,可仅为某一个渠道或账号禁用自动重启,而无需关闭全局监控。 - - 请参阅[健康检查](/zh-CN/gateway/health)了解运维排障方法,并参阅[完整参考](/zh-CN/gateway/configuration-reference#gateway)了解全部字段。 + - 使用 `channels..healthMonitor.enabled` 或 `channels..accounts..healthMonitor.enabled`,可只为某个渠道或账号禁用自动重启,而无需禁用全局监控。 + - 请参阅[健康检查](/zh-CN/gateway/health)了解运维调试方法,并参阅[完整参考](/zh-CN/gateway/configuration-reference#gateway)了解所有字段。 @@ -292,7 +269,7 @@ JSON。 ```json5 { session: { - dmScope: "per-channel-peer", // recommended for multi-user + dmScope: "per-channel-peer", // 推荐用于多用户 threadBindings: { enabled: true, idleHours: 24, @@ -308,9 +285,9 @@ JSON。 ``` - `dmScope`:`main`(共享)| `per-peer` | `per-channel-peer` | `per-account-channel-peer` - - `threadBindings`:线程绑定会话路由的全局默认值(Discord 支持 `/focus`、`/unfocus`、`/agents`、`/session idle` 和 `/session max-age`)。 + - `threadBindings`:用于线程绑定会话路由的全局默认值(Discord 支持 `/focus`、`/unfocus`、`/agents`、`/session idle` 和 `/session max-age`)。 - 请参阅[会话管理](/zh-CN/concepts/session)了解作用域、身份关联和发送策略。 - - 请参阅[完整参考](/zh-CN/gateway/configuration-reference#session)了解全部字段。 + - 请参阅[完整参考](/zh-CN/gateway/configuration-reference#session)了解所有字段。 @@ -330,16 +307,16 @@ JSON。 } ``` - 先构建镜像:`scripts/sandbox-setup.sh` + 请先构建镜像:`scripts/sandbox-setup.sh` 请参阅[沙箱隔离](/zh-CN/gateway/sandboxing)了解完整指南,并参阅[完整参考](/zh-CN/gateway/configuration-reference#agentsdefaultssandbox)了解所有选项。 - 基于 relay 的推送在 `openclaw.json` 中配置。 + 基于 relay 的推送在 `openclaw.json` 中进行配置。 - 在 Gateway 网关 配置中设置: + 在 Gateway 网关 配置中设置以下内容: ```json5 { @@ -357,43 +334,43 @@ JSON。 } ``` - 对应的 CLI 写法: + CLI 等效命令: ```bash openclaw config set gateway.push.apns.relay.baseUrl https://relay.example.com ``` - 这会执行以下操作: + 作用如下: - - 让 Gateway 网关 能够通过外部 relay 发送 `push.test`、唤醒提示和重连唤醒。 - - 使用由已配对 iOS 应用转发的、按注册范围限定的发送授权。Gateway 网关 不需要部署范围的 relay token。 + - 让 Gateway 网关 可以通过外部 relay 发送 `push.test`、唤醒提示和重连唤醒。 + - 使用由已配对 iOS 应用转发的、以注册为作用域的发送授权。Gateway 网关 不需要部署范围的 relay token。 - 将每个基于 relay 的注册绑定到 iOS 应用所配对的 Gateway 网关 身份,因此其他 Gateway 网关 无法复用已存储的注册信息。 - - 让本地 / 手动 iOS 构建继续使用直连 APNs。基于 relay 的发送仅适用于通过 relay 完成注册的官方分发构建。 - - 必须与官方 / TestFlight iOS 构建中内置的 relay base URL 匹配,这样注册和发送流量才能到达同一个 relay 部署。 + - 本地/手动 iOS 构建仍使用直接 APNs。基于 relay 的发送仅适用于通过 relay 完成注册的官方分发构建。 + - 必须与官方/TestFlight iOS 构建中内置的 relay 基础 URL 保持一致,这样注册流量和发送流量才能到达同一个 relay 部署。 端到端流程: - 1. 安装一个使用相同 relay base URL 编译的官方 / TestFlight iOS 构建。 + 1. 安装一个使用相同 relay 基础 URL 编译的官方/TestFlight iOS 构建。 2. 在 Gateway 网关 上配置 `gateway.push.apns.relay.baseUrl`。 3. 将 iOS 应用与 Gateway 网关 配对,并让节点会话和操作员会话都连接上。 - 4. iOS 应用获取 Gateway 网关 身份,使用 App Attest 加上应用回执向 relay 注册,然后将基于 relay 的 `push.apns.register` 负载发布到已配对的 Gateway 网关。 + 4. iOS 应用获取 Gateway 网关 身份,使用 App Attest 和应用收据向 relay 注册,然后将基于 relay 的 `push.apns.register` 负载发布到已配对的 Gateway 网关。 5. Gateway 网关 存储 relay 句柄和发送授权,然后将其用于 `push.test`、唤醒提示和重连唤醒。 - 运维说明: + 运行说明: - - 如果你将 iOS 应用切换到另一个 Gateway 网关,请重新连接该应用,以便它发布绑定到新 Gateway 网关 的 relay 注册。 + - 如果你将 iOS 应用切换到另一个 Gateway 网关,请重新连接该应用,以便它发布一个绑定到该 Gateway 网关 的新 relay 注册。 - 如果你发布了一个指向不同 relay 部署的新 iOS 构建,应用会刷新其缓存的 relay 注册,而不是复用旧的 relay 来源。 兼容性说明: - `OPENCLAW_APNS_RELAY_BASE_URL` 和 `OPENCLAW_APNS_RELAY_TIMEOUT_MS` 仍可作为临时环境变量覆盖项使用。 - - `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true` 仍是仅限 loopback 的开发逃生舱;不要在配置中持久化 HTTP relay URL。 + - `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true` 仍然是仅限 local loopback 的开发逃生阀;不要在配置中持久化 HTTP relay URL。 - 请参阅[iOS 应用](/zh-CN/platforms/ios#relay-backed-push-for-official-builds)了解端到端流程,并参阅[认证与信任流程](/zh-CN/platforms/ios#authentication-and-trust-flow)了解 relay 安全模型。 + 请参阅 [iOS App](/zh-CN/platforms/ios#relay-backed-push-for-official-builds) 了解端到端流程,并参阅 [Authentication and trust flow](/zh-CN/platforms/ios#authentication-and-trust-flow) 了解 relay 安全模型。 - + ```json5 { agents: { @@ -407,10 +384,10 @@ JSON。 } ``` - - `every`:时长字符串(`30m`、`2h`)。设置为 `0m` 可禁用。 + - `every`:时长字符串(`30m`、`2h`)。设为 `0m` 可禁用。 - `target`:`last` | `none` | ``(例如 `discord`、`matrix`、`telegram` 或 `whatsapp`) - - `directPolicy`:对私信式 heartbeat 目标可设置为 `allow`(默认)或 `block` - - 请参阅[Heartbeat](/zh-CN/gateway/heartbeat)了解完整指南。 + - `directPolicy`:用于私信式 heartbeat 目标的 `allow`(默认)或 `block` + - 请参阅 [Heartbeat](/zh-CN/gateway/heartbeat) 了解完整指南。 @@ -429,9 +406,9 @@ JSON。 } ``` - - `sessionRetention`:从 `sessions.json` 中清理已完成的隔离运行会话(默认值为 `24h`;设置为 `false` 可禁用)。 + - `sessionRetention`:从 `sessions.json` 中清理已完成的隔离运行会话(默认 `24h`;设为 `false` 可禁用)。 - `runLog`:按大小和保留行数清理 `cron/runs/.jsonl`。 - - 请参阅[Cron 作业](/zh-CN/automation/cron-jobs)了解功能概览和 CLI 示例。 + - 请参阅 [Cron jobs](/zh-CN/automation/cron-jobs) 了解功能概览和 CLI 示例。 @@ -460,20 +437,20 @@ JSON。 ``` 安全说明: - - 将所有 hook / webhook 负载内容都视为不可信输入。 + - 将所有 hook/webhook 负载内容都视为不可信输入。 - 使用专用的 `hooks.token`;不要复用共享的 Gateway 网关 token。 - - Hook 认证仅支持请求头(`Authorization: Bearer ...` 或 `x-openclaw-token`);查询字符串 token 会被拒绝。 - - `hooks.path` 不能为 `/`;请将 webhook 入口保持在专用子路径下,例如 `/hooks`。 - - 除非是在进行严格限定范围的调试,否则请保持不安全内容绕过标志处于禁用状态(`hooks.gmail.allowUnsafeExternalContent`、`hooks.mappings[].allowUnsafeExternalContent`)。 - - 如果你启用了 `hooks.allowRequestSessionKey`,也应同时设置 `hooks.allowedSessionKeyPrefixes`,以约束调用方可选的会话键。 - - 对于由 hook 驱动的智能体,优先使用强力的现代模型层级和严格工具策略(例如仅消息传递,并尽可能启用沙箱隔离)。 + - Hook 身份验证仅支持请求头(`Authorization: Bearer ...` 或 `x-openclaw-token`);查询字符串 token 会被拒绝。 + - `hooks.path` 不能为 `/`;请将 webhook 入口保留在专用子路径下,例如 `/hooks`。 + - 保持不安全内容绕过标志为禁用状态(`hooks.gmail.allowUnsafeExternalContent`、`hooks.mappings[].allowUnsafeExternalContent`),除非你是在进行严格限定范围的调试。 + - 如果你启用了 `hooks.allowRequestSessionKey`,也要设置 `hooks.allowedSessionKeyPrefixes` 以限制调用方可选择的会话键。 + - 对于由 hook 驱动的智能体,优先使用更强的现代模型层级和严格的工具策略(例如仅限消息传递,并尽可能配合沙箱隔离)。 请参阅[完整参考](/zh-CN/gateway/configuration-reference#hooks)了解所有映射选项和 Gmail 集成。 - 运行多个隔离的智能体,并为它们分别配置工作区和会话: + 运行多个彼此隔离的智能体,并分别使用独立工作区和会话: ```json5 { @@ -490,12 +467,12 @@ JSON。 } ``` - 请参阅[多智能体](/zh-CN/concepts/multi-agent)和[完整参考](/zh-CN/gateway/configuration-reference#multi-agent-routing)了解绑定规则和每个智能体的访问配置文件。 + 请参阅 [Multi-Agent](/zh-CN/concepts/multi-agent) 和[完整参考](/zh-CN/gateway/configuration-reference#multi-agent-routing)了解绑定规则和每个智能体的访问配置文件。 - 使用 `$include` 组织大型配置: + 使用 `$include` 来组织大型配置: ```json5 // ~/.openclaw/openclaw.json @@ -508,18 +485,18 @@ JSON。 } ``` - - **单个文件**:替换所在对象 - - **文件数组**:按顺序深度合并(后者优先) - - **同级键**:在 includes 之后合并(覆盖 include 中的值) - - **嵌套 includes**:最多支持 10 层嵌套 + - **单个文件**:替换其所在对象 + - **文件数组**:按顺序深度合并(后者覆盖前者) + - **同级键**:在 include 之后合并(覆盖被包含值) + - **嵌套 include**:支持,最多 10 层 - **相对路径**:相对于包含它的文件进行解析 - - **OpenClaw 自有写入**:当一次写入只更改一个由单文件 include 支持的顶级区段时, - 例如 `plugins: { $include: "./plugins.json5" }`, + - **由 OpenClaw 管理的写入**:当一次写入只更改一个顶级分区, + 且该分区由单文件 include 支撑时,例如 `plugins: { $include: "./plugins.json5" }`, OpenClaw 会更新该被包含文件,并保持 `openclaw.json` 不变 - - **不支持的透传写入**:对于根 include、include 数组,以及带有同级覆盖的 includes, - OpenClaw 自有写入会以失败关闭的方式处理, - 而不是将配置拍平 - - **错误处理**:对缺失文件、解析错误和循环 include 提供清晰错误信息 + - **不支持的透传写入**:根级 include、include 数组以及带有 + 同级覆盖项的 include,在 OpenClaw 管理的写入场景下会以安全关闭方式失败, + 而不会将配置拍平 + - **错误处理**:对于缺失文件、解析错误和循环 include 提供清晰错误信息 @@ -529,26 +506,26 @@ JSON。 Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改——大多数设置都不需要手动重启。 直接编辑文件在通过校验前会被视为不可信。监视器会等待 -编辑器临时写入 / 重命名抖动稳定下来,读取最终文件,并通过恢复 -最近一次已知良好的配置来拒绝无效的外部编辑。OpenClaw 自有的 -配置写入在写入前也会经过同样的 schema 门禁;像删除 `gateway.mode` -或将文件缩小到原来一半以下这样的破坏性覆盖会被拒绝, +编辑器的临时写入/重命名抖动稳定下来,读取最终文件,并通过恢复最后已知正常配置来拒绝 +无效的外部编辑。由 OpenClaw 管理的 +配置写入在写入前也会通过同样的 schema 门控;像删除 `gateway.mode` +或将文件缩小到不足原来一半这类破坏性覆盖,会被拒绝, 并保存为 `.rejected.*` 以供检查。 如果你在日志中看到 `Config auto-restored from last-known-good` 或 -`config reload restored last-known-good config`,请检查 `openclaw.json` -旁边对应的 `.clobbered.*` 文件,修复被拒绝的负载,然后运行 -`openclaw config validate`。请参阅 [Gateway 网关 故障排除](/zh-CN/gateway/troubleshooting#gateway-restored-last-known-good-config) +`config reload restored last-known-good config`,请检查 +`openclaw.json` 旁边对应的 `.clobbered.*` 文件,修复被拒绝的负载,然后运行 +`openclaw config validate`。请参阅[Gateway 网关 故障排除](/zh-CN/gateway/troubleshooting#gateway-restored-last-known-good-config) 了解恢复检查清单。 ### 重载模式 | 模式 | 行为 | | ---------------------- | --------------------------------------------------------------------------------------- | -| **`hybrid`**(默认) | 立即热应用安全更改。对关键更改会自动重启。 | -| **`hot`** | 仅热应用安全更改。需要重启时会记录警告——由你自行处理。 | +| **`hybrid`**(默认) | 立即热应用安全更改。对于关键更改会自动重启。 | +| **`hot`** | 仅热应用安全更改。当需要重启时会记录警告——由你来处理。 | | **`restart`** | 任何配置更改都会重启 Gateway 网关,不论是否安全。 | -| **`off`** | 禁用文件监视。更改会在下一次手动重启时生效。 | +| **`off`** | 禁用文件监视。更改将在下次手动重启时生效。 | ```json5 { @@ -558,105 +535,65 @@ Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改—— } ``` -### 哪些可以热应用,哪些需要重启 +### 哪些会热应用,哪些需要重启 大多数字段都可以在不停机的情况下热应用。在 `hybrid` 模式下,需要重启的更改会自动处理。 | 类别 | 字段 | 需要重启? | | ------------------- | ----------------------------------------------------------------- | --------------- | -| 渠道 | `channels.*`、`web`(WhatsApp)——所有内置和渠道插件 | 否 | -| 智能体和模型 | `agent`、`agents`、`models`、`routing` | 否 | +| 渠道 | `channels.*`、`web`(WhatsApp)——所有内置和插件渠道 | 否 | +| 智能体与模型 | `agent`、`agents`、`models`、`routing` | 否 | | 自动化 | `hooks`、`cron`、`agent.heartbeat` | 否 | | 会话与消息 | `session`、`messages` | 否 | | 工具与媒体 | `tools`、`browser`、`skills`、`audio`、`talk` | 否 | -| UI 与杂项 | `ui`、`logging`、`identity`、`bindings` | 否 | +| UI 与其他 | `ui`、`logging`、`identity`、`bindings` | 否 | | Gateway 网关 服务器 | `gateway.*`(port、bind、auth、tailscale、TLS、HTTP) | **是** | | 基础设施 | `discovery`、`canvasHost`、`plugins` | **是** | -`gateway.reload` 和 `gateway.remote` 是例外——更改它们 **不会** 触发重启。 +`gateway.reload` 和 `gateway.remote` 是例外——更改它们**不会**触发重启。 ### 重载规划 -当你编辑一个通过 `$include` 引用的源文件时,OpenClaw 会根据源文件编写时的布局来规划 -重载,而不是根据拍平后的内存视图。 -这让热重载决策(热应用还是重启)即使在 -单个顶级区段位于其自身包含文件中的情况下也能保持可预测,例如 -`plugins: { $include: "./plugins.json5" }`。如果源布局存在歧义, -重载规划会以失败关闭的方式处理。 +当你编辑通过 `$include` 引用的源文件时,OpenClaw 会根据源文件作者定义的布局来规划 +重载,而不是基于拍平后的内存视图。 +这样即使 +某个顶级分区位于单独的被包含文件中,例如 +`plugins: { $include: "./plugins.json5" }`,热重载决策(热应用还是重启)也会保持可预测。 +如果源布局存在歧义,重载规划会以安全关闭方式失败。 ## 配置 RPC(程序化更新) +对于通过 Gateway 网关 API 写入配置的工具,推荐使用以下流程: + +- `config.schema.lookup`:检查一个子树(浅层 schema 节点 + 子项 + 摘要) +- `config.get`:获取当前快照以及 `hash` +- `config.patch`:进行部分更新(JSON merge patch:对象合并,`null` + 删除,数组替换) +- `config.apply`:仅在你打算替换整个配置时使用 +- `update.run`:执行显式自更新并重启 + -控制平面写入 RPC(`config.apply`、`config.patch`、`update.run`)会按每个 `deviceId+clientIp` 限速为 **每 60 秒 3 次请求**。触发限制时,RPC 会返回 `UNAVAILABLE` 和 `retryAfterMs`。 +控制平面写入(`config.apply`、`config.patch`、`update.run`)会按 +每个 `deviceId+clientIp` 在每 60 秒内限制为 3 次请求。 +重启请求会被合并,然后在两次重启周期之间强制执行 30 秒冷却时间。 -安全 / 默认流程: +部分 patch 示例: -- `config.schema.lookup`:检查单个路径范围内的配置子树,返回浅层 - schema 节点、匹配的提示元数据,以及直接子项摘要 -- `config.get`:获取当前快照 + 哈希 -- `config.patch`:首选的部分更新路径 -- `config.apply`:仅用于整份配置替换 -- `update.run`:显式执行自更新 + 重启 +```bash +openclaw gateway call config.get --params '{}' # 获取 payload.hash +openclaw gateway call config.patch --params '{ + "raw": "{ channels: { telegram: { groups: { \"*\": { requireMention: false } } } } }", + "baseHash": "" +}' +``` -如果你不是要替换整个配置,优先使用 `config.schema.lookup` -然后再用 `config.patch`。 - - - - 在一步中完成整份配置的校验 + 写入,并重启 Gateway 网关。 - - - `config.apply` 会替换**整个配置**。部分更新请使用 `config.patch`,单个键请使用 `openclaw config set`。 - - - 参数: - - - `raw`(字符串)— 整份配置的 JSON5 负载 - - `baseHash`(可选)— 来自 `config.get` 的配置哈希(当配置已存在时为必填) - - `sessionKey`(可选)— 重启后唤醒 ping 使用的会话键 - - `note`(可选)— 重启哨兵使用的备注 - - `restartDelayMs`(可选)— 重启前延迟(默认 `2000`) - - 当已有重启处于待处理 / 进行中时,重启请求会被合并;并且两次重启周期之间会应用 30 秒冷却时间。 - - ```bash - openclaw gateway call config.get --params '{}' # capture payload.hash - openclaw gateway call config.apply --params '{ - "raw": "{ agents: { defaults: { workspace: \"~/.openclaw/workspace\" } } }", - "baseHash": "", - "sessionKey": "agent:main:whatsapp:direct:+15555550123" - }' - ``` - - - - - 将部分更新合并到现有配置中(JSON merge patch 语义): - - - 对象会递归合并 - - `null` 会删除键 - - 数组会整体替换 - - 参数: - - - `raw`(字符串)— 仅包含要更改键名的 JSON5 - - `baseHash`(必填)— 来自 `config.get` 的配置哈希 - - `sessionKey`、`note`、`restartDelayMs` — 与 `config.apply` 相同 - - 重启行为与 `config.apply` 一致:会合并待处理的重启请求,并在两次重启周期之间设置 30 秒冷却时间。 - - ```bash - openclaw gateway call config.patch --params '{ - "raw": "{ channels: { telegram: { groups: { \"*\": { requireMention: false } } } } }", - "baseHash": "" - }' - ``` - - - +`config.apply` 和 `config.patch` 都接受 `raw`、`baseHash`、`sessionKey`、 +`note` 和 `restartDelayMs`。`baseHash` 对 `config.patch` 是必需的, +而当配置已存在时,也建议为 `config.apply` 提供它。 ## 环境变量 @@ -665,7 +602,7 @@ OpenClaw 会从父进程读取环境变量,另外还会读取: - 当前工作目录中的 `.env`(如果存在) - `~/.openclaw/.env`(全局后备) -这两个文件都不会覆盖已存在的环境变量。你也可以在配置中设置内联环境变量: +这两个文件都不会覆盖现有环境变量。你也可以在配置中设置内联环境变量: ```json5 { @@ -677,7 +614,7 @@ OpenClaw 会从父进程读取环境变量,另外还会读取: ``` - 如果启用,且预期键名未设置,OpenClaw 会运行你的登录 shell,并且只导入缺失的键: + 如果已启用且预期键名尚未设置,OpenClaw 会运行你的登录 shell,并且只导入缺失的键: ```json5 { @@ -687,11 +624,11 @@ OpenClaw 会从父进程读取环境变量,另外还会读取: } ``` -对应环境变量:`OPENCLAW_LOAD_SHELL_ENV=1` +等效环境变量:`OPENCLAW_LOAD_SHELL_ENV=1` - 你可以在任意配置字符串值中使用 `${VAR_NAME}` 引用环境变量: + 可在任意配置字符串值中使用 `${VAR_NAME}` 引用环境变量: ```json5 { @@ -702,15 +639,15 @@ OpenClaw 会从父进程读取环境变量,另外还会读取: 规则: -- 只匹配大写名称:`[A-Z_][A-Z0-9_]*` -- 缺失 / 为空的变量会在加载时抛出错误 -- 使用 `$${VAR}` 可输出字面值 -- 在 `$include` 文件中同样有效 +- 仅匹配大写名称:`[A-Z_][A-Z0-9_]*` +- 缺失/为空的环境变量会在加载时抛出错误 +- 使用 `$${VAR}` 转义以输出字面量 +- 在 `$include` 文件中也可用 - 内联替换:`"${BASE}/v1"` → `"https://api.example.com/v1"` - + 对于支持 SecretRef 对象的字段,你可以使用: ```json5 @@ -743,8 +680,8 @@ OpenClaw 会从父进程读取环境变量,另外还会读取: } ``` -SecretRef 详情(包括用于 `env` / `file` / `exec` 的 `secrets.providers`)请参阅[密钥管理](/zh-CN/gateway/secrets)。 -支持的凭证路径列在 [SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface) 中。 +有关 SecretRef 的详细信息(包括用于 `env`/`file`/`exec` 的 `secrets.providers`),请参阅[密钥管理](/zh-CN/gateway/secrets)。 +支持的凭证路径列在[SecretRef 凭证范围](/zh-CN/reference/secretref-credential-surface)中。 请参阅[环境](/zh-CN/help/environment)了解完整的优先级和来源。 diff --git a/docs/zh-CN/plugins/architecture.md b/docs/zh-CN/plugins/architecture.md index f4c8e72dd..da7807795 100644 --- a/docs/zh-CN/plugins/architecture.md +++ b/docs/zh-CN/plugins/architecture.md @@ -1,17 +1,17 @@ --- read_when: - 构建或调试原生 OpenClaw 插件 - - 了解插件能力模型或归属边界 + - 理解插件能力模型或归属边界 - 处理插件加载流水线或注册表 - - 实现 provider 运行时钩子或渠道插件 + - 实现提供商运行时钩子或渠道插件 sidebarTitle: Internals summary: 插件内部机制:能力模型、归属、契约、加载流水线和运行时辅助工具 title: 插件内部机制 x-i18n: - generated_at: "2026-04-23T07:25:46Z" + generated_at: "2026-04-23T08:14:04Z" model: gpt-5.4 provider: openai - source_hash: e7500ddc49feb828c65b0ec856aafdd53d52c965c32232bb518eb218f686ebf0 + source_hash: d3d5e4b9c48c2a0fc8116733e38a745bac5dfdbe65fdea8e9be6563b4051d805 source_path: plugins/architecture.md workflow: 15 --- @@ -19,131 +19,131 @@ x-i18n: # 插件内部机制 - 这是**深度架构参考**。如需实用指南,请参见: - - [安装和使用插件](/zh-CN/tools/plugin) — 用户指南 - - [入门指南](/zh-CN/plugins/building-plugins) — 第一个插件教程 - - [渠道插件](/zh-CN/plugins/sdk-channel-plugins) — 构建消息渠道 - - [提供商插件](/zh-CN/plugins/sdk-provider-plugins) — 构建模型提供商 - - [SDK 概览](/zh-CN/plugins/sdk-overview) — 导入映射和注册 API + 这是**深度架构参考**。如需实用指南,请参阅: + - [安装和使用插件](/zh-CN/tools/plugin) —— 用户指南 + - [入门指南](/zh-CN/plugins/building-plugins) —— 第一个插件教程 + - [渠道插件](/zh-CN/plugins/sdk-channel-plugins) —— 构建消息渠道 + - [提供商插件](/zh-CN/plugins/sdk-provider-plugins) —— 构建模型提供商 + - [SDK 概览](/zh-CN/plugins/sdk-overview) —— import map 和注册 API 本页介绍 OpenClaw 插件系统的内部架构。 -## 公开能力模型 +## 公共能力模型 能力是 OpenClaw 内部公开的**原生插件**模型。每个原生 OpenClaw 插件都会针对一种或多种能力类型进行注册: -| 能力 | 注册方式 | 示例插件 | -| ------------------------ | ------------------------------------------------ | ------------------------------------ | -| 文本推理 | `api.registerProvider(...)` | `openai`, `anthropic` | -| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`, `anthropic` | -| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | -| 实时转录 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | -| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | `openai` | -| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | -| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | -| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | -| 视频生成 | `api.registerVideoGenerationProvider(...)` | `qwen` | -| Web 抓取 | `api.registerWebFetchProvider(...)` | `firecrawl` | -| Web 搜索 | `api.registerWebSearchProvider(...)` | `google` | -| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`, `matrix` | +| 能力 | 注册方法 | 示例插件 | +| ---------------------- | ------------------------------------------------ | ------------------------------------ | +| 文本推理 | `api.registerProvider(...)` | `openai`, `anthropic` | +| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`, `anthropic` | +| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | +| 实时转录 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | +| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | `openai` | +| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | +| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | +| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | +| 视频生成 | `api.registerVideoGenerationProvider(...)` | `qwen` | +| Web 抓取 | `api.registerWebFetchProvider(...)` | `firecrawl` | +| Web 搜索 | `api.registerWebSearchProvider(...)` | `google` | +| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`, `matrix` | -一个注册了零种能力、但提供钩子、工具或服务的插件,是**仅钩子**插件。这种模式目前仍被完全支持。 +一个注册了零个能力、但提供钩子、工具或服务的插件,属于**仅 legacy hook** 插件。这种模式目前仍然受到完全支持。 ### 外部兼容性立场 -能力模型已经在核心中落地,并且当前已被内置 / 原生插件使用,但外部插件兼容性仍然需要比“它已导出,因此它已冻结”更严格的标准。 +能力模型已经在核心中落地,并已被当前的内置 / 原生插件使用,但外部插件的兼容性仍需要比“它已导出,因此它已冻结”更严格的标准。 -当前指导原则: +当前指导如下: -- **现有外部插件:** 保持基于钩子的集成继续可用;将其视为兼容性基线 -- **新的内置 / 原生插件:** 优先使用显式能力注册,而不是依赖特定厂商的深入接入或新的仅钩子设计 -- **采用能力注册的外部插件:** 允许,但除非文档明确将某个契约标记为稳定,否则应将能力相关的辅助接口视为仍在演进中 +- **现有外部插件:** 保持基于 hook 的集成可正常工作;将其视为兼容性的基线 +- **新的内置 / 原生插件:** 优先使用显式能力注册,而不是特定供应商的内部访问或新的仅 hook 设计 +- **采用能力注册的外部插件:** 允许,但除非文档明确将某个契约标记为稳定,否则应将能力专用的辅助接口视为仍在演进中 实际规则: - 能力注册 API 是预期的发展方向 -- 在过渡期间,旧式钩子仍然是对外部插件最安全、最不容易破坏兼容性的路径 -- 已导出的辅助子路径并不全都同等稳定;优先使用文档化的狭义契约,而不是偶然暴露出的辅助导出 +- 在过渡期间,legacy hook 仍然是对外部插件来说最安全、最不易破坏的路径 +- 并非所有导出的辅助子路径都同等重要;优先使用文档化的狭义契约,而不是偶然导出的辅助接口 ### 插件形态 -OpenClaw 会根据每个已加载插件的实际注册行为(而不仅仅是静态元数据)将其归类为一种形态: +OpenClaw 会根据每个已加载插件的实际注册行为来判定其形态(而不仅仅是静态元数据): -- **plain-capability** —— 只注册一种能力类型(例如仅提供 provider 的插件,如 `mistral`) +- **plain-capability** —— 仅注册一种能力类型(例如仅提供商插件 `mistral`) - **hybrid-capability** —— 注册多种能力类型(例如 `openai` 同时拥有文本推理、语音、媒体理解和图像生成) -- **hook-only** —— 仅注册钩子(类型化或自定义),不注册能力、工具、命令或服务 +- **hook-only** —— 仅注册 hooks(类型化或自定义),不注册能力、工具、命令或服务 - **non-capability** —— 注册工具、命令、服务或路由,但不注册能力 -使用 `openclaw plugins inspect ` 可以查看插件的形态和能力拆分。详见 [CLI 参考](/zh-CN/cli/plugins#inspect)。 +使用 `openclaw plugins inspect ` 可查看插件的形态和能力细分。详见 [CLI 参考](/zh-CN/cli/plugins#inspect)。 -### 旧式钩子 +### Legacy hooks -`before_agent_start` 钩子仍然作为仅钩子插件的兼容路径而被支持。现实中的旧插件仍然依赖它。 +`before_agent_start` hook 仍然作为仅 hook 插件的兼容路径受到支持。现实中的 legacy 插件仍然依赖它。 -方向: +方向如下: -- 保持其可用 -- 将其文档化为旧式能力 -- 对于模型 / provider 覆盖工作,优先使用 `before_model_resolve` +- 保持其正常工作 +- 在文档中将其标记为 legacy +- 对于模型 / 提供商覆盖工作,优先使用 `before_model_resolve` - 对于提示词变更工作,优先使用 `before_prompt_build` -- 只有在真实使用量下降,并且夹具覆盖证明迁移安全后,才考虑移除 +- 只有在真实使用量下降且 fixture 覆盖证明迁移安全后,才考虑移除 ### 兼容性信号 当你运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,可能会看到以下标签之一: -| 信号 | 含义 | -| ------------------------ | ------------------------------------------------------------ | -| **config valid** | 配置可正常解析,插件可正常解析 | -| **compatibility advisory** | 插件使用了受支持但较旧的模式(例如 `hook-only`) | -| **legacy warning** | 插件使用了 `before_agent_start`,该项已弃用 | -| **hard error** | 配置无效,或者插件加载失败 | +| 信号 | 含义 | +| -------------------------- | ------------------------------------------------------------ | +| **config valid** | 配置解析正常,且插件可解析 | +| **compatibility advisory** | 插件使用了受支持但较旧的模式(例如 `hook-only`) | +| **legacy warning** | 插件使用了 `before_agent_start`,该接口已弃用 | +| **hard error** | 配置无效,或插件加载失败 | -目前,`hook-only` 和 `before_agent_start` 都不会导致你的插件失效 —— `hook-only` 只是提示性信息,而 `before_agent_start` 只会触发警告。这些信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。 +`hook-only` 和 `before_agent_start` 当前都不会导致你的插件失效——`hook-only` 只是提示,而 `before_agent_start` 只会触发警告。这些信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。 ## 架构概览 -OpenClaw 的插件系统分为四层: +OpenClaw 的插件系统有四层: -1. **清单 + 发现** - OpenClaw 会从配置路径、工作区根目录、全局插件根目录和内置插件中发现候选插件。发现流程会优先读取原生 `openclaw.plugin.json` 清单,以及受支持的 bundle 清单。 -2. **启用 + 验证** - 核心决定某个已发现插件是启用、禁用、阻止,还是被选中用于某个排他槽位(例如 memory)。 -3. **运行时加载** - 原生 OpenClaw 插件会通过 jiti 在进程内加载,并将能力注册到中央注册表中。兼容的 bundle 会被规范化为注册表记录,而无需导入运行时代码。 +1. **Manifest + 设备发现** + OpenClaw 会从已配置路径、workspace 根目录、全局插件根目录以及内置插件中查找候选插件。设备发现会优先读取原生 `openclaw.plugin.json` manifests,以及受支持的 bundle manifests。 +2. **启用 + 验证** + 核心决定已发现的插件是已启用、已禁用、已阻止,还是被选中用于某个独占槽位(例如 memory)。 +3. **运行时加载** + 原生 OpenClaw 插件会通过 jiti 在进程内加载,并将能力注册到中央注册表中。兼容的 bundles 会在不导入运行时代码的情况下规范化为注册表记录。 4. **表面消费** - OpenClaw 的其余部分会读取注册表,以公开工具、渠道、provider 设置、钩子、HTTP 路由、CLI 命令和服务。 + OpenClaw 的其余部分会读取注册表,以暴露工具、渠道、提供商设置、hooks、HTTP 路由、CLI 命令和服务。 -对于插件 CLI,根命令发现专门分为两个阶段: +对于插件 CLI 本身,根命令发现分为两个阶段: -- 解析阶段元数据来自 `registerCli(..., { descriptors: [...] })` -- 真正的插件 CLI 模块可以保持延迟加载,并在首次调用时注册 +- 解析阶段的元数据来自 `registerCli(..., { descriptors: [...] })` +- 真正的插件 CLI 模块可以保持懒加载,并在首次调用时注册 -这样既能让插件自有的 CLI 代码保留在插件内部,又能让 OpenClaw 在解析前预留根命令名称。 +这样既能让插件拥有的 CLI 代码保留在插件内部,又能让 OpenClaw 在解析前预留根命令名称。 -重要的设计边界: +重要的设计边界是: -- 发现 + 配置验证应该基于**清单 / schema 元数据**完成,而无需执行插件代码 +- 设备发现 + 配置验证应该仅依赖 **manifest / schema 元数据** 即可工作,而无需执行插件代码 - 原生运行时行为来自插件模块的 `register(api)` 路径 -这种拆分让 OpenClaw 能够在完整运行时激活之前,完成配置验证、解释缺失 / 已禁用插件,并构建 UI / schema 提示。 +这种拆分让 OpenClaw 能在完整运行时尚未激活之前,先验证配置、解释缺失 / 已禁用的插件,并构建 UI / schema 提示。 -### 渠道插件和共享消息工具 +### 渠道插件与共享消息工具 -对于常规聊天操作,渠道插件无需单独注册发送 / 编辑 / 反应工具。OpenClaw 在核心中保留了一个共享的 `message` 工具,而渠道插件负责其背后的渠道特定发现和执行。 +对于常规聊天操作,渠道插件无需单独注册发送 / 编辑 / 反应工具。OpenClaw 在核心中保留一个共享的 `message` 工具,而渠道插件则拥有其背后的渠道专用发现和执行逻辑。 -当前边界如下: +当前的边界如下: -- 核心拥有共享 `message` 工具宿主、提示词接线、会话 / 线程簿记以及执行分发 -- 渠道插件拥有作用域内动作发现、能力发现,以及任何渠道特定的 schema 片段 -- 渠道插件拥有 provider 特定的会话对话语法,例如对话 id 如何编码线程 id,或如何从父对话继承 +- 核心拥有共享 `message` 工具宿主、提示词接线、会话 / 线程记录和执行分发 +- 渠道插件拥有作用域化动作发现、能力发现,以及任何渠道专用的 schema 片段 +- 渠道插件拥有提供商专用的会话对话语法,例如对话 id 如何编码线程 id,或如何从父对话继承 - 渠道插件通过其动作适配器执行最终动作 -对于渠道插件,SDK 接口为 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现调用允许插件一起返回其可见动作、能力和 schema 贡献,从而避免这些部分发生漂移。 +对于渠道插件,SDK 表面是 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现调用允许插件同时返回其可见动作、能力和 schema 贡献,从而避免这些部分彼此漂移。 -当某个渠道特定的消息工具参数携带媒体来源(例如本地路径或远程媒体 URL)时,插件还应从 `describeMessageTool(...)` 返回 `mediaSourceParams`。核心使用这个显式列表来应用沙箱路径规范化和出站媒体访问提示,而不需要硬编码插件自有的参数名。 -这里应优先使用按动作划分的映射,而不是整个渠道范围的扁平列表,这样仅用于 profile 的媒体参数就不会在 `send` 等无关动作中被规范化。 +当某个渠道专用 message-tool 参数携带媒体来源(例如本地路径或远程媒体 URL)时,插件还应从 `describeMessageTool(...)` 返回 `mediaSourceParams`。核心会使用这个显式列表来应用沙箱路径规范化和出站媒体访问提示,而不会硬编码插件拥有的参数名称。 +这里应优先使用按动作划分的映射,而不是某个渠道范围内的扁平列表,这样仅限 profile 的媒体参数就不会在 `send` 等无关动作上被规范化。 核心会将运行时作用域传入该发现步骤。重要字段包括: @@ -156,86 +156,86 @@ OpenClaw 的插件系统分为四层: - `agentId` - 受信任的入站 `requesterSenderId` -这对上下文敏感型插件很重要。渠道可以根据活动账户、当前房间 / 线程 / 消息,或受信任的请求者身份来隐藏或公开消息动作,而无需在核心 `message` 工具中硬编码渠道特定分支。 +这对于上下文敏感的插件很重要。渠道可以根据活动账户、当前房间 / 线程 / 消息,或受信任的请求者身份来隐藏或暴露消息动作,而无需在核心 `message` 工具中硬编码渠道专用分支。 -这也是为什么嵌入式 runner 路由变更仍然属于插件工作:runner 负责将当前聊天 / 会话身份转发到插件发现边界,这样共享 `message` 工具才能为当前轮次公开正确的、由渠道拥有的表面。 +这也是为什么嵌入式 runner 路由改动仍然属于插件工作:runner 负责将当前聊天 / 会话身份转发到插件发现边界,以便共享的 `message` 工具能够为当前轮次暴露正确的、由渠道拥有的表面。 -对于渠道自有的执行辅助工具,内置插件应将执行运行时保留在它们自己的扩展模块中。核心不再在 `src/agents/tools` 下拥有 Discord、Slack、Telegram 或 WhatsApp 的消息动作运行时。 -我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置插件应直接从自己的扩展模块中导入本地运行时代码。 +对于渠道拥有的执行辅助工具,内置插件应将执行运行时保留在它们自己的扩展模块中。核心不再拥有位于 `src/agents/tools` 下的 Discord、Slack、Telegram 或 WhatsApp 消息动作运行时。 +我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置插件应直接从其扩展拥有的模块导入本地运行时代码。 -同样的边界也适用于一般意义上的按 provider 命名的 SDK 接缝:核心不应导入 Slack、Discord、Signal、WhatsApp 或类似扩展的渠道特定便捷 barrel。如果核心需要某种行为,要么消费该内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么将该需求提升为共享 SDK 中的狭义通用能力。 +相同的边界也适用于一般意义上按提供商命名的 SDK 接缝:核心不应导入 Slack、Discord、Signal、WhatsApp 或类似扩展的渠道专用便捷 barrel。如果核心需要某种行为,要么消费内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么将该需求提升为共享 SDK 中狭义的通用能力。 -对投票而言,当前有两条执行路径: +对于投票,当前有两条执行路径: -- `outbound.sendPoll` 是适用于符合通用投票模型的渠道的共享基线 -- `actions.handleAction("poll")` 是用于渠道特定投票语义或额外投票参数的首选路径 +- `outbound.sendPoll` 是适用于符合通用投票模型渠道的共享基线 +- `actions.handleAction("poll")` 是适用于渠道专用投票语义或额外投票参数的首选路径 -现在,核心会在插件投票分发拒绝该动作之后,才回退到共享投票解析,因此插件自有的投票处理器可以接受渠道特定的投票字段,而不会先被通用投票解析器拦住。 +现在,核心会在插件投票分发拒绝该动作之后,才延迟执行共享投票解析,因此插件拥有的投票处理器可以接受渠道专用投票字段,而不会先被通用投票解析器拦住。 -完整启动序列请参见 [加载流水线](#load-pipeline)。 +完整启动顺序请参阅[加载流水线](#load-pipeline)。 ## 能力归属模型 -OpenClaw 将原生插件视为某个**公司**或某个**功能**的归属边界,而不是一个杂乱无章的无关集成集合。 +OpenClaw 将原生插件视为**公司**或**功能**的归属边界,而不是无关集成的大杂烩。 这意味着: -- 公司插件通常应拥有该公司的所有面向 OpenClaw 的表面 -- 功能插件通常应拥有它引入的完整功能表面 -- 渠道应消费共享的核心能力,而不是临时重新实现 provider 行为 +- 公司插件通常应拥有该公司的所有 OpenClaw 对外表面 +- 功能插件通常应拥有其引入的完整功能表面 +- 渠道应消费共享的核心能力,而不是临时重新实现提供商行为 示例: -- 内置 `openai` 插件拥有 OpenAI 模型 provider 行为,以及 OpenAI 的语音、实时语音、媒体理解和图像生成行为 -- 内置 `elevenlabs` 插件拥有 ElevenLabs 语音行为 -- 内置 `microsoft` 插件拥有 Microsoft 语音行为 -- 内置 `google` 插件拥有 Google 模型 provider 行为,以及 Google 的媒体理解、图像生成和 Web 搜索行为 -- 内置 `firecrawl` 插件拥有 Firecrawl Web 抓取行为 -- 内置 `minimax`、`mistral`、`moonshot` 和 `zai` 插件拥有它们各自的媒体理解后端 -- 内置 `qwen` 插件拥有 Qwen 文本 provider 行为,以及媒体理解和视频生成行为 -- `voice-call` 插件是一个功能插件:它拥有通话传输、工具、CLI、路由和 Twilio 媒体流桥接,但它会消费共享的语音、实时转录和实时语音能力,而不是直接导入厂商插件 +- 内置的 `openai` 插件拥有 OpenAI 模型提供商行为,以及 OpenAI 语音 + 实时语音 + 媒体理解 + 图像生成行为 +- 内置的 `elevenlabs` 插件拥有 ElevenLabs 语音行为 +- 内置的 `microsoft` 插件拥有 Microsoft 语音行为 +- 内置的 `google` 插件拥有 Google 模型提供商行为,以及 Google 媒体理解 + 图像生成 + Web 搜索行为 +- 内置的 `firecrawl` 插件拥有 Firecrawl Web 抓取行为 +- 内置的 `minimax`、`mistral`、`moonshot` 和 `zai` 插件拥有它们各自的媒体理解后端 +- 内置的 `qwen` 插件拥有 Qwen 文本提供商行为,以及媒体理解和视频生成行为 +- `voice-call` 插件是一个功能插件:它拥有通话传输、工具、CLI、路由以及 Twilio 媒体流桥接,但它会消费共享的语音、实时转录和实时语音能力,而不是直接导入供应商插件 预期的最终状态是: -- OpenAI 即使同时覆盖文本模型、语音、图像以及未来的视频能力,也仍然存在于一个插件中 -- 其他厂商也可以对自己的表面区域采用相同方式 -- 渠道并不关心哪个厂商插件拥有某个 provider;它们消费的是由核心公开的共享能力契约 +- 即使 OpenAI 横跨文本模型、语音、图像和未来的视频,它仍然位于一个插件中 +- 另一个供应商也可以对其自身的表面区域采用相同方式 +- 渠道并不关心哪个供应商插件拥有该提供商;它们消费的是由核心暴露的共享能力契约 -这是关键区别: +这就是关键区别: - **plugin** = 归属边界 - **capability** = 可由多个插件实现或消费的核心契约 -因此,如果 OpenClaw 添加了一个新领域,例如视频,首先要问的不是“哪个 provider 应该硬编码视频处理?”。首先要问的是“核心的视频能力契约是什么?”。一旦这个契约存在,厂商插件就可以针对它进行注册,而渠道 / 功能插件也可以消费它。 +因此,如果 OpenClaw 新增了诸如视频之类的新领域,第一个问题不应是“哪个提供商应该硬编码视频处理?”而应该是“核心视频能力契约是什么?”一旦该契约存在,供应商插件就可以针对它进行注册,渠道 / 功能插件也可以消费它。 如果该能力尚不存在,通常正确的做法是: 1. 在核心中定义缺失的能力 -2. 通过插件 API / 运行时以类型化方式公开它 -3. 让渠道 / 功能针对该能力完成接线 -4. 让厂商插件注册实现 +2. 通过插件 API / 运行时以类型化方式暴露它 +3. 让渠道 / 功能对接该能力 +4. 让供应商插件注册实现 -这样可以在保持归属明确的同时,避免核心行为依赖单一厂商或一次性的插件特定代码路径。 +这样可以保持归属明确,同时避免核心行为依赖单一供应商或某个一次性的插件专用代码路径。 ### 能力分层 -在决定代码应放在哪里时,请使用以下心智模型: +决定代码应放在哪里时,请使用这个心智模型: - **核心能力层**:共享编排、策略、回退、配置合并规则、交付语义和类型化契约 -- **厂商插件层**:厂商特定 API、认证、模型目录、语音合成、图像生成、未来的视频后端、用量端点 -- **渠道 / 功能插件层**:Slack / Discord / voice-call / 等集成,它们消费核心能力并在某个表面上呈现出来 +- **供应商插件层**:供应商专用 API、身份验证、模型目录、语音合成、图像生成、未来的视频后端、使用量端点 +- **渠道 / 功能插件层**:Slack / Discord / voice-call / 等集成,它们消费核心能力并将其呈现在某个表面上 -例如,TTS 遵循以下形态: +例如,TTS 遵循如下结构: -- 核心拥有回复时 TTS 策略、回退顺序、偏好和渠道投递 +- 核心拥有回复时 TTS 策略、回退顺序、偏好和渠道交付 - `openai`、`elevenlabs` 和 `microsoft` 拥有合成实现 - `voice-call` 消费电话 TTS 运行时辅助工具 -未来的能力也应优先采用相同模式。 +未来的能力也应优先采用同样的模式。 ### 多能力公司插件示例 -从外部看,公司插件应当是内聚的。如果 OpenClaw 拥有模型、语音、实时转录、实时语音、媒体理解、图像生成、视频生成、Web 抓取和 Web 搜索的共享契约,那么某个厂商可以在一个地方拥有它的全部表面: +一个公司插件从外部看起来应当是内聚的。如果 OpenClaw 具有用于模型、语音、实时转录、实时语音、媒体理解、图像生成、视频生成、Web 抓取和 Web 搜索的共享契约,那么一个供应商就可以在同一个地方拥有其所有表面: ```ts import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry"; @@ -289,48 +289,46 @@ const plugin: OpenClawPluginDefinition = { export default plugin; ``` -重要的不是具体的辅助函数名称。重要的是这种形态: +重要的不是确切的辅助函数名称,而是这种结构: -- 一个插件拥有厂商表面 +- 一个插件拥有该供应商表面 - 核心仍然拥有能力契约 -- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是厂商代码 -- 契约测试可以断言该插件确实注册了它声称拥有的能力 +- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是供应商代码 +- 契约测试可以断言该插件已注册它声称拥有的能力 ### 能力示例:视频理解 -OpenClaw 已经将图像 / 音频 / 视频理解视为一个共享能力。相同的归属模型也适用于这里: +OpenClaw 已经将图像 / 音频 / 视频理解视为一种共享能力。相同的归属模型也适用于这里: 1. 核心定义媒体理解契约 -2. 厂商插件按适用情况注册 `describeImage`、`transcribeAudio` 和 `describeVideo` -3. 渠道和功能插件消费共享核心行为,而不是直接接入厂商代码 +2. 供应商插件按适用情况注册 `describeImage`、`transcribeAudio` 和 `describeVideo` +3. 渠道和功能插件消费共享的核心行为,而不是直接连接到供应商代码 -这样可以避免将某个 provider 对视频的假设固化进核心。插件拥有厂商表面;核心拥有能力契约和回退行为。 +这样可以避免将某个提供商对视频的假设固化进核心中。插件拥有供应商表面;核心拥有能力契约和回退行为。 -视频生成已经采用相同顺序:核心拥有类型化能力契约和运行时辅助工具,而厂商插件则注册 `api.registerVideoGenerationProvider(...)` 实现来对接该契约。 +视频生成也已经采用了同样的顺序:核心拥有类型化能力契约和运行时辅助工具,供应商插件则针对其注册 `api.registerVideoGenerationProvider(...)` 实现。 -需要具体的发布检查清单吗?请参见 -[能力扩展手册](/zh-CN/plugins/architecture)。 +需要一个具体的发布清单吗?请参阅[能力扩展手册](/zh-CN/plugins/architecture)。 -## 契约和约束 +## 契约与约束 -插件 API 表面被有意设计为类型化,并集中在 -`OpenClawPluginApi` 中。该契约定义了受支持的注册点,以及插件可以依赖的运行时辅助工具。 +插件 API 表面是有意进行类型化并集中在 `OpenClawPluginApi` 中的。这个契约定义了受支持的注册点,以及插件可依赖的运行时辅助工具。 -这很重要,因为: +这很重要,原因如下: -- 插件作者可以获得一个稳定的内部标准 -- 核心可以拒绝重复归属,例如两个插件注册同一个 provider id -- 启动时可以为格式错误的注册提供可操作的诊断信息 -- 契约测试可以约束内置插件的归属,防止无声漂移 +- 插件作者获得一种稳定的内部标准 +- 核心可以拒绝重复归属,例如两个插件注册相同的 provider id +- 启动阶段可以为格式错误的注册提供可执行的诊断信息 +- 契约测试可以强制执行内置插件的归属,并防止静默漂移 这里有两层约束: -1. **运行时注册约束** - 插件注册表会在插件加载时验证注册内容。例如:重复的 provider id、重复的语音 provider id,以及格式错误的注册,都会产生插件诊断,而不是导致未定义行为。 -2. **契约测试** - 在测试运行期间,内置插件会被捕获到契约注册表中,这样 OpenClaw 就可以显式断言归属。目前这已用于模型 provider、语音 provider、Web 搜索 provider 和内置注册归属。 +1. **运行时注册约束** + 插件注册表会在插件加载时验证注册内容。例如:重复的 provider id、重复的 speech provider id 以及格式错误的注册,都会产生插件诊断,而不是导致未定义行为。 +2. **契约测试** + 在测试运行期间,内置插件会被捕获到契约注册表中,这样 OpenClaw 就可以明确断言归属。如今这已用于模型提供商、语音提供商、Web 搜索提供商以及内置注册归属。 -实际效果是,OpenClaw 能够预先知道哪个插件拥有哪个表面。这使得核心和渠道可以无缝组合,因为归属是声明式的、类型化的并且可测试,而不是隐式的。 +实际效果是,OpenClaw 能够预先知道哪个插件拥有哪个表面。这使得核心和渠道可以无缝组合,因为归属是声明式的、类型化的、可测试的,而不是隐式的。 ### 什么应该属于契约 @@ -338,145 +336,141 @@ OpenClaw 已经将图像 / 音频 / 视频理解视为一个共享能力。相 - 类型化的 - 小而精的 -- 能力特定的 -- 由核心拥有的 -- 可被多个插件复用的 -- 可被渠道 / 功能消费而无需了解厂商细节 +- 能力专用的 +- 由核心拥有 +- 可被多个插件复用 +- 可被渠道 / 功能消费,而无需了解供应商细节 不好的插件契约则是: -- 隐藏在核心中的厂商特定策略 +- 隐藏在核心中的供应商专用策略 - 绕过注册表的一次性插件逃生口 -- 直接深入某个厂商实现的渠道代码 +- 直接深入供应商实现的渠道代码 - 不属于 `OpenClawPluginApi` 或 `api.runtime` 的临时运行时对象 如果拿不准,请提升抽象层级:先定义能力,再让插件接入它。 ## 执行模型 -原生 OpenClaw 插件会与 Gateway 网关**在同一进程内**运行。它们不是沙箱隔离的。已加载的原生插件与核心代码具有相同的进程级信任边界。 +原生 OpenClaw 插件与 Gateway 网关 **在同一进程中** 运行。它们不是沙箱隔离的。一个已加载的原生插件与核心代码具有相同的进程级信任边界。 -影响: +这意味着: -- 原生插件可以注册工具、网络处理器、钩子和服务 -- 原生插件中的 bug 可能会使 gateway 崩溃或变得不稳定 -- 恶意原生插件等同于在 OpenClaw 进程内执行任意代码 +- 原生插件可以注册工具、网络处理器、hooks 和服务 +- 原生插件中的 bug 可能导致 gateway 崩溃或变得不稳定 +- 恶意原生插件等同于在 OpenClaw 进程内部执行任意代码 -兼容 bundle 默认更安全,因为 OpenClaw 当前将其视为元数据 / 内容包。在当前版本中,这主要意味着内置 Skills。 +兼容 bundle 默认更安全,因为 OpenClaw 当前将它们视为元数据 / 内容包。在当前版本中,这主要意味着内置 skills。 -对于非内置插件,请使用 allowlist 和显式安装 / 加载路径。应将工作区插件视为开发期代码,而不是生产默认值。 +对于非内置插件,请使用 allowlist 和显式的安装 / 加载路径。应将 workspace 插件视为开发时代码,而不是生产默认项。 -对于内置工作区包名,保持插件 id 锚定在 npm 名称中:默认使用 `@openclaw/`,或者在包刻意公开较窄插件角色时,使用经批准的类型化后缀,例如 `-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`。 +对于内置 workspace 包名,请让插件 id 锚定在 npm 名称中:默认使用 `@openclaw/`,或者使用批准的类型化后缀,例如 `-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`,前提是该包有意暴露更狭义的插件角色。 -重要信任说明: +重要的信任说明: - `plugins.allow` 信任的是**插件 id**,而不是来源出处。 -- 如果启用了 / 加入 allowlist 的工作区插件与某个内置插件具有相同 id,它会有意覆盖内置副本。 +- 当同 id 的 workspace 插件被启用 / 加入 allowlist 时,它会有意遮蔽内置插件副本。 - 这属于正常且有用的行为,适用于本地开发、补丁测试和热修复。 -- 内置插件信任是根据加载时的源码快照解析的 —— 即磁盘上的清单和代码 —— 而不是根据安装元数据解析。损坏或被替换的安装记录无法在实际源码声明之外,悄悄扩大内置插件的信任表面。 +- 内置插件信任是根据源码快照来解析的——即加载时磁盘上的 manifest 和代码——而不是根据安装元数据。损坏或被替换的安装记录,无法在实际源码声称之外悄悄扩大内置插件的信任表面。 ## 导出边界 -OpenClaw 导出的是能力,而不是实现便利层。 +OpenClaw 导出的是能力,而不是实现便利接口。 -保持能力注册为公开接口。收紧非契约辅助导出: +保持能力注册对外公开。裁剪非契约辅助导出: -- 内置插件特定的辅助子路径 -- 不打算作为公开 API 的运行时管线子路径 -- 厂商特定的便捷辅助工具 -- 属于实现细节的设置 / 新手引导辅助工具 +- 内置插件专用辅助子路径 +- 不打算作为公共 API 的运行时管线子路径 +- 供应商专用的便捷辅助工具 +- 属于实现细节的 setup / onboarding 辅助工具 -出于兼容性和内置插件维护需要,某些内置插件辅助子路径仍保留在生成的 SDK 导出映射中。当前示例包括 -`plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、 -`plugin-sdk/zalo-setup`,以及若干 `plugin-sdk/matrix*` 接缝。应将这些视为保留的实现细节导出,而不是新第三方插件推荐采用的 SDK 模式。 +出于兼容性和内置插件维护目的,某些内置插件辅助子路径仍然保留在生成的 SDK 导出映射中。当前示例包括 `plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、`plugin-sdk/zalo-setup` 以及若干 `plugin-sdk/matrix*` 接缝。应将这些视为保留的实现细节导出,而不是新第三方插件推荐采用的 SDK 模式。 ## 加载流水线 -在启动时,OpenClaw 大致会执行以下步骤: +在启动时,OpenClaw 大致会执行以下流程: 1. 发现候选插件根目录 -2. 读取原生或兼容 bundle 清单及包元数据 +2. 读取原生或兼容 bundle 的 manifest 和包元数据 3. 拒绝不安全的候选项 4. 规范化插件配置(`plugins.enabled`、`allow`、`deny`、`entries`、`slots`、`load.paths`) -5. 为每个候选项决定启用状态 +5. 决定每个候选项是否启用 6. 加载已启用的原生模块:已构建的内置模块使用原生加载器;未构建的原生插件使用 jiti -7. 调用原生 `register(api)` 钩子,并将注册结果收集到插件注册表中 +7. 调用原生 `register(api)` hooks,并将注册内容收集到插件注册表中 8. 将注册表暴露给命令 / 运行时表面 -`activate` 是 `register` 的旧别名 —— 加载器会解析两者中存在的那个(`def.register ?? def.activate`),并在同一时机调用。所有内置插件都使用 `register`;新插件请优先使用 `register`。 +`activate` 是 `register` 的 legacy 别名——加载器会解析两者中存在的那个(`def.register ?? def.activate`),并在同一时机调用。所有内置插件都使用 `register`;新插件请优先使用 `register`。 -安全闸门发生在**运行时代码执行之前**。当入口逃逸出插件根目录、路径对所有用户可写,或者对于非内置插件而言路径归属看起来可疑时,候选项会被阻止。 +安全门会发生在运行时代码执行**之前**。如果候选项的入口逃逸出插件根目录、路径对所有人可写,或者对于非内置插件来说路径归属看起来可疑,那么该候选项会被阻止。 -### Manifest-first 行为 +### Manifest 优先行为 -清单是控制平面的事实来源。OpenClaw 使用它来: +manifest 是控制平面的事实来源。OpenClaw 使用它来: - 标识插件 -- 发现已声明的渠道 / Skills / 配置 schema 或 bundle 能力 +- 发现声明的渠道 / skills / 配置 schema 或 bundle 能力 - 验证 `plugins.entries..config` - 增强 Control UI 标签 / 占位符 - 显示安装 / 目录元数据 -- 在不加载插件运行时的前提下保留轻量激活和设置描述符 +- 在不加载插件运行时的情况下保留轻量激活和设置描述符 -对于原生插件,运行时模块是数据平面部分。它会注册真实行为,例如钩子、工具、命令或 provider 流程。 +对于原生插件,运行时模块是数据平面部分。它会注册实际行为,例如 hooks、工具、命令或提供商流程。 -可选的清单 `activation` 和 `setup` 块仍然属于控制平面。它们只是用于激活规划和设置发现的纯元数据描述符;并不会替代运行时注册、`register(...)` 或 `setupEntry`。 -首批实时激活使用方现在会利用清单中的命令、渠道和 provider 提示,在更广泛的注册表实体化之前收窄插件加载范围: +可选的 manifest `activation` 和 `setup` 块仍然留在控制平面。它们是用于激活规划和设置发现的纯元数据描述符;它们不会替代运行时注册、`register(...)` 或 `setupEntry`。 +首批实时激活消费者现在会使用 manifest 中的命令、渠道和提供商提示,在更广泛的注册表实体化之前缩小插件加载范围: - CLI 加载会收窄到拥有所请求主命令的插件 - 渠道设置 / 插件解析会收窄到拥有所请求渠道 id 的插件 -- 显式 provider 设置 / 运行时解析会收窄到拥有所请求 provider id 的插件 +- 显式提供商设置 / 运行时解析会收窄到拥有所请求 provider id 的插件 -设置发现现在会优先使用由描述符拥有的 id,例如 `setup.providers` 和 `setup.cliBackends`,以在回退到 `setup-api` 之前先收窄候选插件;`setup-api` 仅用于那些在设置阶段仍需要运行时钩子的插件。如果多个已发现插件声明了相同的规范化设置 provider 或 CLI 后端 id,则设置查找会拒绝这个有歧义的归属,而不是依赖发现顺序。 +设置发现现在会优先使用由描述符拥有的 id,例如 `setup.providers` 和 `setup.cliBackends`,以便在回退到 `setup-api` 之前先收窄候选插件范围;`setup-api` 仅用于那些仍需要设置时运行时 hooks 的插件。如果多个已发现插件声称拥有相同的规范化 setup provider 或 CLI backend id,则设置查找会拒绝这个有歧义的归属,而不是依赖发现顺序。 -### 加载器会缓存什么 +### 加载器缓存的内容 -OpenClaw 会为以下内容保留短期的进程内缓存: +OpenClaw 会保留以下短期进程内缓存: - 发现结果 -- 清单注册表数据 +- manifest 注册表数据 - 已加载的插件注册表 -这些缓存可以减少突发式启动开销和重复命令开销。可以放心将它们视为短生命周期的性能缓存,而不是持久化机制。 +这些缓存可减少突发启动和重复命令的开销。可以将它们安全地视为短生命周期的性能缓存,而不是持久化机制。 性能说明: -- 设置 `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` 或 - `OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1` 可禁用这些缓存。 -- 可使用 `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS` 和 - `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS` 调整缓存时间窗口。 +- 设置 `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` 或 `OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1` 可禁用这些缓存。 +- 使用 `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS` 和 `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS` 调整缓存窗口。 ## 注册表模型 -已加载的插件不会直接修改核心中的任意全局状态。它们会注册到一个中央插件注册表中。 +已加载插件不会直接修改任意核心全局状态。它们会注册到一个中央插件注册表中。 -注册表会跟踪: +该注册表会跟踪: -- 插件记录(身份、来源、出处、状态、诊断) +- 插件记录(身份、来源、源头、状态、诊断) - 工具 -- 旧式钩子和类型化钩子 +- legacy hooks 和类型化 hooks - 渠道 -- providers +- 提供商 - Gateway 网关 RPC 处理器 - HTTP 路由 - CLI 注册器 - 后台服务 -- 插件自有命令 +- 插件拥有的命令 -随后,核心功能会从该注册表读取信息,而不是直接与插件模块交互。这使得加载保持单向: +然后核心功能从该注册表读取,而不是直接与插件模块通信。这使加载保持单向: -- 插件模块 -> 注册到注册表 -- 核心运行时 -> 消费注册表 +- 插件模块 -> 注册表注册 +- 核心运行时 -> 注册表消费 -这种分离对可维护性非常重要。这意味着大多数核心表面只需要一个集成点:“读取注册表”,而不是“对每个插件模块做特殊分支处理”。 +这种分离对可维护性很重要。它意味着大多数核心表面只需要一个集成点:“读取注册表”,而不是“为每个插件模块做特殊处理”。 -## 对话绑定回调 +## 会话绑定回调 -绑定对话的插件可以在审批结果解析后作出响应。 +绑定会话的插件可以在批准结果确定时作出响应。 -使用 `api.onConversationBindingResolved(...)` 可以在绑定请求被批准或拒绝后接收回调: +使用 `api.onConversationBindingResolved(...)` 可在绑定请求被批准或拒绝后收到回调: ```ts export default { @@ -500,102 +494,84 @@ export default { - `status`:`"approved"` 或 `"denied"` - `decision`:`"allow-once"`、`"allow-always"` 或 `"deny"` -- `binding`:针对已批准请求解析出的绑定 -- `request`:原始请求摘要、detach 提示、发送者 id 和对话元数据 +- `binding`:已获批准请求的已解析绑定 +- `request`:原始请求摘要、分离提示、发送者 id 和会话元数据 -这个回调仅用于通知。它不会改变谁有权绑定对话,并且它会在核心审批处理完成之后运行。 +此回调仅用于通知。它不会改变谁被允许绑定某个会话,并且会在核心批准处理完成后运行。 -## provider 运行时钩子 +## 提供商运行时 hooks -provider 插件现在有两层: +提供商插件现在有两层: -- 清单元数据:`providerAuthEnvVars` 用于在运行时加载前低成本查找 provider 的环境变量认证,`providerAuthAliases` 用于共享认证的 provider 变体,`channelEnvVars` 用于在运行时加载前低成本查找渠道环境变量 / 设置,此外还有 `providerAuthChoices`,用于在运行时加载前提供低成本的新手引导 / 认证选择标签和 CLI 标志元数据 -- 配置时钩子:`catalog` / 旧式 `discovery`,以及 `applyConfigDefaults` -- 运行时钩子:`normalizeModelId`、`normalizeTransport`、 - `normalizeConfig`、 - `applyNativeStreamingUsageCompat`、`resolveConfigApiKey`、 - `resolveSyntheticAuth`、`resolveExternalAuthProfiles`、 - `shouldDeferSyntheticProfileAuth`、 - `resolveDynamicModel`、`prepareDynamicModel`、`normalizeResolvedModel`、 - `contributeResolvedModelCompat`、`capabilities`、 - `normalizeToolSchemas`、`inspectToolSchemas`、 - `resolveReasoningOutputMode`、`prepareExtraParams`、`createStreamFn`、 - `wrapStreamFn`、`resolveTransportTurnState`、 - `resolveWebSocketSessionPolicy`、`formatApiKey`、`refreshOAuth`、 - `buildAuthDoctorHint`、`matchesContextOverflowError`、 - `classifyFailoverReason`、`isCacheTtlEligible`、 - `buildMissingAuthMessage`、`suppressBuiltInModel`、`augmentModelCatalog`、 - `resolveThinkingProfile`、`isBinaryThinking`、`supportsXHighThinking`、 - `resolveDefaultThinkingLevel`、`isModernModelRef`、`prepareRuntimeAuth`、 - `resolveUsageAuth`、`fetchUsageSnapshot`、`createEmbeddingProvider`、 - `buildReplayPolicy`、 - `sanitizeReplayHistory`、`validateReplayTurns`、`onModelSelected` +- manifest 元数据:`providerAuthEnvVars` 用于在运行时加载前以低成本查找基于环境变量的提供商认证,`providerAuthAliases` 用于共享认证的提供商变体,`channelEnvVars` 用于在运行时加载前以低成本查找基于环境变量的渠道配置 / 设置,此外还有 `providerAuthChoices`,用于在运行时加载前以低成本提供 onboarding / 认证选择标签和 CLI flag 元数据 +- 配置时 hooks:`catalog` / legacy `discovery`,以及 `applyConfigDefaults` +- 运行时 hooks:`normalizeModelId`、`normalizeTransport`、`normalizeConfig`、`applyNativeStreamingUsageCompat`、`resolveConfigApiKey`、`resolveSyntheticAuth`、`resolveExternalAuthProfiles`、`shouldDeferSyntheticProfileAuth`、`resolveDynamicModel`、`prepareDynamicModel`、`normalizeResolvedModel`、`contributeResolvedModelCompat`、`capabilities`、`normalizeToolSchemas`、`inspectToolSchemas`、`resolveReasoningOutputMode`、`prepareExtraParams`、`createStreamFn`、`wrapStreamFn`、`resolveTransportTurnState`、`resolveWebSocketSessionPolicy`、`formatApiKey`、`refreshOAuth`、`buildAuthDoctorHint`、`matchesContextOverflowError`、`classifyFailoverReason`、`isCacheTtlEligible`、`buildMissingAuthMessage`、`suppressBuiltInModel`、`augmentModelCatalog`、`resolveThinkingProfile`、`isBinaryThinking`、`supportsXHighThinking`、`resolveDefaultThinkingLevel`、`isModernModelRef`、`prepareRuntimeAuth`、`resolveUsageAuth`、`fetchUsageSnapshot`、`createEmbeddingProvider`、`buildReplayPolicy`、`sanitizeReplayHistory`、`validateReplayTurns`、`onModelSelected` -OpenClaw 仍然拥有通用智能体循环、故障切换、转录处理和工具策略。这些钩子是在无需整套自定义推理传输的情况下,用于扩展 provider 特定行为的表面。 +OpenClaw 仍然拥有通用智能体循环、故障切换、转录处理和工具策略。这些 hooks 是提供商专用行为的扩展表面,而无需引入一整套自定义推理传输。 -当 provider 具有基于环境变量的凭证,并且通用认证 / 状态 / 模型选择器路径需要在不加载插件运行时的情况下感知这些凭证时,请使用清单中的 `providerAuthEnvVars`。当某个 provider id 应复用另一个 provider id 的环境变量、认证配置文件、基于配置的认证以及 API key 新手引导选项时,请使用清单中的 `providerAuthAliases`。当新手引导 / 认证选择 CLI 表面需要在不加载 provider 运行时的情况下,知道该 provider 的 choice id、分组标签和简单的单标志认证接线时,请使用清单中的 `providerAuthChoices`。保留 provider 运行时 `envVars` 用于面向操作员的提示,例如新手引导标签或 OAuth client-id / client-secret 设置变量。 +当提供商具有基于环境变量的凭证,并且通用认证 / 状态 / 模型选择器路径需要在不加载插件运行时的情况下感知它们时,请使用 manifest `providerAuthEnvVars`。当某个 provider id 应复用另一个 provider id 的环境变量、认证配置文件、基于配置的认证以及 API 密钥 onboarding 选项时,请使用 manifest `providerAuthAliases`。当 onboarding / 认证选择 CLI 表面需要在不加载提供商运行时的情况下了解该提供商的 choice id、分组标签和简单的单 flag 认证接线时,请使用 manifest `providerAuthChoices`。将提供商运行时 `envVars` 保留给面向操作员的提示,例如 onboarding 标签或 OAuth client-id / client-secret 设置变量。 -当某个渠道具有由环境变量驱动的认证或设置,并且通用 shell 环境变量回退、配置 / 状态检查或设置提示需要在不加载渠道运行时的情况下感知它时,请使用清单中的 `channelEnvVars`。 +当某个渠道具有基于环境变量的认证或设置,并且通用 shell 环境变量回退、配置 / 状态检查或设置提示需要在不加载渠道运行时的情况下感知它时,请使用 manifest `channelEnvVars`。 -### 钩子顺序和用法 +### Hook 顺序和用法 -对于模型 / provider 插件,OpenClaw 大致按以下顺序调用这些钩子。 -“何时使用”这一列是快速决策指南。 +对于模型 / 提供商插件,OpenClaw 大致会按以下顺序调用 hooks。 +“何时使用”一列是快速决策指南。 -| # | 钩子 | 作用 | 何时使用 | +| # | Hook | 作用 | 何时使用 | | --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `catalog` | 在生成 `models.json` 期间,将 provider 配置发布到 `models.providers` 中 | provider 拥有目录或 base URL 默认值 | -| 2 | `applyConfigDefaults` | 在配置实体化期间,应用 provider 自有的全局配置默认值 | 默认值依赖于认证模式、环境变量或 provider 模型族语义 | -| -- | _(内置模型查找)_ | OpenClaw 会先尝试常规注册表 / 目录路径 | _(不是插件钩子)_ | -| 3 | `normalizeModelId` | 在查找前规范化旧式或预览版 model-id 别名 | provider 拥有在规范模型解析之前进行别名清理的逻辑 | -| 4 | `normalizeTransport` | 在通用模型组装之前,规范化 provider 族的 `api` / `baseUrl` | provider 拥有同一传输族中自定义 provider id 的传输清理逻辑 | -| 5 | `normalizeConfig` | 在运行时 / provider 解析之前,规范化 `models.providers.` | provider 需要将配置清理逻辑放在插件中;内置 Google 族辅助工具也会为受支持的 Google 配置项提供兜底 | -| 6 | `applyNativeStreamingUsageCompat` | 对配置 providers 应用原生流式用量兼容性改写 | provider 需要基于端点驱动的原生流式用量元数据修复 | -| 7 | `resolveConfigApiKey` | 在加载运行时认证之前,为配置 provider 解析 env-marker 认证 | provider 拥有自己的 env-marker API key 解析逻辑;`amazon-bedrock` 在这里也有一个内置 AWS env-marker 解析器 | -| 8 | `resolveSyntheticAuth` | 在不持久化明文的情况下公开本地 / 自托管或基于配置的认证 | provider 可以通过合成 / 本地凭证标记运行 | -| 9 | `resolveExternalAuthProfiles` | 叠加 provider 自有的外部认证配置文件;对 CLI / 应用自有凭证,默认 `persistence` 为 `runtime-only` | provider 会复用外部认证凭证,而不持久化复制的刷新令牌;需在清单中声明 `contracts.externalAuthProviders` | -| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的合成配置文件占位符优先级降到环境变量 / 基于配置的认证之后 | provider 会存储合成占位配置文件,而这些占位项不应获得更高优先级 | -| 11 | `resolveDynamicModel` | 对本地注册表中尚不存在的 provider 自有 model id 执行同步回退解析 | provider 接受任意上游 model id | -| 12 | `prepareDynamicModel` | 异步预热,然后再次运行 `resolveDynamicModel` | provider 在解析未知 id 之前需要网络元数据 | -| 13 | `normalizeResolvedModel` | 在嵌入式 runner 使用已解析模型之前执行最终改写 | provider 需要进行传输改写,但仍然使用核心传输 | -| 14 | `contributeResolvedModelCompat` | 为另一种兼容传输背后的厂商模型提供兼容性标志 | provider 能在不接管该 provider 的情况下,在代理传输上识别自己的模型 | -| 15 | `capabilities` | 由共享核心逻辑使用的 provider 自有转录 / 工具元数据 | provider 需要处理转录 / provider 族特有差异 | -| 16 | `normalizeToolSchemas` | 在嵌入式 runner 看到工具 schema 之前对其进行规范化 | provider 需要进行传输族 schema 清理 | -| 17 | `inspectToolSchemas` | 在规范化之后公开 provider 自有的 schema 诊断 | provider 希望提供关键字警告,而不必让核心了解 provider 特定规则 | -| 18 | `resolveReasoningOutputMode` | 选择原生推理输出契约还是带标签的推理输出契约 | provider 需要使用带标签的推理 / 最终输出,而不是原生字段 | -| 19 | `prepareExtraParams` | 在通用流式选项包装器之前进行请求参数规范化 | provider 需要默认请求参数或按 provider 清理参数 | -| 20 | `createStreamFn` | 使用自定义传输完全替换常规流路径 | provider 需要自定义线路协议,而不只是一个包装器 | -| 21 | `wrapStreamFn` | 在应用通用包装器之后再包装流函数 | provider 需要请求头 / 请求体 / 模型兼容性包装器,而不是自定义传输 | -| 22 | `resolveTransportTurnState` | 附加原生的按轮次传输请求头或元数据 | provider 希望通用传输发送 provider 原生轮次身份 | -| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 请求头或会话冷却策略 | provider 希望通用 WS 传输调优会话请求头或回退策略 | -| 24 | `formatApiKey` | 认证配置文件格式化器:已存储配置文件会变成运行时 `apiKey` 字符串 | provider 会存储额外认证元数据,并需要自定义运行时令牌形态 | -| 25 | `refreshOAuth` | 为自定义刷新端点或刷新失败策略覆盖 OAuth 刷新逻辑 | provider 不适配共享的 `pi-ai` 刷新器 | -| 26 | `buildAuthDoctorHint` | 当 OAuth 刷新失败时附加修复提示 | provider 在刷新失败后需要 provider 自有的认证修复指引 | -| 27 | `matchesContextOverflowError` | provider 自有的上下文窗口溢出匹配器 | provider 存在通用启发式无法识别的原始溢出错误 | -| 28 | `classifyFailoverReason` | provider 自有的故障切换原因分类 | provider 可以将原始 API / 传输错误映射为速率限制 / 过载 / 等 | -| 29 | `isCacheTtlEligible` | 面向代理 / 回传 provider 的提示词缓存策略 | provider 需要代理特定的缓存 TTL 门控 | -| 30 | `buildMissingAuthMessage` | 替代通用缺失认证恢复消息 | provider 需要 provider 特定的缺失认证恢复提示 | -| 31 | `suppressBuiltInModel` | 过时上游模型抑制,并可附带面向用户的错误提示 | provider 需要隐藏过时的上游条目,或用厂商提示替换它们 | -| 32 | `augmentModelCatalog` | 在发现后附加合成 / 最终目录条目 | provider 需要在 `models list` 和选择器中补充合成的前向兼容条目 | -| 33 | `resolveThinkingProfile` | 针对特定模型设置 `/think` 级别、显示标签和默认值 | provider 为选定模型公开自定义 thinking 阶梯或二元标签 | -| 34 | `isBinaryThinking` | 开 / 关推理切换兼容性钩子 | provider 仅公开二元的 thinking 开 / 关 | -| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容性钩子 | provider 只希望在部分模型上支持 `xhigh` | -| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 级别兼容性钩子 | provider 拥有某个模型族的默认 `/think` 策略 | -| 37 | `isModernModelRef` | 用于实时配置文件过滤和 smoke 选择的现代模型匹配器 | provider 拥有实时 / smoke 首选模型匹配逻辑 | -| 38 | `prepareRuntimeAuth` | 在推理前,将已配置凭证交换为实际运行时令牌 / key | provider 需要令牌交换或短时效请求凭证 | -| 39 | `resolveUsageAuth` | 为 `/usage` 及相关状态表面解析用量 / 计费凭证 | provider 需要自定义用量 / 配额令牌解析,或使用不同的用量凭证 | -| 40 | `fetchUsageSnapshot` | 在认证解析后获取并规范化 provider 特定的用量 / 配额快照 | provider 需要 provider 特定的用量端点或负载解析器 | -| 41 | `createEmbeddingProvider` | 为 memory / 搜索构建 provider 自有的 embedding 适配器 | Memory embedding 行为应归属于 provider 插件 | -| 42 | `buildReplayPolicy` | 返回一个控制该 provider 转录处理方式的回放策略 | provider 需要自定义转录策略(例如剥离 thinking 块) | -| 43 | `sanitizeReplayHistory` | 在通用转录清理之后改写回放历史 | provider 需要在共享压缩辅助工具之外,进一步执行 provider 特定的回放改写 | -| 44 | `validateReplayTurns` | 在嵌入式 runner 之前,对回放轮次进行最终校验或重塑 | provider 传输在通用净化之后需要更严格的轮次校验 | -| 45 | `onModelSelected` | 在模型变为活动状态时运行 provider 自有的后续副作用 | provider 在模型激活时需要遥测或 provider 自有状态 | +| 1 | `catalog` | 在生成 `models.json` 期间将提供商配置发布到 `models.providers` 中 | 提供商拥有目录,或拥有 base URL 默认值 | +| 2 | `applyConfigDefaults` | 在配置实体化期间应用由提供商拥有的全局配置默认值 | 默认值依赖于认证模式、环境或提供商模型家族语义 | +| -- | _(内置模型查找)_ | OpenClaw 会先尝试常规注册表 / 目录路径 | _(不是插件 hook)_ | +| 3 | `normalizeModelId` | 在查找前规范化 legacy 或预览版 model-id 别名 | 提供商拥有在规范模型解析前进行别名清理的逻辑 | +| 4 | `normalizeTransport` | 在通用模型组装前规范化提供商家族的 `api` / `baseUrl` | 提供商拥有同一传输家族中自定义 provider id 的传输清理逻辑 | +| 5 | `normalizeConfig` | 在运行时 / 提供商解析前规范化 `models.providers.` | 提供商需要与插件放在一起的配置清理逻辑;内置的 Google 家族辅助工具也会为受支持的 Google 配置项提供兜底 | +| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式用量兼容性重写 | 提供商需要基于端点的原生流式用量元数据修复 | +| 7 | `resolveConfigApiKey` | 在加载运行时认证前,为配置提供商解析环境变量标记认证 | 提供商具有由其拥有的环境变量标记 API 密钥解析逻辑;`amazon-bedrock` 在这里也有内置的 AWS 环境变量标记解析器 | +| 8 | `resolveSyntheticAuth` | 在不持久化明文的情况下暴露本地 / 自托管或基于配置的认证 | 提供商可使用合成 / 本地凭证标记运行 | +| 9 | `resolveExternalAuthProfiles` | 叠加由提供商拥有的外部认证配置文件;CLI / 应用拥有的凭证默认 `persistence` 为 `runtime-only` | 提供商会复用外部认证凭证,而不持久化复制的刷新令牌;请在 manifest 中声明 `contracts.externalAuthProviders` | +| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的合成配置文件占位符优先级降到基于环境变量 / 配置的认证之后 | 提供商会存储合成占位配置文件,而这些占位符不应获得更高优先级 | +| 11 | `resolveDynamicModel` | 为本地注册表中尚不存在的、由提供商拥有的 model id 执行同步回退解析 | 提供商接受任意上游 model id | +| 12 | `prepareDynamicModel` | 执行异步预热,然后再次运行 `resolveDynamicModel` | 提供商在解析未知 id 前需要网络元数据 | +| 13 | `normalizeResolvedModel` | 在嵌入式 runner 使用已解析模型前执行最终重写 | 提供商需要传输重写,但仍使用核心传输 | +| 14 | `contributeResolvedModelCompat` | 为另一种兼容传输后面的供应商模型提供兼容性标志 | 提供商能在代理传输上识别自己的模型,而无需接管该提供商 | +| 15 | `capabilities` | 由提供商拥有、供共享核心逻辑使用的转录 / 工具元数据 | 提供商需要转录 / 提供商家族特定差异处理 | +| 16 | `normalizeToolSchemas` | 在嵌入式 runner 看见工具 schema 之前对其进行规范化 | 提供商需要传输家族级别的 schema 清理 | +| 17 | `inspectToolSchemas` | 在规范化后暴露由提供商拥有的 schema 诊断信息 | 提供商希望给出关键字警告,而无需让核心理解提供商专用规则 | +| 18 | `resolveReasoningOutputMode` | 选择原生或带标记的推理输出契约 | 提供商需要带标记的推理 / 最终输出,而不是原生字段 | +| 19 | `prepareExtraParams` | 在通用流选项包装器之前进行请求参数规范化 | 提供商需要默认请求参数或按提供商清理参数 | +| 20 | `createStreamFn` | 用自定义传输完全替换正常流路径 | 提供商需要自定义线协议,而不仅仅是包装器 | +| 21 | `wrapStreamFn` | 在应用通用包装器后对流进行包装 | 提供商需要请求头 / 请求体 / 模型兼容性包装器,而不是自定义传输 | +| 22 | `resolveTransportTurnState` | 附加原生的逐轮传输头或元数据 | 提供商希望通用传输发送提供商原生的轮次身份信息 | +| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 头或会话冷却策略 | 提供商希望通用 WS 传输调整会话头或回退策略 | +| 24 | `formatApiKey` | 认证配置文件格式化器:已存储配置文件会变成运行时 `apiKey` 字符串 | 提供商会存储额外认证元数据,并需要自定义运行时令牌形态 | +| 25 | `refreshOAuth` | 为自定义刷新端点或刷新失败策略覆盖 OAuth 刷新逻辑 | 提供商不适配共享的 `pi-ai` 刷新器 | +| 26 | `buildAuthDoctorHint` | 当 OAuth 刷新失败时附加修复提示 | 提供商需要在刷新失败后提供其自有的认证修复指导 | +| 27 | `matchesContextOverflowError` | 由提供商拥有的上下文窗口溢出匹配器 | 提供商存在通用启发式无法识别的原始溢出错误 | +| 28 | `classifyFailoverReason` | 由提供商拥有的故障切换原因分类 | 提供商可以将原始 API / 传输错误映射为速率限制 / 过载等原因 | +| 29 | `isCacheTtlEligible` | 面向代理 / 回程提供商的提示词缓存策略 | 提供商需要代理专用的缓存 TTL 门控 | +| 30 | `buildMissingAuthMessage` | 替换通用的缺失认证恢复消息 | 提供商需要提供商专用的缺失认证恢复提示 | +| 31 | `suppressBuiltInModel` | 过时上游模型抑制,以及可选的面向用户错误提示 | 提供商需要隐藏过时的上游条目,或用供应商提示替换它们 | +| 32 | `augmentModelCatalog` | 在发现后附加合成 / 最终目录条目 | 提供商需要在 `models list` 和选择器中添加合成的前向兼容条目 | +| 33 | `resolveThinkingProfile` | 特定模型的 `/think` 级别集、显示标签和默认值 | 提供商为选定模型暴露自定义思考层级或二元标签 | +| 34 | `isBinaryThinking` | 开 / 关推理切换兼容性 hook | 提供商只暴露二元思考开 / 关 | +| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容性 hook | 提供商希望仅在部分模型上启用 `xhigh` | +| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 级别兼容性 hook | 提供商拥有某个模型家族的默认 `/think` 策略 | +| 37 | `isModernModelRef` | 用于实时配置文件过滤和 smoke 选择的现代模型匹配器 | 提供商拥有实时 / smoke 首选模型匹配逻辑 | +| 38 | `prepareRuntimeAuth` | 在推理前最后一刻,将已配置凭证交换为实际运行时令牌 / 密钥 | 提供商需要令牌交换或短期请求凭证 | +| 39 | `resolveUsageAuth` | 为 `/usage` 及相关状态表面解析用量 / 计费凭证 | 提供商需要自定义用量 / 配额令牌解析,或需要不同的用量凭证 | +| 40 | `fetchUsageSnapshot` | 在认证解析完成后获取并规范化提供商专用的用量 / 配额快照 | 提供商需要提供商专用的用量端点或负载解析器 | +| 41 | `createEmbeddingProvider` | 为 memory / 搜索构建由提供商拥有的 embedding 适配器 | Memory embedding 行为应属于提供商插件 | +| 42 | `buildReplayPolicy` | 返回一个控制该提供商转录处理方式的重放策略 | 提供商需要自定义转录策略(例如去除 thinking 块) | +| 43 | `sanitizeReplayHistory` | 在通用转录清理后重写重放历史 | 提供商需要超出共享压缩辅助工具之外的提供商专用重放重写 | +| 44 | `validateReplayTurns` | 在嵌入式 runner 之前对重放轮次进行最终验证或重塑 | 提供商传输在通用净化后需要更严格的轮次验证 | +| 45 | `onModelSelected` | 在模型被选中后运行由提供商拥有的副作用 | 当模型变为激活状态时,提供商需要遥测或提供商自有状态 | -`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配到的 provider 插件,然后再依次回退到其他具备钩子能力的 provider 插件,直到有某个插件真正改写 model id 或 transport / config。这样可以让别名 / 兼容 provider 垫片继续工作,而不要求调用方知道是哪个内置插件拥有该改写逻辑。如果没有任何 provider 钩子去改写受支持的 Google 族配置项,内置 Google 配置规范化器仍会执行该兼容性清理。 +`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配到的提供商插件,然后继续回退到其他具备对应 hook 能力的提供商插件,直到某个插件实际修改了 model id 或 transport / config。这样可以让别名 / 兼容性提供商 shim 继续工作,而无需调用方知道哪个内置插件拥有该重写逻辑。如果没有任何提供商 hook 重写受支持的 Google 家族配置项,那么内置的 Google 配置规范化器仍会应用该兼容性清理。 -如果 provider 需要完全自定义的线路协议或自定义请求执行器,那属于另一类扩展。这些钩子适用于仍运行在 OpenClaw 常规推理循环上的 provider 行为。 +如果提供商需要完全自定义的线协议或自定义请求执行器,那就是另一类扩展方式了。这里的这些 hooks 适用于仍运行在 OpenClaw 常规推理循环上的提供商行为。 -### provider 示例 +### 提供商示例 ```ts api.registerProvider({ @@ -651,64 +627,19 @@ api.registerProvider({ ### 内置示例 -- Anthropic 使用 `resolveDynamicModel`、`capabilities`、`buildAuthDoctorHint`、 - `resolveUsageAuth`、`fetchUsageSnapshot`、`isCacheTtlEligible`、 - `resolveThinkingProfile`、`applyConfigDefaults`、`isModernModelRef` - 和 `wrapStreamFn`,因为它拥有 Claude 4.6 前向兼容、provider 族提示、认证修复指引、用量端点集成、提示词缓存资格、具备认证感知的配置默认值、Claude 默认 / 自适应 thinking 策略,以及面向 beta 请求头、`/fast` / `serviceTier` 和 `context1m` 的 Anthropic 特定流整形。 -- Anthropic 的 Claude 特定流辅助工具目前保留在内置插件自己的公开 `api.ts` / `contract-api.ts` 接缝中。该包表面导出 `wrapAnthropicProviderStream`、`resolveAnthropicBetas`、 - `resolveAnthropicFastMode`、`resolveAnthropicServiceTier` 以及更底层的 Anthropic 包装器构建工具,而不是为了某个 provider 的 beta 请求头规则去扩大通用 SDK。 -- OpenAI 使用 `resolveDynamicModel`、`normalizeResolvedModel` 和 - `capabilities`,再加上 `buildMissingAuthMessage`、`suppressBuiltInModel`、 - `augmentModelCatalog`、`resolveThinkingProfile` 和 `isModernModelRef`, - 因为它拥有 GPT-5.4 前向兼容、直接 OpenAI - `openai-completions` -> `openai-responses` 规范化、具备 Codex 感知的认证提示、Spark 抑制、合成 OpenAI 列表行,以及 GPT-5 thinking / 实时模型策略;`openai-responses-defaults` 流族则拥有共享的原生 OpenAI Responses 包装器,用于处理 attribution 请求头、`/fast` / `serviceTier`、文本详细度、原生 Codex Web 搜索、推理兼容负载整形以及 Responses 上下文管理。 -- OpenRouter 使用 `catalog`,以及 `resolveDynamicModel` 和 - `prepareDynamicModel`,因为该 provider 是透传型的,可能会在 OpenClaw 静态目录更新之前公开新的 model id;它还使用 - `capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,以将 provider 特定请求头、路由元数据、推理补丁和提示词缓存策略保留在核心之外。它的回放策略来自 `passthrough-gemini` 族,而 `openrouter-thinking` 流族拥有代理推理注入以及对不受支持模型 / `auto` 的跳过逻辑。 -- GitHub Copilot 使用 `catalog`、`auth`、`resolveDynamicModel` 和 - `capabilities`,再加上 `prepareRuntimeAuth` 和 `fetchUsageSnapshot`, - 因为它需要 provider 自有的设备登录、模型回退行为、Claude 转录差异、GitHub token -> Copilot token 交换,以及 provider 自有的用量端点。 -- OpenAI Codex 使用 `catalog`、`resolveDynamicModel`、 - `normalizeResolvedModel`、`refreshOAuth` 和 `augmentModelCatalog`, - 再加上 `prepareExtraParams`、`resolveUsageAuth` 和 `fetchUsageSnapshot`, - 因为它仍运行在核心 OpenAI 传输之上,但拥有自己的传输 / base URL 规范化、OAuth 刷新回退策略、默认传输选择、合成 Codex 目录行,以及 ChatGPT 用量端点集成;它与直接 OpenAI 共享同一个 `openai-responses-defaults` 流族。 -- Google AI Studio 和 Gemini CLI OAuth 使用 `resolveDynamicModel`、 - `buildReplayPolicy`、`sanitizeReplayHistory`、 - `resolveReasoningOutputMode`、`wrapStreamFn` 和 `isModernModelRef`,因为 - `google-gemini` 回放族拥有 Gemini 3.1 前向兼容回退、原生 Gemini 回放校验、引导回放净化、带标签推理输出模式以及现代模型匹配,而 - `google-thinking` 流族拥有 Gemini thinking 负载规范化;Gemini CLI OAuth 还使用 `formatApiKey`、`resolveUsageAuth` 和 - `fetchUsageSnapshot` 来处理令牌格式化、令牌解析和配额端点接线。 -- Anthropic Vertex 通过 `anthropic-by-model` 回放族使用 `buildReplayPolicy`,这样 Claude 特定的回放清理就只会作用于 Claude id,而不是每个 `anthropic-messages` 传输。 -- Amazon Bedrock 使用 `buildReplayPolicy`、`matchesContextOverflowError`、 - `classifyFailoverReason` 和 `resolveThinkingProfile`,因为它拥有面向 Bedrock 上 Anthropic 流量的 Bedrock 特定限流 / 未就绪 / 上下文溢出错误分类;它的回放策略仍共享同一个仅限 Claude 的 `anthropic-by-model` 守卫。 -- OpenRouter、Kilocode、Opencode 和 Opencode Go 通过 - `passthrough-gemini` 回放族使用 `buildReplayPolicy`,因为它们通过 OpenAI 兼容传输代理 Gemini 模型,并需要 Gemini - thought-signature 净化,而不需要原生 Gemini 回放校验或引导改写。 -- MiniMax 通过 `hybrid-anthropic-openai` 回放族使用 `buildReplayPolicy`,因为同一个 provider 同时拥有 Anthropic-message 和 OpenAI 兼容语义;它会在 Anthropic 一侧保留仅针对 Claude 的 thinking 块丢弃逻辑,同时将推理输出模式覆盖回原生,而 `minimax-fast-mode` 流族则在共享流路径上拥有 fast-mode 模型改写。 -- Moonshot 使用 `catalog`、`resolveThinkingProfile` 和 `wrapStreamFn`,因为它仍使用共享 - OpenAI 传输,但需要 provider 自有的 thinking 负载规范化;`moonshot-thinking` 流族会将配置加 `/think` 状态映射到其原生的二元 thinking 负载。 -- Kilocode 使用 `catalog`、`capabilities`、`wrapStreamFn` 和 - `isCacheTtlEligible`,因为它需要 provider 自有请求头、推理负载规范化、Gemini 转录提示和 Anthropic - 缓存 TTL 门控;`kilocode-thinking` 流族会在共享代理流路径上保留 Kilo thinking 注入,同时跳过 `kilo/auto` 和其他不支持显式推理负载的代理 model id。 -- Z.AI 使用 `resolveDynamicModel`、`prepareExtraParams`、`wrapStreamFn`、 - `isCacheTtlEligible`、`resolveThinkingProfile`、`isModernModelRef`、 - `resolveUsageAuth` 和 `fetchUsageSnapshot`,因为它拥有 GLM-5 回退、 - `tool_stream` 默认值、二元 thinking UX、现代模型匹配,以及用量认证和配额抓取;`tool-stream-default-on` 流族会将默认开启的 `tool_stream` 包装器保留在逐 provider 手写胶水代码之外。 -- xAI 使用 `normalizeResolvedModel`、`normalizeTransport`、 - `contributeResolvedModelCompat`、`prepareExtraParams`、`wrapStreamFn`、 - `resolveSyntheticAuth`、`resolveDynamicModel` 和 `isModernModelRef`, - 因为它拥有原生 xAI Responses 传输规范化、Grok fast-mode 别名改写、默认 `tool_stream`、严格工具 / 推理负载清理、面向插件自有工具的回退认证复用、前向兼容 Grok 模型解析,以及 provider 自有兼容性补丁,例如 xAI 工具 schema 配置文件、不受支持的 schema 关键字、原生 `web_search` 和 HTML 实体工具调用参数解码。 -- Mistral、OpenCode Zen 和 OpenCode Go 仅使用 `capabilities`,以将转录 / 工具差异保留在核心之外。 -- 仅目录型的内置 providers,例如 `byteplus`、`cloudflare-ai-gateway`、 - `huggingface`、`kimi-coding`、`nvidia`、`qianfan`、 - `synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine`,仅使用 `catalog`。 -- Qwen 为其文本 provider 使用 `catalog`,并为其多模态表面使用共享的媒体理解和视频生成注册。 -- MiniMax 和 Xiaomi 同时使用 `catalog` 和用量钩子,因为它们的 `/usage` - 行为归插件所有,尽管推理仍通过共享传输运行。 +内置的提供商插件会根据各供应商在目录、认证、思考、重放和用量跟踪方面的需求,以不同组合使用上述 hooks。每个提供商的精确 hook 集合都与插件源码一起位于 `extensions/` 下;应以那里为权威列表,而不是在此处镜像维护。 + +示例模式: + +- **直通目录提供商**(OpenRouter、Kilocode、Z.AI、xAI)会注册 `catalog` 加 `resolveDynamicModel` / `prepareDynamicModel`,这样它们就可以在 OpenClaw 的静态目录之前暴露上游 model id。 +- **OAuth + 用量端点提供商**(GitHub Copilot、Gemini CLI、ChatGPT Codex、MiniMax、Xiaomi、z.ai)会将 `prepareRuntimeAuth` 或 `formatApiKey` 与 `resolveUsageAuth` + `fetchUsageSnapshot` 配对使用,以拥有令牌交换和 `/usage` 集成。 +- **重放 / 转录清理** 通过命名家族共享:`google-gemini`、`passthrough-gemini`、`anthropic-by-model`、`hybrid-anthropic-openai`。提供商通过 `buildReplayPolicy` 选择启用,而不是各自实现转录清理。 +- **仅目录** 的内置提供商(`byteplus`、`cloudflare-ai-gateway`、`huggingface`、`kimi-coding`、`nvidia`、`qianfan`、`synthetic`、`together`、`venice`、`vercel-ai-gateway`、`volcengine`)只注册 `catalog`,并复用共享推理循环。 +- **Anthropic 专用流辅助工具**(beta headers、`/fast` / `serviceTier`、`context1m`)位于 Anthropic 内置插件的公共 `api.ts` / `contract-api.ts` 接缝中(`wrapAnthropicProviderStream`、`resolveAnthropicBetas`、`resolveAnthropicFastMode`、`resolveAnthropicServiceTier`),而不在通用 SDK 中。 ## 运行时辅助工具 -插件可以通过 `api.runtime` 访问部分选定的核心辅助工具。对于 TTS: +插件可以通过 `api.runtime` 访问部分核心辅助工具。以 TTS 为例: ```ts const clip = await api.runtime.tts.textToSpeech({ @@ -729,14 +660,14 @@ const voices = await api.runtime.tts.listVoices({ 说明: -- `textToSpeech` 返回用于文件 / 语音便笺表面的常规核心 TTS 输出负载。 -- 使用核心 `messages.tts` 配置和 provider 选择。 -- 返回 PCM 音频缓冲区和采样率。插件必须为 providers 重新采样 / 编码。 -- `listVoices` 对每个 provider 来说是可选的。可将其用于厂商自有语音选择器或设置流程。 -- 语音列表可以包含更丰富的元数据,例如语言区域、性别和个性标签,以支持具备 provider 感知能力的选择器。 +- `textToSpeech` 返回用于文件 / 语音笔记表面的标准核心 TTS 输出负载。 +- 它使用核心 `messages.tts` 配置和提供商选择。 +- 返回 PCM 音频缓冲区 + 采样率。插件必须为各提供商自行重采样 / 编码。 +- `listVoices` 对每个提供商来说是可选的。可将其用于供应商自有语音选择器或设置流程。 +- 语音列表可以包含更丰富的元数据,例如区域设置、性别和 personality 标签,以供提供商感知型选择器使用。 - 目前 OpenAI 和 ElevenLabs 支持电话场景。Microsoft 不支持。 -插件也可以通过 `api.registerSpeechProvider(...)` 注册语音 providers。 +插件也可以通过 `api.registerSpeechProvider(...)` 注册语音提供商。 ```ts api.registerSpeechProvider({ @@ -756,12 +687,12 @@ api.registerSpeechProvider({ 说明: -- 将 TTS 策略、回退和回复投递保留在核心中。 -- 对于厂商自有的合成行为,请使用语音 providers。 -- 旧式 Microsoft `edge` 输入会被规范化为 `microsoft` provider id。 -- 推荐的归属模型是面向公司的:随着 OpenClaw 增加这些能力契约,一个厂商插件可以拥有文本、语音、图像以及未来的媒体 providers。 +- 将 TTS 策略、回退和回复交付保留在核心中。 +- 将语音提供商用于供应商自有的合成行为。 +- legacy Microsoft `edge` 输入会被规范化为 `microsoft` provider id。 +- 首选的归属模型是面向公司的:随着 OpenClaw 增加这些能力契约,一个供应商插件可以同时拥有文本、语音、图像和未来的媒体提供商。 -对于图像 / 音频 / 视频理解,插件会注册一个类型化的媒体理解 provider,而不是注册一个通用键 / 值包: +对于图像 / 音频 / 视频理解,插件会注册一个类型化的媒体理解提供商,而不是通用的键 / 值袋: ```ts api.registerMediaUnderstandingProvider({ @@ -776,11 +707,11 @@ api.registerMediaUnderstandingProvider({ 说明: - 将编排、回退、配置和渠道接线保留在核心中。 -- 将厂商行为保留在 provider 插件中。 +- 将供应商行为保留在提供商插件中。 - 增量扩展应保持类型化:新的可选方法、新的可选结果字段、新的可选能力。 -- 视频生成已经遵循相同模式: +- 视频生成也已经遵循同样的模式: - 核心拥有能力契约和运行时辅助工具 - - 厂商插件注册 `api.registerVideoGenerationProvider(...)` + - 供应商插件注册 `api.registerVideoGenerationProvider(...)` - 功能 / 渠道插件消费 `api.runtime.videoGeneration.*` 对于媒体理解运行时辅助工具,插件可以调用: @@ -798,7 +729,7 @@ const video = await api.runtime.mediaUnderstanding.describeVideoFile({ }); ``` -对于音频转录,插件既可以使用媒体理解运行时,也可以使用旧的 STT 别名: +对于音频转录,插件可以使用媒体理解运行时,或较旧的 STT 别名: ```ts const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ @@ -812,11 +743,11 @@ const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ 说明: - `api.runtime.mediaUnderstanding.*` 是图像 / 音频 / 视频理解的首选共享表面。 -- 使用核心媒体理解音频配置(`tools.media.audio`)和 provider 回退顺序。 -- 当未产生转录输出时(例如输入被跳过 / 不受支持),返回 `{ text: undefined }`。 -- `api.runtime.stt.transcribeAudioFile(...)` 仍作为兼容性别名保留。 +- 它使用核心媒体理解音频配置(`tools.media.audio`)和提供商回退顺序。 +- 当没有产生转录输出时,会返回 `{ text: undefined }`(例如输入被跳过 / 不受支持)。 +- `api.runtime.stt.transcribeAudioFile(...)` 仍保留为兼容性别名。 -插件也可以通过 `api.runtime.subagent` 启动后台子智能体运行: +插件还可以通过 `api.runtime.subagent` 启动后台子智能体运行: ```ts const result = await api.runtime.subagent.run({ @@ -830,13 +761,13 @@ const result = await api.runtime.subagent.run({ 说明: -- `provider` 和 `model` 是每次运行的可选覆盖项,不是持久性的会话变更。 -- OpenClaw 仅对受信任调用方生效这些覆盖字段。 -- 对于插件自有的回退运行,运维人员必须通过 `plugins.entries..subagent.allowModelOverride: true` 显式启用。 -- 使用 `plugins.entries..subagent.allowedModels` 将受信任插件限制到特定的规范 `provider/model` 目标,或设置为 `"*"` 以显式允许任意目标。 -- 不受信任插件的子智能体运行仍然可用,但覆盖请求会被拒绝,而不是静默回退。 +- `provider` 和 `model` 是按次运行覆盖项,而不是持久会话变更。 +- OpenClaw 仅对受信任调用方认可这些覆盖字段。 +- 对于插件拥有的回退运行,操作员必须通过 `plugins.entries..subagent.allowModelOverride: true` 明确启用。 +- 使用 `plugins.entries..subagent.allowedModels` 可将受信任插件限制为特定规范 `provider/model` 目标,或显式设为 `"*"` 以允许任意目标。 +- 不受信任的插件子智能体运行仍可工作,但覆盖请求会被拒绝,而不是静默回退。 -对于 Web 搜索,插件可以消费共享运行时辅助工具,而不是深入智能体工具接线: +对于 Web 搜索,插件可以消费共享运行时辅助工具,而不必深入智能体工具接线: ```ts const providers = api.runtime.webSearch.listProviders({ @@ -852,14 +783,13 @@ const result = await api.runtime.webSearch.search({ }); ``` -插件也可以通过 -`api.registerWebSearchProvider(...)` 注册 Web 搜索 providers。 +插件也可以通过 `api.registerWebSearchProvider(...)` 注册 Web 搜索提供商。 说明: -- 将 provider 选择、凭证解析和共享请求语义保留在核心中。 -- 对于厂商特定的搜索传输,请使用 Web 搜索 providers。 -- `api.runtime.webSearch.*` 是功能 / 渠道插件在不依赖智能体工具包装器的情况下需要搜索行为时的首选共享表面。 +- 将提供商选择、凭证解析和共享请求语义保留在核心中。 +- 将 Web 搜索提供商用于供应商专用搜索传输。 +- `api.runtime.webSearch.*` 是需要搜索行为但不依赖智能体工具包装器的功能 / 渠道插件的首选共享表面。 ### `api.runtime.imageGeneration` @@ -874,12 +804,12 @@ const providers = api.runtime.imageGeneration.listProviders({ }); ``` -- `generate(...)`:使用已配置的图像生成 provider 链生成图像。 -- `listProviders(...)`:列出可用的图像生成 providers 及其能力。 +- `generate(...)`:使用已配置的图像生成提供商链生成图像。 +- `listProviders(...)`:列出可用的图像生成提供商及其能力。 ## Gateway 网关 HTTP 路由 -插件可以通过 `api.registerHttpRoute(...)` 公开 HTTP 端点。 +插件可以通过 `api.registerHttpRoute(...)` 暴露 HTTP 端点。 ```ts api.registerHttpRoute({ @@ -897,213 +827,150 @@ api.registerHttpRoute({ 路由字段: - `path`:Gateway 网关 HTTP 服务器下的路由路径。 -- `auth`:必填。使用 `"gateway"` 以要求普通 Gateway 网关认证,或使用 `"plugin"` 以使用插件管理的认证 / webhook 校验。 +- `auth`:必填。使用 `"gateway"` 以要求常规 gateway 认证,或使用 `"plugin"` 进行插件管理的认证 / webhook 验证。 - `match`:可选。`"exact"`(默认)或 `"prefix"`。 -- `replaceExisting`:可选。允许同一插件替换自己已有的路由注册。 +- `replaceExisting`:可选。允许同一插件替换它自己现有的路由注册。 - `handler`:当路由处理了请求时返回 `true`。 说明: -- `api.registerHttpHandler(...)` 已移除,并会导致插件加载错误。请改用 `api.registerHttpRoute(...)`。 +- `api.registerHttpHandler(...)` 已被移除,并会导致插件加载错误。请改用 `api.registerHttpRoute(...)`。 - 插件路由必须显式声明 `auth`。 -- 精确的 `path + match` 冲突会被拒绝,除非设置了 `replaceExisting: true`,并且一个插件不能替换另一个插件的路由。 -- 具有不同 `auth` 级别的重叠路由会被拒绝。仅在相同认证级别内保留 `exact` / `prefix` 逐级回退链。 -- `auth: "plugin"` 路由**不会**自动接收运维人员运行时作用域。它们用于插件管理的 webhook / 签名校验,而不是特权 Gateway 网关辅助调用。 +- 除非设置 `replaceExisting: true`,否则精确 `path + match` 冲突会被拒绝,而且一个插件不能替换另一个插件的路由。 +- 不同 `auth` 级别的重叠路由会被拒绝。仅在相同 auth 级别上保留 `exact` / `prefix` 回退链。 +- `auth: "plugin"` 路由**不会**自动接收操作员运行时作用域。它们用于插件管理的 webhook / 签名验证,而不是特权 Gateway 网关辅助调用。 - `auth: "gateway"` 路由会在 Gateway 网关请求运行时作用域内运行,但该作用域是有意保守的: - - 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes` - - 带有可信身份信息的 HTTP 模式(例如 `trusted-proxy`,或私有入口上的 `gateway.auth.mode = "none"`)只有在显式存在该请求头时才会遵循 `x-openclaw-scopes` - - 如果这些带身份信息的插件路由请求中缺少 `x-openclaw-scopes`,运行时作用域会回退为 `operator.write` -- 实际规则:不要假设一个经过 gateway 认证的插件路由天然就是管理员表面。如果你的路由需要仅管理员可用的行为,请要求使用带身份信息的认证模式,并文档化显式的 `x-openclaw-scopes` 请求头契约。 + - 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes` 也是如此 + - 受信任、带身份的 HTTP 模式(例如 `trusted-proxy`,或私有入口上的 `gateway.auth.mode = "none"`)只有在显式存在该头时才会认可 `x-openclaw-scopes` + - 如果这些带身份的插件路由请求中缺少 `x-openclaw-scopes`,运行时作用域将回退为 `operator.write` +- 实际规则:不要假定 gateway-auth 插件路由天然就是隐式管理员表面。如果你的路由需要仅管理员可用的行为,请要求带身份的认证模式,并在文档中说明显式 `x-openclaw-scopes` 头契约。 ## 插件 SDK 导入路径 -在编写插件时,请使用 SDK 子路径,而不是整体式的 `openclaw/plugin-sdk` 导入: +在编写新插件时,请使用狭义 SDK 子路径,而不是整体式的 `openclaw/plugin-sdk` 根 barrel。核心子路径: -- `openclaw/plugin-sdk/plugin-entry` 用于插件注册原语。 -- `openclaw/plugin-sdk/core` 用于通用共享的面向插件契约。 -- `openclaw/plugin-sdk/config-schema` 用于根 `openclaw.json` Zod schema - 导出(`OpenClawSchema`)。 -- 稳定的渠道原语,例如 `openclaw/plugin-sdk/channel-setup`、 - `openclaw/plugin-sdk/setup-runtime`、 - `openclaw/plugin-sdk/setup-adapter-runtime`、 - `openclaw/plugin-sdk/setup-tools`、 - `openclaw/plugin-sdk/channel-pairing`、 - `openclaw/plugin-sdk/channel-contract`、 - `openclaw/plugin-sdk/channel-feedback`、 - `openclaw/plugin-sdk/channel-inbound`、 - `openclaw/plugin-sdk/channel-lifecycle`、 - `openclaw/plugin-sdk/channel-reply-pipeline`、 - `openclaw/plugin-sdk/command-auth`、 - `openclaw/plugin-sdk/secret-input`,以及 - `openclaw/plugin-sdk/webhook-ingress`,用于共享设置 / 认证 / 回复 / webhook - 接线。`channel-inbound` 是去抖动、提及匹配、入站提及策略辅助工具、信封格式化和入站信封上下文辅助工具的共享归属位置。 - `channel-setup` 是狭义的可选安装设置接缝。 - `setup-runtime` 是由 `setupEntry` / 延迟启动使用的运行时安全设置表面,其中包括导入安全的设置补丁适配器。 - `setup-adapter-runtime` 是具备环境变量感知能力的账户设置适配器接缝。 - `setup-tools` 是小型 CLI / 归档 / 文档辅助工具接缝(`formatCliCommand`、 - `detectBinary`、`extractArchive`、`resolveBrewExecutable`、`formatDocsLink`、 - `CONFIG_DIR`)。 -- 领域子路径,例如 `openclaw/plugin-sdk/channel-config-helpers`、 - `openclaw/plugin-sdk/allow-from`、 - `openclaw/plugin-sdk/channel-config-schema`、 - `openclaw/plugin-sdk/telegram-command-config`、 - `openclaw/plugin-sdk/channel-policy`、 - `openclaw/plugin-sdk/approval-gateway-runtime`、 - `openclaw/plugin-sdk/approval-handler-adapter-runtime`、 - `openclaw/plugin-sdk/approval-handler-runtime`、 - `openclaw/plugin-sdk/approval-runtime`、 - `openclaw/plugin-sdk/config-runtime`、 - `openclaw/plugin-sdk/infra-runtime`、 - `openclaw/plugin-sdk/agent-runtime`、 - `openclaw/plugin-sdk/lazy-runtime`、 - `openclaw/plugin-sdk/reply-history`、 - `openclaw/plugin-sdk/routing`、 - `openclaw/plugin-sdk/status-helpers`、 - `openclaw/plugin-sdk/text-runtime`、 - `openclaw/plugin-sdk/runtime-store`,以及 - `openclaw/plugin-sdk/directory-runtime`,用于共享运行时 / 配置辅助工具。 - `telegram-command-config` 是 Telegram 自定义命令规范化 / 校验的狭义公开接缝,即使内置 Telegram 契约表面暂时不可用,它也保持可用。 - `text-runtime` 是共享的文本 / Markdown / 日志接缝,包括对智能体可见文本的剥离、Markdown 渲染 / 分块辅助工具、脱敏辅助工具、指令标签辅助工具和安全文本工具。 -- 与审批相关的渠道接缝应优先使用插件上的单一 `approvalCapability` - 契约。随后,核心会通过这一能力读取审批认证、投递、渲染、原生路由和惰性原生处理器行为,而不是把审批行为混入不相关的插件字段中。 -- `openclaw/plugin-sdk/channel-runtime` 已弃用,目前仅作为旧插件的兼容垫片保留。新代码应改为导入更狭义的通用原语,仓库代码也不应新增对该垫片的导入。 -- 内置扩展内部实现仍然是私有的。外部插件应仅使用 `openclaw/plugin-sdk/*` 子路径。OpenClaw 核心 / 测试代码可以使用插件包根目录下仓库公开入口点,例如 `index.js`、`api.js`、 - `runtime-api.js`、`setup-entry.js`,以及像 `login-qr-api.js` 这样的狭义文件。 - 永远不要从核心或另一个扩展中导入插件包的 `src/*`。 -- 仓库入口点拆分: - `/api.js` 是辅助工具 / 类型 barrel, - `/runtime-api.js` 是仅运行时 barrel, - `/index.js` 是内置插件入口, - `/setup-entry.js` 是设置插件入口。 -- 当前内置 provider 示例: - - Anthropic 使用 `api.js` / `contract-api.js` 作为 Claude 流辅助工具接缝,例如 `wrapAnthropicProviderStream`、beta 请求头辅助工具和 `service_tier` - 解析。 - - OpenAI 使用 `api.js` 提供 provider 构建器、默认模型辅助工具和实时 provider 构建器。 - - OpenRouter 使用 `api.js` 提供其 provider 构建器以及新手引导 / 配置辅助工具,而 `register.runtime.js` 仍可以为仓库本地使用重新导出通用 - `plugin-sdk/provider-stream` 辅助工具。 -- 通过 facade 加载的公开入口点会在存在活动运行时配置快照时优先使用它;如果 OpenClaw 尚未提供运行时快照,则回退到磁盘上的已解析配置文件。 -- 通用共享原语仍然是首选的公开 SDK 契约。仍然存在一小组保留的、与内置渠道品牌相关的兼容性辅助工具接缝。应将这些视为内置维护 / 兼容性接缝,而不是新的第三方导入目标;新的跨渠道契约仍应落在通用 `plugin-sdk/*` 子路径或插件本地 `api.js` / - `runtime-api.js` barrel 上。 +| 子路径 | 用途 | +| ----------------------------------- | -------------------------------------------------- | +| `openclaw/plugin-sdk/plugin-entry` | 插件注册原语 | +| `openclaw/plugin-sdk/core` | 通用共享的面向插件契约 | +| `openclaw/plugin-sdk/config-schema` | 根 `openclaw.json` Zod schema(`OpenClawSchema`) | -兼容性说明: +渠道插件可从一组狭义接缝中进行选择——`channel-setup`、`setup-runtime`、`setup-adapter-runtime`、`setup-tools`、`channel-pairing`、`channel-contract`、`channel-feedback`、`channel-inbound`、`channel-lifecycle`、`channel-reply-pipeline`、`command-auth`、`secret-input`、`webhook-ingress`、`channel-targets` 和 `channel-actions`。审批行为应统一收敛到一个 `approvalCapability` 契约,而不是混杂在无关的插件字段之间。参见[渠道插件](/zh-CN/plugins/sdk-channel-plugins)。 -- 新代码应避免使用根 `openclaw/plugin-sdk` barrel。 -- 优先使用狭义稳定原语。较新的 setup / pairing / reply / - feedback / contract / inbound / threading / command / secret-input / webhook / infra / - allowlist / status / message-tool 子路径,是新内置插件和外部插件开发的预期契约。 - 目标解析 / 匹配应归属于 `openclaw/plugin-sdk/channel-targets`。 - 消息动作闸门和 reaction message-id 辅助工具应归属于 - `openclaw/plugin-sdk/channel-actions`。 -- 内置扩展特定的辅助工具 barrel 默认并不稳定。如果某个辅助工具只被某个内置扩展需要,应将它保留在该扩展本地的 `api.js` 或 `runtime-api.js` 接缝后面,而不是将其提升到 - `openclaw/plugin-sdk/`。 -- 新的共享辅助工具接缝应当是通用的,而不是带渠道品牌的。共享目标解析应归属于 `openclaw/plugin-sdk/channel-targets`;渠道特定内部实现应保留在拥有该渠道的插件本地 `api.js` 或 `runtime-api.js` - 接缝之后。 -- `image-generation`、 - `media-understanding` 和 `speech` 等能力特定子路径之所以存在,是因为内置 / 原生插件今天正在使用它们。它们的存在本身并不意味着每一个导出的辅助工具都是长期冻结的外部契约。 +运行时和配置辅助工具位于对应的 `*-runtime` 子路径下(`approval-runtime`、`config-runtime`、`infra-runtime`、`agent-runtime`、`lazy-runtime`、`directory-runtime`、`text-runtime`、`runtime-store` 等)。 + + +`openclaw/plugin-sdk/channel-runtime` 已弃用——它是为旧插件保留的兼容性 shim。新代码应改为导入更狭义的通用原语。 + + +仓库内部入口点(每个内置插件包根目录): + +- `index.js` —— 内置插件入口 +- `api.js` —— 辅助工具 / 类型 barrel +- `runtime-api.js` —— 仅运行时 barrel +- `setup-entry.js` —— setup 插件入口 + +外部插件应仅导入 `openclaw/plugin-sdk/*` 子路径。绝不要从核心或其他插件中导入另一个插件包的 `src/*`。由 facade 加载的入口点会优先使用当前激活的运行时配置快照;如果不存在,则回退到磁盘上已解析的配置文件。 + +诸如 `image-generation`、`media-understanding` 和 `speech` 这样的能力专用子路径之所以存在,是因为当前的内置插件正在使用它们。它们并不自动等同于长期冻结的外部契约——依赖它们时,请查阅对应的 SDK 参考页面。 ## 消息工具 schema -对于 reaction、已读和投票等非消息原语,插件应拥有渠道特定的 `describeMessageTool(...)` schema 贡献。 -共享发送呈现应使用通用 `MessagePresentation` 契约,而不是 provider 原生的 button、component、block 或 card 字段。 -契约、回退规则、provider 映射和插件作者检查清单请参见 [消息呈现](/zh-CN/plugins/message-presentation)。 +对于反应、已读和投票等非消息原语,插件应拥有渠道专用的 `describeMessageTool(...)` schema 贡献。共享发送呈现应使用通用 `MessagePresentation` 契约,而不是提供商原生的按钮、组件、区块或卡片字段。 +关于该契约、回退规则、提供商映射和插件作者清单,请参阅[消息呈现](/zh-CN/plugins/message-presentation)。 -具备发送能力的插件通过消息能力声明其可渲染内容: +具备发送能力的插件通过消息能力声明自己能渲染的内容: -- `presentation` 用于语义化呈现块(`text`、`context`、`divider`、`buttons`、`select`) -- `delivery-pin` 用于置顶投递请求 +- `presentation`,用于语义化呈现区块(`text`、`context`、`divider`、`buttons`、`select`) +- `delivery-pin`,用于固定投递请求 -核心决定是原生渲染该呈现,还是将其降级为文本。不要从通用消息工具中公开 provider 原生 UI 逃生口。 -为兼容现有第三方插件而保留的旧式原生 schema SDK 辅助工具仍然会导出,但新插件不应使用它们。 +核心决定是原生渲染该呈现,还是将其降级为文本。不要从通用 message 工具暴露提供商原生 UI 逃生口。 +面向 legacy 原生 schema 的已弃用 SDK 辅助工具仍然会为现有第三方插件保留导出,但新插件不应使用它们。 ## 渠道目标解析 -渠道插件应拥有渠道特定的目标语义。保持共享出站宿主的通用性,并使用消息适配器表面承载 provider 规则: +渠道插件应拥有渠道专用的目标语义。保持共享 outbound host 的通用性,并使用消息适配器表面处理提供商规则: -- `messaging.inferTargetChatType({ to })` 决定规范化目标在目录查找之前应被视为 `direct`、`group` 还是 `channel`。 -- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉核心,某个输入是否应跳过目录搜索,直接进入类似 id 的解析。 -- `messaging.targetResolver.resolveTarget(...)` 是插件回退路径,用于在规范化之后或目录未命中之后,由核心执行最终的 provider 自有解析。 -- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后拥有 provider 特定的会话路由构造逻辑。 +- `messaging.inferTargetChatType({ to })` 决定某个规范化目标在目录查找前应被视为 `direct`、`group` 还是 `channel` +- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉核心某个输入是否应跳过目录搜索,直接进入类 id 解析 +- `messaging.targetResolver.resolveTarget(...)` 是插件回退路径,用于在规范化之后或目录未命中之后,由核心进行最终的提供商自有解析 +- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后拥有提供商专用的会话路由构造逻辑 -推荐拆分方式: +推荐拆分: -- 对于应在搜索联系人 / 群组之前做出的类别决策,使用 `inferTargetChatType`。 -- 对于“将其视为显式 / 原生目标 id”的检查,使用 `looksLikeId`。 -- 对于 provider 特定的规范化回退,使用 `resolveTarget`,而不是将其用于广泛的目录搜索。 -- 将 provider 原生 id,例如 chat id、thread id、JID、handle 和 room id,保留在 `target` 值或 provider 特定参数中,而不是放在通用 SDK 字段里。 +- 对于应在搜索 peers / groups 之前发生的类别判定,使用 `inferTargetChatType` +- 对于“将其视为显式 / 原生目标 id”的判断,使用 `looksLikeId` +- 对于提供商专用的规范化回退,使用 `resolveTarget`,而不是用于广义目录搜索 +- 将提供商原生 id,例如 chat id、thread id、JID、handle 和 room id,保留在 `target` 值或提供商专用参数中,而不要放进通用 SDK 字段 ## 基于配置的目录 -如果插件需要从配置推导目录项,应将该逻辑保留在插件中,并复用 -`openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。 +对于从配置派生目录条目的插件,应将该逻辑保留在插件内部,并复用 `openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。 -当某个渠道需要基于配置的联系人 / 群组时,可以使用此方式,例如: +当某个渠道需要基于配置的 peers / groups 时,可使用这种方式,例如: -- 基于 allowlist 驱动的私信联系人 +- 基于 allowlist 的私信 peers - 已配置的渠道 / 群组映射 - 按账户划分的静态目录回退 -`directory-runtime` 中的共享辅助工具只处理通用操作: +`directory-runtime` 中的共享辅助工具仅处理通用操作: - 查询过滤 -- 限制应用 +- 应用限制 - 去重 / 规范化辅助工具 - 构建 `ChannelDirectoryEntry[]` -渠道特定的账户检查和 id 规范化应保留在插件实现中。 +渠道专用的账户检查和 id 规范化应保留在插件实现中。 -## provider 目录 +## 提供商目录 -provider 插件可以通过 -`registerProvider({ catalog: { run(...) { ... } } })` 定义用于推理的模型目录。 +提供商插件可以通过 `registerProvider({ catalog: { run(...) { ... } } })` 为推理定义模型目录。 -`catalog.run(...)` 返回与 OpenClaw 写入 -`models.providers` 中相同的结构: +`catalog.run(...)` 返回与 OpenClaw 写入 `models.providers` 相同的结构: -- `{ provider }` 表示一个 provider 条目 -- `{ providers }` 表示多个 provider 条目 +- `{ provider }`,表示一个提供商条目 +- `{ providers }`,表示多个提供商条目 -当插件拥有 provider 特定的 model id、base URL 默认值或受认证门控的模型元数据时,请使用 `catalog`。 +当插件拥有提供商专用的 model id、base URL 默认值或受认证门控的模型元数据时,请使用 `catalog`。 -`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式 providers 的合并时机: +`catalog.order` 控制某个插件目录相对于 OpenClaw 内置隐式提供商的合并时机: -- `simple`:纯 API key 或环境变量驱动的 providers -- `profile`:当存在认证配置文件时出现的 providers -- `paired`:会合成多个相关 provider 条目的 providers -- `late`:最后一轮,在其他隐式 providers 之后 +- `simple`:普通 API 密钥或基于环境变量的提供商 +- `profile`:存在认证配置文件时出现的提供商 +- `paired`:合成多个相关提供商条目的提供商 +- `late`:最后一轮,在其他隐式提供商之后 -后出现的 provider 会在键冲突时胜出,因此插件可以有意覆盖具有相同 provider id 的内置 provider 条目。 +后面的提供商在键冲突时会获胜,因此插件可以有意用相同 provider id 覆盖内置提供商条目。 兼容性: -- `discovery` 仍可作为旧式别名使用 +- `discovery` 作为 legacy 别名仍然可用 - 如果同时注册了 `catalog` 和 `discovery`,OpenClaw 会使用 `catalog` ## 只读渠道检查 -如果你的插件注册了一个渠道,请优先在 `resolveAccount(...)` 之外同时实现 -`plugin.config.inspectAccount(cfg, accountId)`。 +如果你的插件注册了一个渠道,除了 `resolveAccount(...)` 之外,还应优先实现 `plugin.config.inspectAccount(cfg, accountId)`。 原因: -- `resolveAccount(...)` 是运行时路径。它可以假定凭证已经完全实体化,并且在缺少必要密钥时快速失败。 -- 只读命令路径,例如 `openclaw status`、`openclaw status --all`、 - `openclaw channels status`、`openclaw channels resolve`,以及 doctor / 配置修复流程,不应仅为了描述配置就必须实体化运行时凭证。 +- `resolveAccount(...)` 是运行时路径。它可以假设凭证已被完整实体化,并且在缺少必需 secret 时快速失败。 +- 像 `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve` 以及 doctor / 配置修复流程这样的只读命令路径,不应为了描述配置就必须实体化运行时凭证。 推荐的 `inspectAccount(...)` 行为: -- 只返回描述性的账户状态。 +- 仅返回描述性账户状态。 - 保留 `enabled` 和 `configured`。 - 在相关时包含凭证来源 / 状态字段,例如: - `tokenSource`、`tokenStatus` - `botTokenSource`、`botTokenStatus` - `appTokenSource`、`appTokenStatus` - `signingSecretSource`、`signingSecretStatus` -- 你不需要仅为了报告只读可用性而返回原始 token 值。对于状态类命令,返回 `tokenStatus: "available"`(以及对应的来源字段)就足够了。 -- 当凭证通过 SecretRef 配置但在当前命令路径中不可用时,请使用 `configured_unavailable`。 +- 你不需要为了报告只读可用性而返回原始令牌值。返回 `tokenStatus: "available"`(以及匹配的来源字段)就足以满足 status 风格命令。 +- 当某个凭证通过 SecretRef 配置,但在当前命令路径中不可用时,请使用 `configured_unavailable`。 -这样,只读命令就可以报告“已配置,但在当前命令路径中不可用”,而不是崩溃或错误地将该账户报告为未配置。 +这样可以让只读命令报告“已配置,但在此命令路径中不可用”,而不是崩溃或错误地将该账户报告为未配置。 -## Package packs +## 包集合 插件目录可以包含带有 `openclaw.extensions` 的 `package.json`: @@ -1117,46 +984,37 @@ provider 插件可以通过 } ``` -每个条目都会成为一个插件。如果该 pack 列出了多个扩展,则插件 id -会变为 `name/`。 +每个条目都会成为一个插件。如果该包集合列出了多个扩展,则插件 id 将变为 `name/`。 -如果你的插件导入了 npm 依赖,请在该目录中安装它们,以便 `node_modules` -可用(`npm install` / `pnpm install`)。 +如果你的插件导入了 npm 依赖,请在该目录中安装它们,以便 `node_modules` 可用(`npm install` / `pnpm install`)。 -安全护栏:每个 `openclaw.extensions` 条目在解析符号链接后都必须保持在插件目录内。任何逃逸出包目录的条目都会被拒绝。 +安全护栏:每个 `openclaw.extensions` 条目在解析符号链接后都必须保留在插件目录内。任何逃逸出包目录的条目都会被拒绝。 -安全说明:`openclaw plugins install` 会使用 -`npm install --omit=dev --ignore-scripts` 安装插件依赖(无生命周期脚本,运行时无开发依赖)。请保持插件依赖树为“纯 JS / TS”,并避免需要 `postinstall` 构建的包。 +安全说明:`openclaw plugins install` 会使用 `npm install --omit=dev --ignore-scripts` 安装插件依赖(无生命周期脚本、运行时不安装开发依赖)。请保持插件依赖树为“纯 JS / TS”,并避免需要 `postinstall` 构建的包。 -可选:`openclaw.setupEntry` 可以指向一个轻量级、仅用于设置的模块。 -当 OpenClaw 需要为一个已禁用的渠道插件提供设置表面,或者某个渠道插件已启用但尚未完成配置时,它会加载 `setupEntry` -而不是完整插件入口。这样在你的主插件入口还会接线工具、钩子或其他仅运行时代码时,可以让启动和设置更轻量。 +可选:`openclaw.setupEntry` 可以指向一个轻量级、仅 setup 的模块。当 OpenClaw 需要为已禁用的渠道插件提供 setup 表面,或某个渠道插件已启用但尚未配置时,它会加载 `setupEntry`,而不是完整插件入口。这样当主插件入口还会接线工具、hooks 或其他仅运行时代码时,就能让启动和 setup 更轻量。 -可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` -可以让某个渠道插件在 Gateway 网关监听前的启动阶段也走相同的 `setupEntry` 路径,即使该渠道已经配置完成。 +可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` 可让某个渠道插件在 Gateway 网关监听前的启动阶段,即使该渠道已配置,也采用同样的 `setupEntry` 路径。 -只有在 `setupEntry` 能完全覆盖 Gateway 网关开始监听之前必须存在的启动表面时,才应使用此选项。实际而言,这意味着设置入口必须注册启动所依赖的每一项渠道自有能力,例如: +只有当 `setupEntry` 完整覆盖了 gateway 开始监听前必须存在的启动表面时,才应使用此选项。实践中,这意味着 setup 入口必须注册启动所依赖的每一项渠道自有能力,例如: - 渠道注册本身 -- 任何必须在 Gateway 网关开始监听前可用的 HTTP 路由 -- 任何必须在同一时间窗口内存在的 Gateway 网关方法、工具或服务 +- 任何必须在 gateway 开始监听前可用的 HTTP 路由 +- 在同一时间窗口内必须存在的任何 gateway 方法、工具或服务 -如果你的完整入口仍然拥有任何必需的启动能力,请不要启用此标志。保持插件的默认行为,让 OpenClaw 在启动期间加载完整入口。 +如果你的完整入口仍然拥有任何必需的启动能力,请不要启用此标志。保持插件采用默认行为,并让 OpenClaw 在启动期间加载完整入口。 -内置渠道还可以发布仅用于设置的契约表面辅助工具,供核心在完整渠道运行时加载之前查询。当前的设置提升表面包括: +内置渠道也可以发布仅 setup 的契约表面辅助工具,以便核心在完整渠道运行时加载之前进行查询。当前的 setup 提升表面包括: - `singleAccountKeysToMove` - `namedAccountPromotionKeys` - `resolveSingleAccountPromotionTarget(...)` -当核心需要在不加载完整插件入口的情况下,将旧式单账户渠道配置提升到 -`channels..accounts.*` 时,会使用这部分表面。Matrix 是当前的内置示例:当已存在命名账户时,它只会将认证 / 引导键移动到某个已命名的提升账户中,并且它可以保留一个已配置的非规范默认账户键,而不是总是创建 -`accounts.default`。 +当核心需要在不加载完整插件入口的情况下,将 legacy 单账户渠道配置提升到 `channels..accounts.*` 时,就会使用该表面。Matrix 是当前的内置示例:当已存在命名账户时,它只会将认证 / 引导键移动到一个命名的已提升账户中,并且可以保留已配置的非规范默认账户键,而不是总是创建 `accounts.default`。 -这些设置补丁适配器会让内置契约表面发现保持延迟加载。导入时保持轻量;提升表面只会在首次使用时加载,而不会在模块导入期间重新进入内置渠道启动流程。 +这些 setup 补丁适配器使内置契约表面发现保持懒加载。导入时开销保持轻量;提升表面只会在首次使用时加载,而不会在模块导入时重新进入内置渠道启动流程。 -当这些启动表面包含 Gateway 网关 RPC 方法时,请将它们保留在插件特定前缀下。核心管理命名空间(`config.*`、 -`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且始终解析为 `operator.admin`,即使某个插件请求更窄的作用域也是如此。 +当这些启动表面包含 gateway RPC 方法时,请将它们保留在插件专用前缀下。核心管理员命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且始终解析为 `operator.admin`,即使某个插件请求了更窄的作用域。 示例: @@ -1175,7 +1033,7 @@ provider 插件可以通过 ### 渠道目录元数据 -渠道插件可以通过 `openclaw.channel` 宣告设置 / 发现元数据,并通过 `openclaw.install` 宣告安装提示。这样可以让核心目录保持无数据状态。 +渠道插件可以通过 `openclaw.channel` 声明 setup / 发现元数据,并通过 `openclaw.install` 声明安装提示。这样可以让核心目录保持无数据耦合。 示例: @@ -1190,7 +1048,7 @@ provider 插件可以通过 "selectionLabel": "Nextcloud Talk (self-hosted)", "docsPath": "/channels/nextcloud-talk", "docsLabel": "nextcloud-talk", - "blurb": "通过 Nextcloud Talk webhook bots 提供自托管聊天。", + "blurb": "通过 Nextcloud Talk webhook 机器人实现的自托管聊天。", "order": 65, "aliases": ["nc-talk", "nc"] }, @@ -1203,38 +1061,34 @@ provider 插件可以通过 } ``` -除了最小示例之外,有用的 `openclaw.channel` 字段还包括: +除最小示例外,有用的 `openclaw.channel` 字段还包括: - `detailLabel`:用于更丰富目录 / 状态表面的次级标签 - `docsLabel`:覆盖文档链接的链接文本 -- `preferOver`:当前目录条目应优先于的低优先级插件 / 渠道 id +- `preferOver`:此目录条目应优先于的低优先级插件 / 渠道 id - `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择表面的文案控制项 -- `markdownCapable`:将该渠道标记为支持 Markdown,以供出站格式决策使用 -- `exposure.configured`:设为 `false` 时,在已配置渠道列表表面中隐藏该渠道 -- `exposure.setup`:设为 `false` 时,在交互式设置 / 配置选择器中隐藏该渠道 -- `exposure.docs`:将该渠道标记为内部 / 私有,以供文档导航表面使用 -- `showConfigured` / `showInSetup`:旧式别名,出于兼容性仍可接受;优先使用 `exposure` +- `markdownCapable`:将该渠道标记为支持 Markdown,以供出站格式化决策使用 +- `exposure.configured`:设为 `false` 时,在“已配置渠道”列表表面中隐藏该渠道 +- `exposure.setup`:设为 `false` 时,在交互式 setup / configure 选择器中隐藏该渠道 +- `exposure.docs`:将该渠道标记为内部 / 私有,用于文档导航表面 +- `showConfigured` / `showInSetup`:出于兼容性仍接受的 legacy 别名;优先使用 `exposure` - `quickstartAllowFrom`:让该渠道接入标准快速开始 `allowFrom` 流程 - `forceAccountBinding`:即使只存在一个账户,也要求显式账户绑定 -- `preferSessionLookupForAnnounceTarget`:在解析公告目标时优先使用会话查找 +- `preferSessionLookupForAnnounceTarget`:在解析 announce 目标时优先使用会话查找 -OpenClaw 还可以合并**外部渠道目录**(例如 MPM -注册表导出)。将 JSON 文件放在以下任一位置: +OpenClaw 还可以合并**外部渠道目录**(例如 MPM 注册表导出)。将 JSON 文件放到以下任一位置: - `~/.openclaw/mpm/plugins.json` - `~/.openclaw/mpm/catalog.json` - `~/.openclaw/plugins/catalog.json` -或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(用逗号 / 分号 / `PATH` 分隔)。每个文件应包含 -`{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的旧式别名。 +或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(以逗号 / 分号 / `PATH` 分隔)。每个文件应包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器还接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的 legacy 别名。 ## 上下文引擎插件 -上下文引擎插件拥有会话上下文编排,包括摄取、组装和压缩。可在你的插件中通过 -`api.registerContextEngine(id, factory)` 注册它们,然后通过 -`plugins.slots.contextEngine` 选择活动引擎。 +上下文引擎插件拥有会话上下文编排,包括摄取、组装和压缩。可在你的插件中通过 `api.registerContextEngine(id, factory)` 注册它们,然后使用 `plugins.slots.contextEngine` 选择活动引擎。 -当你的插件需要替换或扩展默认上下文流水线,而不是仅仅添加 memory 搜索或钩子时,请使用这种方式。 +当你的插件需要替换或扩展默认上下文流水线,而不只是添加 memory 搜索或 hooks 时,请使用此方式。 ```ts import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core"; @@ -1262,7 +1116,7 @@ export default function (api) { } ``` -如果你的引擎**不**拥有压缩算法,请保持实现 `compact()`,并显式委托它: +如果你的引擎**不**拥有压缩算法,请保持 `compact()` 已实现,并显式委托它: ```ts import { @@ -1299,37 +1153,37 @@ export default function (api) { ## 添加新能力 -当某个插件需要当前 API 无法适配的行为时,不要通过私有深入访问绕过插件系统。应添加缺失的能力。 +当插件需要当前 API 无法满足的行为时,不要通过私有内部访问绕过插件系统。请添加缺失的能力。 推荐顺序: -1. 定义核心契约 - 决定核心应拥有哪些共享行为:策略、回退、配置合并、生命周期、面向渠道的语义,以及运行时辅助工具形态。 -2. 添加类型化的插件注册 / 运行时表面 - 用最小但有用的类型化能力表面扩展 `OpenClawPluginApi` 和 / 或 `api.runtime`。 -3. 接线核心 + 渠道 / 功能使用方 - 渠道和功能插件应通过核心消费这项新能力,而不是直接导入某个厂商实现。 -4. 注册厂商实现 - 然后由厂商插件将其后端注册到这项能力上。 -5. 添加契约覆盖 - 增加测试,以便让归属和注册形态在长期演进中保持明确。 +1. 定义核心契约 + 决定核心应拥有哪些共享行为:策略、回退、配置合并、生命周期、面向渠道的语义以及运行时辅助工具结构。 +2. 添加类型化的插件注册 / 运行时表面 + 以最小但有用的类型化能力表面扩展 `OpenClawPluginApi` 和 / 或 `api.runtime`。 +3. 对接核心 + 渠道 / 功能消费者 + 渠道和功能插件应通过核心消费新能力,而不是直接导入某个供应商实现。 +4. 注册供应商实现 + 然后由供应商插件针对该能力注册其后端实现。 +5. 添加契约覆盖 + 添加测试,使归属和注册结构随着时间推移仍保持明确。 -这就是 OpenClaw 如何在保持明确设计立场的同时,不被某个 provider 的世界观硬编码。具体的文件检查清单和完整示例,请参见 [能力扩展手册](/zh-CN/plugins/architecture)。 +这就是 OpenClaw 保持鲜明主张、又不会被某个供应商世界观硬编码绑死的方式。关于具体的文件清单和完整示例,请参阅[能力扩展手册](/zh-CN/plugins/architecture)。 -### 能力检查清单 +### 能力清单 -当你添加新能力时,实现通常应一起涉及以下表面: +当你添加一个新能力时,实现通常应同时涉及以下表面: - `src//types.ts` 中的核心契约类型 - `src//runtime.ts` 中的核心 runner / 运行时辅助工具 - `src/plugins/types.ts` 中的插件 API 注册表面 - `src/plugins/registry.ts` 中的插件注册表接线 -- 当功能 / 渠道插件需要消费它时,`src/plugins/runtime/*` 中的插件运行时公开表面 +- 当功能 / 渠道插件需要消费它时,`src/plugins/runtime/*` 中的插件运行时暴露 - `src/test-utils/plugin-registration.ts` 中的捕获 / 测试辅助工具 - `src/plugins/contracts/registry.ts` 中的归属 / 契约断言 -- `docs/` 中的运维 / 插件文档 +- `docs/` 中面向操作员 / 插件的文档 -如果这些表面中缺了某一项,通常说明该能力还没有完全接入。 +如果其中某个表面缺失,通常说明这个能力还没有完全集成。 ### 能力模板 @@ -1368,6 +1222,6 @@ expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]); 这样规则就很简单: - 核心拥有能力契约 + 编排 -- 厂商插件拥有厂商实现 +- 供应商插件拥有供应商实现 - 功能 / 渠道插件消费运行时辅助工具 - 契约测试让归属保持明确