diff --git a/docs/zh-CN/plugins/architecture.md b/docs/zh-CN/plugins/architecture.md
index 555b9916f..82654193f 100644
--- a/docs/zh-CN/plugins/architecture.md
+++ b/docs/zh-CN/plugins/architecture.md
@@ -2,16 +2,16 @@
read_when:
- 构建或调试原生 OpenClaw 插件
- 理解插件能力模型或归属边界
- - 开发插件加载流水线或注册表
+ - 处理插件加载流水线或注册表
- 实现提供商运行时钩子或渠道插件
sidebarTitle: Internals
summary: 插件内部机制:能力模型、归属、契约、加载流水线和运行时辅助工具
title: 插件内部机制
x-i18n:
- generated_at: "2026-04-12T09:53:36Z"
+ generated_at: "2026-04-12T16:25:37Z"
model: gpt-5.4
provider: openai
- source_hash: 5bf11fc59b5e201837708ea1ac6ef4bbbdc6f1f6e853fb888fff08ed5d38a370
+ source_hash: 37361c1e9d2da57c77358396f19dfc7f749708b66ff68f1bf737d051b5d7675d
source_path: plugins/architecture.md
workflow: 15
---
@@ -19,12 +19,12 @@ 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) —— 导入映射和注册 API
本页介绍 OpenClaw 插件系统的内部架构。
@@ -48,99 +48,99 @@ x-i18n:
| Web 搜索 | `api.registerWebSearchProvider(...)` | `google` |
| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`, `matrix` |
-如果一个插件注册了零个能力,但提供了钩子、工具或服务,那么它就是一个**仅 legacy 钩子**插件。这种模式仍然得到完全支持。
+如果一个插件注册了零个能力,但提供了钩子、工具或服务,它就是一个**仅旧版钩子**插件。这种模式仍然受到完整支持。
### 外部兼容性立场
-能力模型已经在核心中落地,并已被当前的内置 / 原生插件使用,但外部插件兼容性仍需要比“它已导出,因此它已冻结”更严格的标准。
+能力模型已经在核心中落地,并且当前已被内置 / 原生插件使用,但外部插件兼容性仍然需要比“它已导出,因此它被冻结了”更严格的标准。
当前指导原则:
-- **现有外部插件:** 保持基于钩子的集成继续可用;将其视为兼容性的基线
-- **新的内置 / 原生插件:** 优先使用显式能力注册,而不是厂商特定的内部访问或新的仅钩子设计
-- **采用能力注册的外部插件:** 允许,但除非文档明确将某个契约标记为稳定,否则应将能力特定的辅助接口视为仍在演进中
+- **现有外部插件:** 保持基于钩子的集成正常工作;将其视为兼容性基线
+- **新的内置 / 原生插件:** 优先使用显式能力注册,而不是供应商特定的内部接入方式,或新的仅钩子设计
+- **采用能力注册的外部插件:** 允许这样做,但除非文档明确将某个契约标记为稳定,否则应将能力特定的辅助接口视为仍在演进中
实践规则:
- 能力注册 API 是预期的发展方向
-- 在过渡期间,对于外部插件来说,legacy 钩子仍然是最安全、最不容易破坏兼容性的路径
-- 并非所有导出的辅助子路径都同等重要;优先使用文档化的狭义契约,而不是偶然暴露出来的辅助导出
+- 在过渡期间,对于外部插件,旧版钩子仍然是最安全、最不容易破坏兼容性的路径
+- 已导出的辅助子路径并不完全等价;应优先使用有文档说明的窄契约,而不是偶然暴露出来的辅助导出
### 插件形态
-OpenClaw 会根据每个已加载插件的实际注册行为(而不只是静态元数据)将其分类为某种形态:
+OpenClaw 会根据每个已加载插件的实际注册行为(而不仅仅是静态元数据)将其归类为某种形态:
-- **plain-capability** —— 仅注册一种能力类型(例如仅提供商插件 `mistral`)
-- **hybrid-capability** —— 注册多种能力类型(例如 `openai` 拥有文本推理、语音、媒体理解和图像生成)
+- **plain-capability** —— 只注册一种能力类型(例如仅提供商插件 `mistral`)
+- **hybrid-capability** —— 注册多种能力类型(例如 `openai` 同时拥有文本推理、语音、媒体理解和图像生成)
- **hook-only** —— 仅注册钩子(类型化或自定义),不注册能力、工具、命令或服务
-- **non-capability** —— 注册工具、命令、服务或路由,但不注册任何能力
+- **non-capability** —— 注册工具、命令、服务或路由,但不注册能力
-使用 `openclaw plugins inspect ` 查看某个插件的形态和能力明细。详情参见 [CLI 参考](/cli/plugins#inspect)。
+使用 `openclaw plugins inspect ` 可查看插件的形态和能力明细。详情请参见 [CLI 参考](/cli/plugins#inspect)。
-### Legacy 钩子
+### 旧版钩子
-`before_agent_start` 钩子仍然作为仅钩子插件的兼容路径受到支持。现实中的 legacy 插件仍然依赖它。
+`before_agent_start` 钩子仍然作为仅钩子插件的兼容路径受到支持。现实中仍有旧版插件依赖它。
-方向是:
+方向如下:
- 保持其可用
-- 将其文档化为 legacy
+- 在文档中将其标记为旧版
- 对于模型 / 提供商覆盖工作,优先使用 `before_model_resolve`
-- 对于提示词修改工作,优先使用 `before_prompt_build`
-- 仅在真实使用量下降且夹具覆盖证明迁移安全后才移除
+- 对于提示词变更工作,优先使用 `before_prompt_build`
+- 只有在实际使用量下降且固定测试覆盖证明迁移安全之后,才考虑移除
### 兼容性信号
-当你运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,可能会看到以下标签之一:
+当你运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,你可能会看到以下标签之一:
| 信号 | 含义 |
| -------------------------- | ------------------------------------------------------------ |
-| **config valid** | 配置可正常解析,插件也能正常解析 |
-| **compatibility advisory** | 插件使用了受支持但较旧的模式(例如 `hook-only`) |
-| **legacy warning** | 插件使用 `before_agent_start`,该方式已弃用 |
+| **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` 中。
## 架构概览
-OpenClaw 的插件系统有四层:
+OpenClaw 的插件系统包含四层:
-1. **清单 + 发现**
- OpenClaw 会从已配置路径、工作区根目录、全局扩展根目录以及内置扩展中查找候选插件。设备发现会优先读取原生的 `openclaw.plugin.json` 清单以及受支持的 bundle 清单。
-2. **启用 + 校验**
- 核心会决定已发现的插件是启用、禁用、阻止,还是被选入某个独占槽位(例如 memory)。
-3. **运行时加载**
- 原生 OpenClaw 插件通过 jiti 在进程内加载,并将能力注册到一个中央注册表中。兼容的 bundle 会被规范化为注册表记录,而无需导入运行时代码。
-4. **接口消费**
+1. **清单 + 发现**
+ OpenClaw 会从已配置路径、workspace 根目录、全局扩展根目录以及内置扩展中查找候选插件。发现过程会优先读取原生 `openclaw.plugin.json` 清单以及受支持的 bundle 清单。
+2. **启用 + 验证**
+ 核心决定一个已发现的插件是启用、禁用、阻止,还是被选中用于某个独占槽位(例如 memory)。
+3. **运行时加载**
+ 原生 OpenClaw 插件会通过 jiti 在进程内加载,并将能力注册到中央注册表中。兼容的 bundle 会被规范化为注册表记录,而无需导入运行时代码。
+4. **接口消费**
OpenClaw 的其余部分会读取注册表,以暴露工具、渠道、提供商设置、钩子、HTTP 路由、CLI 命令和服务。
-对于插件 CLI 而言,根命令发现专门分成两个阶段:
+对于插件 CLI 而言,根命令发现专门分为两个阶段:
- 解析时元数据来自 `registerCli(..., { descriptors: [...] })`
-- 真正的插件 CLI 模块可以保持懒加载,并在首次调用时再注册
+- 真实的插件 CLI 模块可以保持惰性,仅在首次调用时注册
-这样既能让插件自有的 CLI 代码保留在插件内部,又能让 OpenClaw 在解析前预留根命令名称。
+这样可以让插件自有的 CLI 代码保留在插件内部,同时仍允许 OpenClaw 在解析前预留根命令名称。
重要的设计边界是:
-- 设备发现 + 配置校验应基于**清单 / schema 元数据**完成,而无需执行插件代码
+- 发现 + 配置验证应该能基于**清单 / schema 元数据**完成,而无需执行插件代码
- 原生运行时行为来自插件模块的 `register(api)` 路径
-这种拆分让 OpenClaw 能够在完整运行时尚未激活之前,就完成配置校验、解释缺失 / 已禁用插件的原因,并构建 UI / schema 提示。
+这种拆分使 OpenClaw 能够在完整运行时尚未激活时,就验证配置、解释插件缺失 / 禁用原因,并构建 UI / schema 提示。
-### 渠道插件与共享 message 工具
+### 渠道插件和共享 message 工具
-对于常规聊天操作,渠道插件不需要单独注册发送 / 编辑 / 反应工具。OpenClaw 在核心中保留一个共享的 `message` 工具,而渠道插件负责其背后的渠道特定发现和执行逻辑。
+对于常规聊天操作,渠道插件不需要单独注册发送 / 编辑 / 响应工具。OpenClaw 在核心中保留了一个共享的 `message` 工具,而渠道插件则在其背后拥有渠道特定的发现和执行逻辑。
当前边界如下:
-- 核心拥有共享 `message` 工具宿主、提示词接线、会话 / 线程簿记,以及执行分发
-- 渠道插件拥有作用域化动作发现、能力发现,以及所有渠道特定 schema 片段
-- 渠道插件拥有提供商特定的会话对话语法,例如会话 id 如何编码线程 id,或如何从父会话继承
+- 核心拥有共享 `message` 工具宿主、提示词接线、会话 / 线程记录以及执行分发
+- 渠道插件拥有作用域动作发现、能力发现,以及任何渠道特定的 schema 片段
+- 渠道插件拥有提供商特定的会话对话语法,例如对话 id 如何编码线程 id,或如何从父会话继承
- 渠道插件通过其动作适配器执行最终动作
-对于渠道插件,SDK 接口是 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现调用允许插件将其可见动作、能力和 schema 贡献一并返回,从而避免这些部分彼此漂移。
+对于渠道插件,SDK 接口为 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现调用允许插件一起返回其可见动作、能力和 schema 扩展,从而避免这些部分发生漂移。
核心会将运行时作用域传入该发现步骤。重要字段包括:
@@ -151,87 +151,87 @@ OpenClaw 的插件系统有四层:
- `sessionKey`
- `sessionId`
- `agentId`
-- 受信任的入站 `requesterSenderId`
+- 可信入站 `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` 子路径,内置插件应直接从其扩展自有模块中导入本地运行时代码。
-这一边界同样适用于一般意义上的提供商命名 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)。
## 能力归属模型
-OpenClaw 将原生插件视为**公司**或**功能**的归属边界,而不是一堆互不相关集成的集合袋。
+OpenClaw 将一个原生插件视为某个**公司**或某项**功能**的归属边界,而不是一堆互不相关集成的集合。
这意味着:
-- 一个公司插件通常应该拥有该公司的所有 OpenClaw 对外接口
-- 一个功能插件通常应该拥有它所引入的完整功能接口
-- 各渠道应消费共享的核心能力,而不是临时重新实现提供商行为
+- 一个公司插件通常应拥有该公司的全部 OpenClaw 对外接口
+- 一个功能插件通常应拥有其引入的完整功能接口
+- 渠道应消费共享的核心能力,而不是临时重新实现提供商行为
示例:
-- 内置的 `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` 插件拥有 OpenAI 模型提供商行为,以及 OpenAI 语音 + 实时语音 + 媒体理解 + 图像生成行为
+- 内置 `elevenlabs` 插件拥有 ElevenLabs 语音行为
+- 内置 `microsoft` 插件拥有 Microsoft 语音行为
+- 内置 `google` 插件拥有 Google 模型提供商行为,以及 Google 媒体理解 + 图像生成 + Web 搜索行为
+- 内置 `firecrawl` 插件拥有 Firecrawl Web 抓取行为
+- 内置 `minimax`、`mistral`、`moonshot` 和 `zai` 插件拥有它们各自的媒体理解后端
+- 内置 `qwen` 插件拥有 Qwen 文本提供商行为,以及媒体理解和视频生成行为
+- `voice-call` 插件是一个功能插件:它拥有通话传输、工具、CLI、路由和 Twilio 媒体流桥接,但它会消费共享的语音能力以及实时转录和实时语音能力,而不是直接导入供应商插件
预期的最终状态是:
-- 即使 OpenAI 横跨文本模型、语音、图像以及未来的视频,它也应存在于同一个插件中
-- 其他厂商也可以对其自身的接口范围采用同样的方式
-- 各渠道不关心是哪一个厂商插件拥有该提供商;它们消费的是核心暴露的共享能力契约
+- 即使 OpenAI 横跨文本模型、语音、图像以及未来的视频能力,它也应存在于同一个插件中
+- 另一个供应商也可以用同样方式覆盖它自己的接口范围
+- 渠道并不关心哪个供应商插件拥有该提供商;它们消费的是核心暴露的共享能力契约
这是关键区别:
- **plugin** = 归属边界
- **capability** = 可由多个插件实现或消费的核心契约
-因此,如果 OpenClaw 新增了一个领域,比如视频,首先要问的不是“哪个提供商应该硬编码视频处理?”首先要问的是“核心视频能力契约是什么?”一旦这个契约存在,厂商插件就可以针对它进行注册,而渠道 / 功能插件也可以消费它。
+因此,如果 OpenClaw 新增一个领域,比如视频,第一个问题不应该是“哪个提供商应该硬编码视频处理?”第一个问题应该是“核心视频能力契约是什么?”一旦这个契约存在,供应商插件就可以针对它进行注册,而渠道 / 功能插件也可以消费它。
如果该能力尚不存在,通常正确的做法是:
1. 在核心中定义缺失的能力
2. 通过插件 API / 运行时以类型化方式暴露它
-3. 让渠道 / 功能对接该能力
-4. 让厂商插件注册实现
+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";
@@ -285,166 +285,173 @@ const plugin: OpenClawPluginDefinition = {
export default plugin;
```
-重要的不是这些辅助工具名称是否完全一致。重要的是这种形态:
+重要的不是确切的辅助函数名称,而是这种形态:
-- 一个插件拥有该厂商接口
+- 一个插件拥有该供应商的接口
- 核心仍然拥有能力契约
-- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是厂商代码
+- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是供应商代码
- 契约测试可以断言该插件确实注册了它声称拥有的能力
### 能力示例:视频理解
-OpenClaw 已经将图像 / 音频 / 视频理解视为一种共享能力。同样的归属模型也适用于这里:
+OpenClaw 已经将图像 / 音频 / 视频理解视为一个共享能力。相同的归属模型也适用于这里:
1. 核心定义 media-understanding 契约
-2. 厂商插件按需注册 `describeImage`、`transcribeAudio` 和 `describeVideo`
-3. 渠道和功能插件消费共享核心行为,而不是直接对接厂商代码
+2. 供应商插件按需注册 `describeImage`、`transcribeAudio` 和 `describeVideo`
+3. 渠道和功能插件消费共享的核心行为,而不是直接接入供应商代码
-这样可以避免把某个提供商的视频假设固化进核心。插件拥有厂商接口;核心拥有能力契约和回退行为。
+这样可以避免将某个提供商的视频假设硬编码进核心。插件拥有供应商接口;核心拥有能力契约和回退行为。
-视频生成也已经采用了相同顺序:核心拥有类型化能力契约和运行时辅助工具,而厂商插件则针对它注册 `api.registerVideoGenerationProvider(...)` 实现。
+视频生成也已经采用同样的顺序:核心拥有类型化能力契约和运行时辅助工具,而供应商插件针对它注册 `api.registerVideoGenerationProvider(...)` 实现。
-需要一个具体的发布检查清单吗?请参见[能力扩展手册](/zh-CN/plugins/architecture)。
+需要一份具体的发布检查清单吗?请参见
+[能力扩展手册](/zh-CN/plugins/architecture)。
## 契约与强制执行
-插件 API 接口有意采用类型化设计,并集中定义在 `OpenClawPluginApi` 中。该契约定义了受支持的注册点,以及插件可依赖的运行时辅助工具。
+插件 API 接口被有意设计为类型化,并集中定义在
+`OpenClawPluginApi` 中。这个契约定义了受支持的注册点,以及插件可以依赖的运行时辅助工具。
这很重要,因为:
-- 插件作者能获得一个稳定的内部标准
+- 插件作者可获得一个稳定的内部标准
- 核心可以拒绝重复归属,例如两个插件注册相同的 provider id
-- 启动过程可以为格式错误的注册暴露可操作的诊断信息
-- 契约测试可以强制执行内置插件归属并防止静默漂移
+- 启动时可以为格式错误的注册暴露可执行的诊断信息
+- 契约测试可以强制执行内置插件归属,并防止无声漂移
-强制执行有两层:
+有两层强制执行:
-1. **运行时注册强制执行**
- 插件加载时,插件注册表会校验注册内容。例如:重复的 provider id、重复的语音 provider id,以及格式错误的注册,都会生成插件诊断信息,而不是导致未定义行为。
-2. **契约测试**
- 在测试运行期间,内置插件会被记录到契约注册表中,这样 OpenClaw 就可以显式断言归属。当前这用于模型提供商、语音提供商、Web 搜索提供商以及内置注册归属。
+1. **运行时注册强制执行**
+ 插件注册表会在插件加载时验证注册内容。例如:重复的 provider id、重复的 speech provider id,以及格式错误的注册,都会产生插件诊断,而不是导致未定义行为。
+2. **契约测试**
+ 内置插件会在测试运行期间被捕获到契约注册表中,以便 OpenClaw 能显式断言归属。当前这用于模型提供商、语音提供商、Web 搜索提供商以及内置注册归属。
-实际效果是,OpenClaw 能够预先知道哪个插件拥有哪个接口。这使得核心和各渠道能够无缝组合,因为归属是声明式、类型化且可测试的,而不是隐式的。
+其实际效果是,OpenClaw 能够预先知道哪个插件拥有哪个接口。这使核心和渠道能够无缝组合,因为归属是声明式的、类型化的、可测试的,而不是隐式的。
-### 什么内容应该属于契约
+### 什么应该属于契约
-好的插件契约应当是:
+好的插件契约应该是:
- 类型化的
- 小而精的
- 能力特定的
-- 由核心拥有的
+- 由核心拥有
- 可被多个插件复用
-- 可被渠道 / 功能消费而无需了解厂商细节
+- 可被渠道 / 功能消费,而无需了解供应商细节
-不好的插件契约包括:
+不好的插件契约是:
-- 隐藏在核心中的厂商特定策略
+- 隐藏在核心中的供应商特定策略
- 绕过注册表的一次性插件逃生口
-- 渠道代码直接深入某个厂商实现
+- 渠道代码直接深入供应商实现
- 不属于 `OpenClawPluginApi` 或 `api.runtime` 的临时运行时对象
-如果拿不准,就提升抽象层级:先定义能力,再让插件接入它。
+如果不确定,就提升抽象层级:先定义能力,再让插件接入它。
## 执行模型
-原生 OpenClaw 插件与 Gateway 网关 **在同一进程内**运行。它们不是沙箱隔离的。已加载的原生插件与核心代码处于同一进程级信任边界。
+原生 OpenClaw 插件会与 Gateway 网关 **在同一进程内**运行。它们**没有**被沙箱隔离。一个已加载的原生插件与核心代码处于同样的进程级信任边界内。
-其影响是:
+这意味着:
- 原生插件可以注册工具、网络处理器、钩子和服务
-- 原生插件中的 bug 可能导致 gateway 崩溃或变得不稳定
-- 恶意原生插件等同于在 OpenClaw 进程内部执行任意代码
+- 原生插件中的 bug 可能导致 gateway 崩溃或失稳
+- 恶意原生插件等同于在 OpenClaw 进程内执行任意代码
兼容 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**,而不是来源出处。
-- 如果某个工作区插件与某个内置插件使用相同 id,那么当该工作区插件被启用 / 加入 allowlist 时,它会有意覆盖内置副本。
+- 与某个内置插件拥有相同 id 的 workspace 插件,在启用 / 加入 allowlist 后,会有意遮蔽内置副本。
- 这属于正常且有用的行为,适用于本地开发、补丁测试和热修复。
## 导出边界
-OpenClaw 导出的是能力,而不是实现层面的便利接口。
+OpenClaw 导出的是能力,而不是实现层面的便捷接口。
-应保持能力注册公开,同时收紧非契约辅助导出:
+应保持能力注册为公共接口,并收紧非契约辅助导出:
- 内置插件特定的辅助子路径
- 不打算作为公共 API 的运行时接线子路径
-- 厂商特定的便捷辅助工具
-- 属于实现细节的 setup / 新手引导辅助工具
+- 供应商特定的便捷辅助工具
+- 属于实现细节的设置 / 新手引导辅助工具
-出于兼容性和内置插件维护的考虑,某些内置插件辅助子路径仍保留在生成的 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 大致会执行以下步骤:
1. 发现候选插件根目录
-2. 读取原生或兼容 bundle 清单和包元数据
+2. 读取原生或兼容 bundle 的清单和包元数据
3. 拒绝不安全的候选项
4. 规范化插件配置(`plugins.enabled`、`allow`、`deny`、`entries`、`slots`、`load.paths`)
-5. 决定每个候选项是否启用
+5. 为每个候选项决定启用状态
6. 通过 jiti 加载已启用的原生模块
-7. 调用原生 `register(api)`(或 `activate(api)` —— 一个 legacy 别名)钩子,并将注册内容收集到插件注册表中
+7. 调用原生 `register(api)`(或 `activate(api)` —— 旧版别名)钩子,并将注册内容收集到插件注册表中
8. 将注册表暴露给命令 / 运行时接口
-`activate` 是 `register` 的 legacy 别名——加载器会解析当前存在的那个(`def.register ?? def.activate`),并在同一时机调用。所有内置插件都使用 `register`;新插件请优先使用 `register`。
+`activate` 是 `register` 的旧版别名——加载器会解析存在的那个(`def.register ?? def.activate`),并在同一时机调用它。所有内置插件都使用 `register`;新插件请优先使用 `register`。
-安全门槛发生在**运行时代码执行之前**。如果入口逃逸插件根目录、路径对所有人可写,或对于非内置插件而言路径归属看起来可疑,候选项就会被阻止。
+安全检查会发生在**运行时代码执行之前**。当入口逃逸出插件根目录、路径可被所有人写入,或对于非内置插件而言路径归属看起来可疑时,候选项会被阻止。
-### Manifest-first 行为
+### 清单优先行为
清单是控制平面的事实来源。OpenClaw 用它来:
- 标识插件
- 发现声明的渠道 / Skills / 配置 schema 或 bundle 能力
-- 校验 `plugins.entries..config`
+- 验证 `plugins.entries..config`
- 增强 Control UI 标签 / 占位符
- 显示安装 / 目录元数据
-- 在不加载插件运行时的前提下,保留轻量的激活和设置描述符
+- 在不加载插件运行时的情况下保留轻量级激活和设置描述符
-对于原生插件,运行时模块是数据平面部分。它会注册实际行为,如钩子、工具、命令或 provider 流程。
+对于原生插件,运行时模块是数据平面部分。它会注册实际行为,例如钩子、工具、命令或提供商流程。
-可选的清单 `activation` 和 `setup` 区块仍属于控制平面。它们是用于激活规划和 setup 发现的纯元数据描述符;它们不会替代运行时注册、`register(...)` 或 `setupEntry`。
-首批实际激活使用方现在会利用清单中的命令和提供商提示,在更广泛的注册表实体化之前先缩小插件加载范围:
+可选的清单 `activation` 和 `setup` 区块仍属于控制平面。它们是用于激活规划和设置发现的纯元数据描述符;它们不会替代运行时注册、`register(...)` 或 `setupEntry`。
+首批实时激活消费者现在会使用清单中的命令、渠道和提供商提示,在更广泛的注册表实体化之前先缩小插件加载范围:
- CLI 加载会缩小到拥有所请求主命令的插件
-- 显式 provider setup / 运行时解析会缩小到拥有所请求 provider id 的插件
+- 渠道设置 / 插件解析会缩小到拥有所请求 channel id 的插件
+- 显式提供商设置 / 运行时解析会缩小到拥有所请求 provider id 的插件
-现在,setup 发现会优先使用描述符自有 id,例如 `setup.providers` 和 `setup.cliBackends`,以便在回退到 `setup-api` 之前先缩小候选插件范围;`setup-api` 仅用于那些在 setup 时仍需要运行时钩子的插件。如果多个已发现插件声称拥有同一个规范化的 setup provider 或 CLI 后端 id,setup 查找会拒绝这个歧义归属,而不是依赖发现顺序。
+设置发现现在会优先使用描述符自有 id,例如 `setup.providers` 和 `setup.cliBackends`,以便在回退到 `setup-api` 之前先缩小候选插件范围;后者仅用于那些仍需要设置时运行时钩子的插件。如果多个已发现插件声称拥有相同的规范化 setup provider 或 CLI backend id,则设置查找会拒绝这个歧义归属,而不是依赖发现顺序。
### 加载器会缓存什么
OpenClaw 会保留一些短生命周期的进程内缓存,用于:
-- 设备发现结果
+- 发现结果
- 清单注册表数据
- 已加载的插件注册表
-这些缓存可减少突发启动和重复命令的开销。可以将它们安全地理解为短生命周期的性能缓存,而不是持久化存储。
+这些缓存可减少突发式启动和重复命令的开销。你可以将它们视为短期性能缓存,而不是持久化机制。
性能说明:
-- 设置 `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 钩子和类型化钩子
+- 旧版钩子和类型化钩子
- 渠道
- 提供商
- Gateway 网关 RPC 处理器
@@ -453,18 +460,18 @@ OpenClaw 会保留一些短生命周期的进程内缓存,用于:
- 后台服务
- 插件自有命令
-随后,核心功能会从该注册表读取内容,而不是直接与插件模块交互。这让加载保持单向:
+然后,核心功能会从该注册表读取信息,而不是直接与插件模块交互。这样可保持单向加载:
- 插件模块 -> 注册表注册
- 核心运行时 -> 注册表消费
-这种分离对可维护性非常重要。它意味着大多数核心接口只需要一个集成点:“读取注册表”,而不是“为每个插件模块做特例处理”。
+这种分离对于可维护性非常重要。它意味着大多数核心接口只需要一个集成点:“读取注册表”,而不是“为每个插件模块编写特例”。
-## 会话绑定回调
+## 对话绑定回调
-绑定会话的插件可以在审批结果确定后作出响应。
+绑定对话的插件可以在审批结果确定后作出响应。
-使用 `api.onConversationBindingResolved(...)` 可以在绑定请求被批准或拒绝后接收回调:
+使用 `api.onConversationBindingResolved(...)` 可以在绑定请求被批准或拒绝后收到回调:
```ts
export default {
@@ -484,87 +491,87 @@ export default {
};
```
-回调负载字段包括:
+回调负载字段:
- `status`:`"approved"` 或 `"denied"`
- `decision`:`"allow-once"`、`"allow-always"` 或 `"deny"`
-- `binding`:针对已批准请求的已解析绑定
-- `request`:原始请求摘要、分离提示、发送者 id 以及会话元数据
+- `binding`:对于已批准请求,为解析后的绑定
+- `request`:原始请求摘要、分离提示、发送者 id 和对话元数据
-该回调仅用于通知。它不会改变谁被允许绑定会话,并且会在核心审批处理完成后运行。
+该回调仅用于通知。它不会改变谁被允许绑定对话,并且会在核心审批处理完成后运行。
## 提供商运行时钩子
-提供商插件现在有两层:
+提供商插件现在分为两层:
-- 清单元数据:`providerAuthEnvVars` 用于在运行时加载前进行轻量的 provider 环境变量认证查找,`providerAuthAliases` 用于共享认证的 provider 变体,`channelEnvVars` 用于在运行时加载前进行轻量的渠道环境变量 / setup 查找,以及 `providerAuthChoices` 用于在运行时加载前提供轻量的新手引导 / 认证选项标签和 CLI flag 元数据
-- 配置时钩子:`catalog` / legacy `discovery` 以及 `applyConfigDefaults`
+- 清单元数据:`providerAuthEnvVars` 用于在运行时加载前进行轻量的提供商环境变量认证查找,`providerAuthAliases` 用于共享认证信息的提供商变体,`channelEnvVars` 用于在运行时加载前进行轻量的渠道环境变量 / 设置查找,此外还有 `providerAuthChoices`,用于在运行时加载前提供轻量的新手引导 / 认证选择标签和 CLI flag 元数据
+- 配置时钩子:`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`、`isBinaryThinking`、`supportsXHighThinking`、`resolveDefaultThinkingLevel`、`isModernModelRef`、`prepareRuntimeAuth`、`resolveUsageAuth`、`fetchUsageSnapshot`、`createEmbeddingProvider`、`buildReplayPolicy`、`sanitizeReplayHistory`、`validateReplayTurns`、`onModelSelected`
-OpenClaw 仍然拥有通用智能体循环、故障切换、转录处理和工具策略。这些钩子是在无需构建完整自定义推理传输层的前提下,用于扩展提供商特定行为的接口。
+OpenClaw 仍然拥有通用智能体循环、故障切换、转录处理和工具策略。这些钩子是在无需实现完整自定义推理传输的情况下,扩展提供商特定行为的接口。
-当某个 provider 具有基于环境变量的凭证,并且希望通用认证 / 状态 / 模型选择器路径在不加载插件运行时的情况下也能感知这些凭证时,请使用清单中的 `providerAuthEnvVars`。当某个 provider id 需要复用另一个 provider id 的环境变量、认证配置文件、基于配置的认证和 API 密钥新手引导选项时,请使用清单中的 `providerAuthAliases`。当新手引导 / 认证选项 CLI 接口需要在不加载 provider 运行时的前提下知道该 provider 的选项 id、分组标签以及简单的单 flag 认证接线时,请使用清单中的 `providerAuthChoices`。请将 provider 运行时中的 `envVars` 保留给面向运维人员的提示,例如新手引导标签或 OAuth client-id / client-secret setup 环境变量。
+当提供商具有基于环境变量的凭证,并且通用认证 / 状态 / 模型选择器路径需要在不加载插件运行时的前提下感知这些凭证时,请使用清单中的 `providerAuthEnvVars`。当一个 provider id 应复用另一个 provider id 的环境变量、认证配置文件、基于配置的认证和 API key 新手引导选项时,请使用清单中的 `providerAuthAliases`。当新手引导 / 认证选择 CLI 接口需要在不加载提供商运行时的情况下,了解该提供商的 choice id、分组标签和简单单 flag 认证接线时,请使用清单中的 `providerAuthChoices`。请将提供商运行时的 `envVars` 保留给面向操作员的提示信息,例如新手引导标签或 OAuth client-id / client-secret 设置变量。
-当某个渠道具有由环境变量驱动的认证或 setup,并且希望通用 shell 环境变量回退、配置 / 状态检查或 setup 提示在不加载渠道运行时的情况下也能感知这些信息时,请使用清单中的 `channelEnvVars`。
+当某个渠道具有基于环境变量驱动的认证或设置,并且通用 shell 环境变量回退、配置 / 状态检查或设置提示需要在不加载渠道运行时的前提下感知这些信息时,请使用清单中的 `channelEnvVars`。
-### 钩子顺序与用法
+### 钩子顺序和用法
-对于模型 / 提供商插件,OpenClaw 大致会按以下顺序调用这些钩子。
+对于模型 / 提供商插件,OpenClaw 会大致按以下顺序调用这些钩子。
“何时使用”这一列是快速决策指南。
| # | 钩子 | 作用 | 何时使用 |
| --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
-| 1 | `catalog` | 在生成 `models.json` 时将 provider 配置发布到 `models.providers` 中 | provider 拥有目录或 base URL 默认值 |
-| 2 | `applyConfigDefaults` | 在配置实体化期间应用 provider 自有的全局配置默认值 | 默认值依赖于认证模式、环境变量或 provider 模型族语义 |
-| -- | _(内置模型查找)_ | OpenClaw 会先尝试常规的注册表 / 目录路径 | _(不是插件钩子)_ |
-| 3 | `normalizeModelId` | 在查找前规范化 legacy 或预览版 model-id 别名 | provider 在规范模型解析之前拥有别名清理逻辑 |
-| 4 | `normalizeTransport` | 在通用模型组装之前规范化 provider 族的 `api` / `baseUrl` | provider 在同一传输族中为自定义 provider id 拥有传输清理逻辑 |
-| 5 | `normalizeConfig` | 在运行时 / provider 解析之前规范化 `models.providers.` | provider 需要将配置清理逻辑保留在插件中;内置的 Google 族辅助工具也会为受支持的 Google 配置项提供兜底 |
-| 6 | `applyNativeStreamingUsageCompat` | 对配置 provider 应用原生流式用量兼容性重写 | provider 需要基于端点的原生流式用量元数据修复 |
-| 7 | `resolveConfigApiKey` | 在加载运行时认证前,为配置 provider 解析环境变量标记认证 | provider 拥有自有的环境变量标记 API 密钥解析逻辑;`amazon-bedrock` 也在这里带有一个内置的 AWS 环境变量标记解析器 |
-| 8 | `resolveSyntheticAuth` | 在不持久化明文的前提下暴露本地 / 自托管或基于配置的认证 | provider 可以使用合成 / 本地凭证标记运行 |
-| 9 | `resolveExternalAuthProfiles` | 叠加 provider 自有的外部认证配置文件;`persistence` 的默认值是 `runtime-only`,适用于 CLI / 应用自有凭证 | provider 在不持久化复制的刷新令牌的情况下复用外部认证凭证 |
-| 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 | `isBinaryThinking` | 面向二元 thinking provider 的开 / 关推理切换 | provider 只暴露二元 thinking 开 / 关 |
-| 34 | `supportsXHighThinking` | 为选定模型提供 `xhigh` 推理支持 | provider 只希望部分模型支持 `xhigh` |
-| 35 | `resolveDefaultThinkingLevel` | 某个特定模型族的默认 `/think` 级别 | provider 拥有某个模型族的默认 `/think` 策略 |
-| 36 | `isModernModelRef` | 用于实时配置文件过滤和 smoke 选择的现代模型匹配器 | provider 拥有 live / smoke 首选模型匹配逻辑 |
-| 37 | `prepareRuntimeAuth` | 在推理前将已配置凭证交换为实际运行时令牌 / 密钥 | provider 需要令牌交换或短生命周期请求凭证 |
-| 38 | `resolveUsageAuth` | 为 `/usage` 及相关状态接口解析用量 / 计费凭证 | provider 需要自定义的用量 / 配额令牌解析,或不同的用量凭证 |
-| 39 | `fetchUsageSnapshot` | 在认证解析完成后获取并规范化 provider 特定的用量 / 配额快照 | provider 需要 provider 特定的用量端点或负载解析器 |
-| 40 | `createEmbeddingProvider` | 为 memory / 搜索构建 provider 自有的嵌入适配器 | memory 嵌入行为应归属于 provider 插件 |
-| 41 | `buildReplayPolicy` | 返回一个控制 provider 转录处理方式的重放策略 | provider 需要自定义转录策略(例如剥离 thinking 块) |
-| 42 | `sanitizeReplayHistory` | 在通用转录清理之后重写重放历史 | provider 需要超出共享压缩辅助工具范围的 provider 特定重放重写 |
-| 43 | `validateReplayTurns` | 在嵌入式 runner 运行前对重放轮次做最终校验或重塑 | provider 传输在通用清理之后需要更严格的轮次校验 |
-| 44 | `onModelSelected` | 在模型被选中后运行 provider 自有的副作用 | 当某个模型变为激活状态时,provider 需要遥测或 provider 自有状态 |
+| 1 | `catalog` | 在生成 `models.json` 期间,将提供商配置发布到 `models.providers` 中 | 当提供商拥有目录或 base URL 默认值时 |
+| 2 | `applyConfigDefaults` | 在配置实体化期间,应用提供商自有的全局配置默认值 | 当默认值依赖认证模式、环境变量或提供商模型家族语义时 |
+| -- | _(内置模型查找)_ | OpenClaw 会先尝试常规的注册表 / 目录路径 | _(这不是插件钩子)_ |
+| 3 | `normalizeModelId` | 在查找前规范化旧版或预览版 model-id 别名 | 当提供商需要在规范模型解析前拥有别名清理逻辑时 |
+| 4 | `normalizeTransport` | 在通用模型组装前,规范化提供商家族的 `api` / `baseUrl` | 当提供商需要为同一传输家族中的自定义 provider id 提供传输清理时 |
+| 5 | `normalizeConfig` | 在运行时 / 提供商解析前,规范化 `models.providers.` | 当提供商需要将配置清理逻辑保留在插件内部时;内置的 Google 家族辅助工具也会为受支持的 Google 配置条目提供兜底 |
+| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式用量兼容性改写 | 当提供商需要基于端点驱动的原生流式用量元数据修复时 |
+| 7 | `resolveConfigApiKey` | 在加载运行时认证前,为配置提供商解析环境变量标记认证 | 当提供商拥有自有的环境变量标记 API key 解析逻辑时;`amazon-bedrock` 在这里也有内置的 AWS 环境变量标记解析器 |
+| 8 | `resolveSyntheticAuth` | 在不持久化明文的情况下暴露本地 / 自托管或基于配置的认证 | 当提供商可以使用 synthetic / 本地凭证标记运行时 |
+| 9 | `resolveExternalAuthProfiles` | 叠加提供商自有的外部认证配置文件;CLI / 应用自有凭证的默认 `persistence` 为 `runtime-only` | 当提供商需要复用外部认证凭证,而不持久化复制的刷新令牌时 |
+| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的 synthetic 配置文件占位符降级到环境变量 / 基于配置的认证之后 | 当提供商会存储 synthetic 占位配置文件,但这些占位符不应优先命中时 |
+| 11 | `resolveDynamicModel` | 为尚未进入本地注册表的提供商自有模型 id 提供同步回退 | 当提供商接受任意上游模型 id 时 |
+| 12 | `prepareDynamicModel` | 执行异步预热,然后再次运行 `resolveDynamicModel` | 当提供商在解析未知 id 之前需要网络元数据时 |
+| 13 | `normalizeResolvedModel` | 在嵌入式 runner 使用解析后的模型之前做最终改写 | 当提供商需要进行传输改写,但仍然使用核心传输时 |
+| 14 | `contributeResolvedModelCompat` | 为运行在另一种兼容传输之上的供应商模型提供兼容标志 | 当提供商能在不接管 provider 的情况下识别自己在代理传输上的模型时 |
+| 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` 字符串 | 当提供商存储了额外认证元数据,并需要自定义运行时 token 形态时 |
+| 25 | `refreshOAuth` | 为自定义刷新端点或刷新失败策略覆盖 OAuth 刷新逻辑 | 当提供商不适配共享的 `pi-ai` 刷新器时 |
+| 26 | `buildAuthDoctorHint` | 当 OAuth 刷新失败时追加修复提示 | 当提供商需要在刷新失败后提供自有的认证修复指导时 |
+| 27 | `matchesContextOverflowError` | 提供商自有的上下文窗口溢出匹配器 | 当提供商存在通用启发式无法识别的原始溢出错误时 |
+| 28 | `classifyFailoverReason` | 提供商自有的故障切换原因分类 | 当提供商可以将原始 API / 传输错误映射为限流 / 过载等类别时 |
+| 29 | `isCacheTtlEligible` | 面向代理 / 回传提供商的提示词缓存策略 | 当提供商需要代理特定的缓存 TTL 门控时 |
+| 30 | `buildMissingAuthMessage` | 替换通用的缺失认证恢复消息 | 当提供商需要提供商特定的缺失认证恢复提示时 |
+| 31 | `suppressBuiltInModel` | 过时上游模型抑制,并可选提供面向用户的错误提示 | 当提供商需要隐藏过时的上游条目,或用供应商提示替换它们时 |
+| 32 | `augmentModelCatalog` | 在发现后追加 synthetic / 最终目录条目 | 当提供商需要在 `models list` 和选择器中加入 synthetic 的前向兼容条目时 |
+| 33 | `isBinaryThinking` | 面向 binary-thinking 提供商的开 / 关推理切换 | 当提供商只支持二元推理开 / 关时 |
+| 34 | `supportsXHighThinking` | 为选定模型提供 `xhigh` 推理支持 | 当提供商只希望在部分模型上启用 `xhigh` 时 |
+| 35 | `resolveDefaultThinkingLevel` | 为特定模型家族解析默认 `/think` 级别 | 当提供商拥有某个模型家族的默认 `/think` 策略时 |
+| 36 | `isModernModelRef` | 用于实时配置文件筛选和 smoke 选择的现代模型匹配器 | 当提供商拥有实时 / smoke 首选模型匹配逻辑时 |
+| 37 | `prepareRuntimeAuth` | 在推理前,将已配置凭证交换为真实运行时 token / key | 当提供商需要 token 交换或短生命周期请求凭证时 |
+| 38 | `resolveUsageAuth` | 为 `/usage` 及相关状态接口解析用量 / 计费凭证 | 当提供商需要自定义用量 / 配额 token 解析,或需要不同的用量凭证时 |
+| 39 | `fetchUsageSnapshot` | 在认证解析后获取并规范化提供商特定的用量 / 配额快照 | 当提供商需要提供商特定的用量端点或负载解析器时 |
+| 40 | `createEmbeddingProvider` | 为 memory / search 构建提供商自有的嵌入适配器 | memory 嵌入行为应归属于提供商插件 |
+| 41 | `buildReplayPolicy` | 返回一个控制该提供商转录处理方式的重放策略 | 当提供商需要自定义转录策略时(例如剥离 thinking block) |
+| 42 | `sanitizeReplayHistory` | 在通用转录清理之后重写重放历史 | 当提供商需要在共享压缩辅助工具之外,再做提供商特定的重放改写时 |
+| 43 | `validateReplayTurns` | 在嵌入式 runner 之前,对重放轮次做最终验证或重塑 | 当提供商传输在通用净化之后仍需要更严格的轮次验证时 |
+| 44 | `onModelSelected` | 在模型被选中后运行提供商自有的副作用 | 当提供商需要在模型激活时记录遥测或维护提供商自有状态时 |
-`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配到的 provider 插件,然后继续回退到其他具备该钩子能力的 provider 插件,直到某个插件实际修改了 model id 或 transport / config。这样可以让别名 / 兼容 provider shim 保持可用,而无需调用方知道是哪一个内置插件拥有该重写逻辑。如果没有任何 provider 钩子去重写某个受支持的 Google 族配置项,那么内置的 Google 配置规范化器仍会应用该兼容性清理。
+`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查已匹配的提供商插件,然后继续回退到其他具备相关钩子能力的提供商插件,直到某个插件实际修改了模型 id 或 transport / config。这样可以让别名 / 兼容型提供商 shim 正常工作,而无需调用方知道哪个内置插件拥有该改写逻辑。如果没有任何提供商钩子改写受支持的 Google 家族配置项,那么内置的 Google 配置规范化器仍会应用这类兼容性清理。
-如果 provider 需要完全自定义的线协议或自定义请求执行器,那属于另一类扩展。这些钩子适用于仍运行在 OpenClaw 正常推理循环上的 provider 行为。
+如果提供商需要完全自定义的线协议或自定义请求执行器,那就是另一类扩展。这些钩子适用于仍运行在 OpenClaw 正常推理循环上的提供商行为。
-### Provider 示例
+### 提供商示例
```ts
api.registerProvider({
@@ -620,29 +627,29 @@ api.registerProvider({
### 内置示例
-- Anthropic 使用 `resolveDynamicModel`、`capabilities`、`buildAuthDoctorHint`、`resolveUsageAuth`、`fetchUsageSnapshot`、`isCacheTtlEligible`、`resolveDefaultThinkingLevel`、`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`、`supportsXHighThinking` 和 `isModernModelRef`,因为它拥有 GPT-5.4 前向兼容、直接 OpenAI 的 `openai-completions` -> `openai-responses` 规范化、面向 Codex 的认证提示、Spark 抑制、合成的 OpenAI 列表条目,以及 GPT-5 thinking / live-model 策略;`openai-responses-defaults` 流式家族则拥有共享的原生 OpenAI Responses 包装器,用于 attribution 头、`/fast` / `serviceTier`、文本冗长度、原生 Codex Web 搜索、reasoning 兼容负载整形以及 Responses 上下文管理。
-- OpenRouter 使用 `catalog` 以及 `resolveDynamicModel` 和 `prepareDynamicModel`,因为该 provider 是透传型的,可能会在 OpenClaw 的静态目录更新之前暴露新的 model id;它还使用 `capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,以便将 provider 特定请求头、路由元数据、reasoning 补丁和提示词缓存策略保留在核心之外。它的重放策略来自 `passthrough-gemini` 家族,而 `openrouter-thinking` 流式家族则拥有代理 reasoning 注入以及不受支持模型 / `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 传输之上,但拥有其自己的 transport / 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` 和 `resolveDefaultThinkingLevel`,因为它拥有面向 Anthropic-on-Bedrock 流量的 Bedrock 特定 throttle / not-ready / context-overflow 错误分类;它的重放策略仍共享同一个仅限 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` 和 `wrapStreamFn`,因为它仍使用共享的 OpenAI 传输,但需要 provider 自有的 thinking 负载规范化;`moonshot-thinking` 流式家族会把配置和 `/think` 状态映射到其原生的二元 thinking 负载上。
-- Kilocode 使用 `catalog`、`capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,因为它需要 provider 自有请求头、reasoning 负载规范化、Gemini 转录提示以及 Anthropic 缓存 TTL 门控;`kilocode-thinking` 流式家族则将 Kilo thinking 注入保留在共享代理流式路径上,同时跳过 `kilo/auto` 和其他不支持显式推理负载的代理 model id。
-- Z.AI 使用 `resolveDynamicModel`、`prepareExtraParams`、`wrapStreamFn`、`isCacheTtlEligible`、`isBinaryThinking`、`isModernModelRef`、`resolveUsageAuth` 和 `fetchUsageSnapshot`,因为它拥有 GLM-5 回退、`tool_stream` 默认值、二元 thinking 用户体验、现代模型匹配,以及用量认证和配额获取;`tool-stream-default-on` 流式家族则将默认开启的 `tool_stream` 包装器保留在逐 provider 手写胶水代码之外。
-- xAI 使用 `normalizeResolvedModel`、`normalizeTransport`、`contributeResolvedModelCompat`、`prepareExtraParams`、`wrapStreamFn`、`resolveSyntheticAuth`、`resolveDynamicModel` 和 `isModernModelRef`,因为它拥有原生 xAI Responses 传输规范化、Grok fast-mode 别名重写、默认 `tool_stream`、strict-tool / reasoning 负载清理、对插件自有工具的回退认证复用、前向兼容的 Grok 模型解析,以及 provider 自有兼容补丁,例如 xAI 工具 schema 配置文件、不受支持的 schema 关键字、原生 `web_search` 和 HTML 实体工具调用参数解码。
-- Mistral、OpenCode Zen 和 OpenCode Go 只使用 `capabilities`,以便将转录 / 工具特性保留在核心之外。
-- 仅目录型内置 provider,例如 `byteplus`、`cloudflare-ai-gateway`、`huggingface`、`kimi-coding`、`nvidia`、`qianfan`、`synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine`,只使用 `catalog`。
-- Qwen 使用 `catalog` 作为其文本 provider,同时为其多模态接口注册共享的 media-understanding 和 video-generation。
-- MiniMax 和 Xiaomi 使用 `catalog` 加上用量钩子,因为尽管推理仍通过共享传输运行,但它们的 `/usage` 行为归插件所有。
+- Anthropic 使用 `resolveDynamicModel`、`capabilities`、`buildAuthDoctorHint`、`resolveUsageAuth`、`fetchUsageSnapshot`、`isCacheTtlEligible`、`resolveDefaultThinkingLevel`、`applyConfigDefaults`、`isModernModelRef` 和 `wrapStreamFn`,因为它拥有 Claude 4.6 前向兼容、提供商家族提示、认证修复指引、用量端点集成、提示词缓存资格、支持认证感知的配置默认值、Claude 默认 / 自适应思考策略,以及面向 beta 头、`/fast` / `serviceTier` 和 `context1m` 的 Anthropic 特定流式整形逻辑。
+- Anthropic 的 Claude 特定流式辅助工具目前仍保留在该内置插件自己的公共 `api.ts` / `contract-api.ts` 接缝中。该包接口导出 `wrapAnthropicProviderStream`、`resolveAnthropicBetas`、`resolveAnthropicFastMode`、`resolveAnthropicServiceTier` 以及更底层的 Anthropic 包装器构建器,而不是为了某个提供商的 beta 头规则去扩展通用 SDK。
+- OpenAI 使用 `resolveDynamicModel`、`normalizeResolvedModel` 和 `capabilities`,以及 `buildMissingAuthMessage`、`suppressBuiltInModel`、`augmentModelCatalog`、`supportsXHighThinking` 和 `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 搜索、reasoning 兼容负载整形以及 Responses 上下文管理。
+- OpenRouter 使用 `catalog` 以及 `resolveDynamicModel` 和 `prepareDynamicModel`,因为该提供商是透传型的,并且可能在 OpenClaw 的静态目录更新前就暴露新模型 id;它还使用 `capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,以避免将提供商特定的请求头、路由元数据、reasoning 补丁和提示词缓存策略放入核心。它的重放策略来自 `passthrough-gemini` 家族,而 `openrouter-thinking` 流家族则拥有代理推理注入以及不受支持模型 / `auto` 跳过逻辑。
+- GitHub Copilot 使用 `catalog`、`auth`、`resolveDynamicModel` 和 `capabilities`,以及 `prepareRuntimeAuth` 和 `fetchUsageSnapshot`,因为它需要提供商自有的设备登录、模型回退行为、Claude 转录差异、GitHub token -> Copilot token 交换,以及提供商自有的用量端点。
+- OpenAI Codex 使用 `catalog`、`resolveDynamicModel`、`normalizeResolvedModel`、`refreshOAuth` 和 `augmentModelCatalog`,以及 `prepareExtraParams`、`resolveUsageAuth` 和 `fetchUsageSnapshot`,因为它虽然仍运行在核心 OpenAI 传输之上,但拥有自己的 transport / 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 重放验证、bootstrap 重放净化、带标签的推理输出模式以及现代模型匹配,而 `google-thinking` 流家族拥有 Gemini thinking 负载规范化;Gemini CLI OAuth 还使用 `formatApiKey`、`resolveUsageAuth` 和 `fetchUsageSnapshot` 来处理 token 格式化、token 解析和配额端点接线。
+- Anthropic Vertex 通过 `anthropic-by-model` 重放家族使用 `buildReplayPolicy`,从而让 Claude 特定的重放清理只限定在 Claude id 上,而不是作用于每个 `anthropic-messages` 传输。
+- Amazon Bedrock 使用 `buildReplayPolicy`、`matchesContextOverflowError`、`classifyFailoverReason` 和 `resolveDefaultThinkingLevel`,因为它拥有用于 Anthropic-on-Bedrock 流量的 Bedrock 特定限流 / 未就绪 / 上下文溢出错误分类;它的重放策略仍共享同一个仅限 Claude 的 `anthropic-by-model` 防护。
+- OpenRouter、Kilocode、Opencode 和 Opencode Go 通过 `passthrough-gemini` 重放家族使用 `buildReplayPolicy`,因为它们通过 OpenAI 兼容传输代理 Gemini 模型,并且需要 Gemini thought-signature 净化,而不需要原生 Gemini 重放验证或 bootstrap 改写。
+- MiniMax 通过 `hybrid-anthropic-openai` 重放家族使用 `buildReplayPolicy`,因为一个提供商同时拥有 Anthropic-message 和 OpenAI 兼容语义;它会在 Anthropic 一侧保持仅限 Claude 的 thinking block 丢弃,同时将 reasoning 输出模式改回原生,而 `minimax-fast-mode` 流家族则在共享流路径上拥有 fast-mode 模型改写逻辑。
+- Moonshot 使用 `catalog` 和 `wrapStreamFn`,因为它仍使用共享的 OpenAI 传输,但需要提供商自有的 thinking 负载规范化;`moonshot-thinking` 流家族将配置和 `/think` 状态映射到其原生的二元 thinking 负载上。
+- Kilocode 使用 `catalog`、`capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,因为它需要提供商自有的请求头、reasoning 负载规范化、Gemini 转录提示和 Anthropic 缓存 TTL 门控;`kilocode-thinking` 流家族在共享代理流路径上保留 Kilo thinking 注入,同时跳过 `kilo/auto` 和其他不支持显式 reasoning 负载的代理模型 id。
+- Z.AI 使用 `resolveDynamicModel`、`prepareExtraParams`、`wrapStreamFn`、`isCacheTtlEligible`、`isBinaryThinking`、`isModernModelRef`、`resolveUsageAuth` 和 `fetchUsageSnapshot`,因为它拥有 GLM-5 回退、`tool_stream` 默认值、二元 thinking 用户体验、现代模型匹配,以及用量认证和配额拉取;`tool-stream-default-on` 流家族则将默认开启的 `tool_stream` 包装器从按提供商手写胶水逻辑中抽离出来。
+- xAI 使用 `normalizeResolvedModel`、`normalizeTransport`、`contributeResolvedModelCompat`、`prepareExtraParams`、`wrapStreamFn`、`resolveSyntheticAuth`、`resolveDynamicModel` 和 `isModernModelRef`,因为它拥有原生 xAI Responses 传输规范化、Grok fast-mode 别名改写、默认 `tool_stream`、严格工具 / reasoning 负载清理、面向插件自有工具的回退认证复用、前向兼容的 Grok 模型解析,以及提供商自有的兼容性补丁,例如 xAI 工具 schema 配置文件、不受支持的 schema 关键字、原生 `web_search` 和 HTML 实体工具调用参数解码。
+- Mistral、OpenCode Zen 和 OpenCode Go 仅使用 `capabilities`,以将转录 / 工具差异保留在核心之外。
+- 仅目录型的内置提供商,如 `byteplus`、`cloudflare-ai-gateway`、`huggingface`、`kimi-coding`、`nvidia`、`qianfan`、`synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine`,仅使用 `catalog`。
+- Qwen 为其文本提供商使用 `catalog`,同时为其多模态接口注册共享的 media-understanding 和 video-generation。
+- MiniMax 和 Xiaomi 使用 `catalog` 加上用量钩子,因为即使推理仍通过共享传输运行,它们的 `/usage` 行为仍归属于插件。
## 运行时辅助工具
-插件可以通过 `api.runtime` 访问选定的核心辅助工具。以 TTS 为例:
+插件可通过 `api.runtime` 访问部分核心辅助工具。以 TTS 为例:
```ts
const clip = await api.runtime.tts.textToSpeech({
@@ -663,14 +670,14 @@ const voices = await api.runtime.tts.listVoices({
说明:
-- `textToSpeech` 返回适用于文件 / 语音便笺接口的常规核心 TTS 输出负载。
-- 使用核心 `messages.tts` 配置和 provider 选择。
-- 返回 PCM 音频缓冲区 + 采样率。插件必须为各 provider 重新采样 / 编码。
-- `listVoices` 对每个 provider 来说都是可选的。可将其用于厂商自有的语音选择器或 setup 流程。
-- 语音列表可以包含更丰富的元数据,例如区域设置、性别和个性标签,以供感知 provider 的选择器使用。
-- 目前 OpenAI 和 ElevenLabs 支持电话场景。Microsoft 不支持。
+- `textToSpeech` 返回用于文件 / 语音消息界面的标准核心 TTS 输出负载。
+- 使用核心 `messages.tts` 配置和提供商选择逻辑。
+- 返回 PCM 音频缓冲区 + 采样率。插件必须为各自提供商完成重采样 / 编码。
+- `listVoices` 对每个提供商来说都是可选的。可用于供应商自有的语音选择器或设置流程。
+- 语音列表可包含更丰富的元数据,例如语言区域、性别和人格标签,以支持提供商感知型选择器。
+- 当前 OpenAI 和 ElevenLabs 支持电话场景。Microsoft 不支持。
-插件也可以通过 `api.registerSpeechProvider(...)` 注册语音 provider。
+插件也可以通过 `api.registerSpeechProvider(...)` 注册语音提供商。
```ts
api.registerSpeechProvider({
@@ -690,12 +697,12 @@ api.registerSpeechProvider({
说明:
-- 将 TTS 策略、回退和回复交付保留在核心中。
-- 使用语音 provider 处理厂商自有的合成行为。
-- legacy Microsoft `edge` 输入会被规范化为 `microsoft` provider id。
-- 首选的归属模型是面向公司的:随着 OpenClaw 增加这些能力契约,一个厂商插件可以同时拥有文本、语音、图像和未来的媒体 provider。
+- 将 TTS 策略、回退和回复投递保留在核心中。
+- 使用语音提供商来承载供应商自有的合成行为。
+- 旧版 Microsoft `edge` 输入会被规范化为 `microsoft` provider id。
+- 推荐的归属模型是面向公司的:随着 OpenClaw 增加这些能力契约,一个供应商插件可以同时拥有文本、语音、图像和未来的媒体提供商。
-对于图像 / 音频 / 视频理解,插件应注册一个类型化的 media-understanding provider,而不是通用的键 / 值包:
+对于图像 / 音频 / 视频理解,插件应注册一个类型化的 media-understanding 提供商,而不是一个通用的键 / 值包:
```ts
api.registerMediaUnderstandingProvider({
@@ -710,11 +717,11 @@ api.registerMediaUnderstandingProvider({
说明:
- 将编排、回退、配置和渠道接线保留在核心中。
-- 将厂商行为保留在 provider 插件中。
-- 增量扩展应保持类型化:新增可选方法、新增可选结果字段、新增可选能力。
-- 视频生成已经遵循同样的模式:
+- 将供应商行为保留在提供商插件中。
+- 增量扩展应保持类型化:新的可选方法、新的可选结果字段、新的可选能力。
+- 视频生成已经遵循相同模式:
- 核心拥有能力契约和运行时辅助工具
- - 厂商插件注册 `api.registerVideoGenerationProvider(...)`
+ - 供应商插件注册 `api.registerVideoGenerationProvider(...)`
- 功能 / 渠道插件消费 `api.runtime.videoGeneration.*`
对于 media-understanding 运行时辅助工具,插件可以调用:
@@ -732,7 +739,7 @@ const video = await api.runtime.mediaUnderstanding.describeVideoFile({
});
```
-对于音频转录,插件既可以使用 media-understanding 运行时,也可以使用较旧的 STT 别名:
+对于音频转录,插件既可以使用 media-understanding 运行时,也可以使用旧版 STT 别名:
```ts
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({
@@ -746,11 +753,11 @@ const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({
说明:
- `api.runtime.mediaUnderstanding.*` 是图像 / 音频 / 视频理解的首选共享接口。
-- 使用核心 media-understanding 音频配置(`tools.media.audio`)和 provider 回退顺序。
-- 当没有生成转录输出时(例如输入被跳过 / 不受支持),返回 `{ text: undefined }`。
+- 使用核心 media-understanding 音频配置(`tools.media.audio`)和提供商回退顺序。
+- 当未产生转录输出时返回 `{ text: undefined }`(例如输入被跳过 / 不受支持时)。
- `api.runtime.stt.transcribeAudioFile(...)` 仍保留为兼容性别名。
-插件还可以通过 `api.runtime.subagent` 启动后台子智能体运行:
+插件也可以通过 `api.runtime.subagent` 启动后台子智能体运行:
```ts
const result = await api.runtime.subagent.run({
@@ -764,13 +771,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({
@@ -786,13 +793,14 @@ const result = await api.runtime.webSearch.search({
});
```
-插件也可以通过 `api.registerWebSearchProvider(...)` 注册 Web 搜索 provider。
+插件也可以通过
+`api.registerWebSearchProvider(...)` 注册 Web 搜索提供商。
说明:
-- 将 provider 选择、凭证解析和共享请求语义保留在核心中。
-- 使用 Web 搜索 provider 处理厂商特定的搜索传输。
-- `api.runtime.webSearch.*` 是需要搜索行为但不想依赖智能体工具包装器的功能 / 渠道插件的首选共享接口。
+- 将提供商选择、凭证解析和共享请求语义保留在核心中。
+- 使用 Web 搜索提供商来承载供应商特定的搜索传输。
+- `api.runtime.webSearch.*` 是功能 / 渠道插件在需要搜索行为但不依赖智能体工具包装器时的首选共享接口。
### `api.runtime.imageGeneration`
@@ -807,12 +815,12 @@ const providers = api.runtime.imageGeneration.listProviders({
});
```
-- `generate(...)`:使用已配置的图像生成 provider 链生成图像。
-- `listProviders(...)`:列出可用的图像生成 provider 及其能力。
+- `generate(...)`:使用已配置的图像生成提供商链生成图像。
+- `listProviders(...)`:列出可用的图像生成提供商及其能力。
## Gateway 网关 HTTP 路由
-插件可以通过 `api.registerHttpRoute(...)` 暴露 HTTP 端点。
+插件可以使用 `api.registerHttpRoute(...)` 暴露 HTTP 端点。
```ts
api.registerHttpRoute({
@@ -830,100 +838,126 @@ api.registerHttpRoute({
路由字段:
- `path`:Gateway 网关 HTTP 服务器下的路由路径。
-- `auth`:必填。使用 `"gateway"` 以要求普通 Gateway 网关认证,或使用 `"plugin"` 处理插件管理的认证 / webhook 校验。
-- `match`:可选。`"exact"`(默认)或 `"prefix"`。
-- `replaceExisting`:可选。允许同一插件替换它自己已有的路由注册。
+- `auth`:必填。使用 `"gateway"` 表示要求常规 Gateway 网关认证,或使用 `"plugin"` 表示由插件自行管理认证 / webhook 校验。
+- `match`:可选。可为 `"exact"`(默认)或 `"prefix"`。
+- `replaceExisting`:可选。允许同一插件替换自身已有的路由注册。
- `handler`:当路由处理了请求时返回 `true`。
说明:
- `api.registerHttpHandler(...)` 已被移除,并会导致插件加载错误。请改用 `api.registerHttpRoute(...)`。
- 插件路由必须显式声明 `auth`。
-- 完全相同的 `path + match` 冲突会被拒绝,除非设置了 `replaceExisting: true`,并且一个插件不能替换另一个插件的路由。
-- 不同 `auth` 级别的重叠路由会被拒绝。请仅在相同认证级别内保留 `exact` / `prefix` 的回退链。
-- `auth: "plugin"` 路由**不会**自动收到运维人员运行时作用域。它们用于插件管理的 webhook / 签名校验,而不是特权 Gateway 网关辅助调用。
-- `auth: "gateway"` 路由会在 Gateway 网关请求运行时作用域内运行,但该作用域有意保持保守:
- - 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes`
- - 带受信身份的 HTTP 模式(例如 `trusted-proxy` 或私有入口上的 `gateway.auth.mode = "none"`)仅会在请求头显式存在时才认可 `x-openclaw-scopes`
- - 如果这些带身份的插件路由请求中缺少 `x-openclaw-scopes`,运行时作用域会回退为 `operator.write`
-- 实践规则:不要假设经过 gateway 认证的插件路由天然就是管理接口。如果你的路由需要仅管理员可用的行为,请要求使用带身份的认证模式,并文档化显式的 `x-openclaw-scopes` 请求头契约。
+- 精确的 `path + match` 冲突会被拒绝,除非设置 `replaceExisting: true`,且一个插件不能替换另一个插件的路由。
+- 具有不同 `auth` 级别的重叠路由会被拒绝。请仅在相同认证级别内使用 `exact` / `prefix` 回退链。
+- `auth: "plugin"` 路由**不会**自动接收操作员运行时作用域。它们用于插件自主管理的 webhook / 签名校验,而不是特权 Gateway 网关辅助调用。
+- `auth: "gateway"` 路由会在 Gateway 网关请求运行时作用域内运行,但该作用域被有意设置得较为保守:
+ - 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由的运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes`
+ - 具备可信身份的 HTTP 模式(例如 `trusted-proxy`,或私有入口上的 `gateway.auth.mode = "none"`)仅在显式存在该头时才会接受 `x-openclaw-scopes`
+ - 如果这些具备身份信息的插件路由请求中缺少 `x-openclaw-scopes`,则运行时作用域会回退为 `operator.write`
+- 实践规则:不要假设一个经过 gateway 认证的插件路由天然就是管理接口。如果你的路由需要仅管理员可用的行为,请要求具备身份信息的认证模式,并记录明确的 `x-openclaw-scopes` 头契约。
## 插件 SDK 导入路径
-在编写插件时,请使用 SDK 子路径,而不是单体式的 `openclaw/plugin-sdk` 导入:
+在编写插件时,应使用 SDK 子路径,而不是整体式的 `openclaw/plugin-sdk` 导入:
- `openclaw/plugin-sdk/plugin-entry` 用于插件注册原语。
-- `openclaw/plugin-sdk/core` 用于通用共享的面向插件契约。
+- `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`,用于共享的 setup / 认证 / 回复 / webhook 接线。
- `channel-inbound` 是 debounce、mention 匹配、入站 mention-policy 辅助工具、信封格式化和入站信封上下文辅助工具的共享归属位置。
- `channel-setup` 是狭义的可选安装 setup 接缝。
- `setup-runtime` 是 `setupEntry` / 延迟启动使用的运行时安全 setup 接口,包括可安全导入的 setup patch 适配器。
- `setup-adapter-runtime` 是感知环境变量的账户 setup 适配器接缝。
- `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/*`。
+- 稳定的渠道原语,如 `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` 已被弃用,仅作为旧版插件的兼容性 shim 保留。新代码应改为导入更窄的通用原语,仓库代码也不应新增对该 shim 的导入。
+- 内置扩展内部实现仍然是私有的。外部插件应仅使用 `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` 是 setup 插件入口。
-- 当前内置 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 上。
+ `/setup-entry.js` 是设置插件入口。
+- 当前内置提供商示例:
+ - Anthropic 使用 `api.js` / `contract-api.js` 暴露 Claude 流式辅助工具,例如 `wrapAnthropicProviderStream`、beta 头辅助工具以及 `service_tier` 解析。
+ - OpenAI 使用 `api.js` 暴露提供商构建器、默认模型辅助工具和实时提供商构建器。
+ - OpenRouter 使用 `api.js` 暴露其提供商构建器以及新手引导 / 配置辅助工具,而 `register.runtime.js` 仍可为仓库本地用途重新导出通用 `plugin-sdk/provider-stream` 辅助工具。
+- 通过 facade 加载的公共入口点在存在活动运行时配置快照时优先使用该快照;当 OpenClaw 尚未提供运行时快照时,则回退到磁盘上已解析的配置文件。
+- 通用共享原语仍然是首选的公共插件 SDK 契约。目前仍存在一小组保留的、带有内置渠道品牌的辅助接缝,用于兼容性。应将它们视为内置维护 / 兼容性接缝,而不是新的第三方导入目标;新的跨渠道契约仍应落在通用 `plugin-sdk/*` 子路径或插件本地 `api.js` / `runtime-api.js` barrel 上。
兼容性说明:
-- 新代码应避免使用根 `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` 这样的能力特定子路径之所以存在,是因为当前内置 / 原生插件确实在使用它们。但这并不自动意味着其中每个导出的辅助工具都是长期冻结的外部契约。
+- 新代码应避免使用根级 `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`。
+ message 动作 gate 和 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` 这样的能力特定子路径之所以存在,是因为当前内置 / 原生插件正在使用它们。但它们的存在本身并不意味着其中每个已导出的辅助工具都是长期冻结的外部契约。
-## Message 工具 schema
+## message 工具 schema
-插件应拥有渠道特定的 `describeMessageTool(...)` schema 贡献。请将 provider 特定字段保留在插件中,而不是放进共享核心中。
+插件应拥有渠道特定的 `describeMessageTool(...)` schema 扩展。请将提供商特定字段保留在插件中,而不是放入共享核心。
-对于共享的可移植 schema 片段,请复用通过 `openclaw/plugin-sdk/channel-actions` 导出的通用辅助工具:
+对于共享的可移植 schema 片段,请复用通过
+`openclaw/plugin-sdk/channel-actions` 导出的通用辅助工具:
-- `createMessageToolButtonsSchema()` 用于按钮网格式负载
+- `createMessageToolButtonsSchema()` 用于按钮网格风格的负载
- `createMessageToolCardSchema()` 用于结构化卡片负载
-如果某个 schema 形状只对某个 provider 有意义,请在该插件自己的源码中定义它,而不是将其提升到共享 SDK 中。
+如果某种 schema 形态只对单个提供商有意义,请在该插件自己的源码中定义它,而不是将其提升到共享 SDK 中。
## 渠道目标解析
-渠道插件应拥有渠道特定的目标语义。请保持共享 outbound 宿主的通用性,并使用消息适配器接口来承载 provider 规则:
+渠道插件应拥有渠道特定的目标语义。请保持共享出站宿主的通用性,并通过消息适配器接口处理提供商规则:
-- `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(...)` 在目标解析完成后,负责构建提供商特定的会话路由
推荐拆分方式:
-- 对于应在搜索 peers / groups 之前发生的类别判断,请使用 `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、线程 id、JID、handle 和 room id 这类提供商原生 id 保留在 `target` 值或提供商特定参数中,而不是放在通用 SDK 字段里
## 基于配置的目录
-对于从配置派生目录条目的插件,应将该逻辑保留在插件中,并复用 `openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。
+如果插件从配置派生目录条目,应将这部分逻辑保留在插件中,并复用
+`openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。
当某个渠道需要基于配置的 peers / groups 时,请使用这种方式,例如:
-- 基于 allowlist 的私信 peers
-- 已配置的 channel / group 映射
+- 由 allowlist 驱动的私信 peers
+- 已配置的渠道 / 群组映射
- 账户作用域内的静态目录回退
`directory-runtime` 中的共享辅助工具只处理通用操作:
@@ -935,57 +969,62 @@ api.registerHttpRoute({
渠道特定的账户检查和 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`。
+当插件拥有提供商特定的模型 id、base URL 默认值或受认证控制的模型元数据时,请使用 `catalog`。
-`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式 provider 的合并时机:
+`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式提供商的合并时机:
-- `simple`:普通 API 密钥或环境变量驱动的 provider
-- `profile`:存在认证配置文件时出现的 provider
-- `paired`:会合成多个相关 provider 条目的 provider
-- `late`:最后一轮,在其他隐式 provider 之后
+- `simple`:普通 API key 或基于环境变量的提供商
+- `profile`:当存在认证配置文件时出现的提供商
+- `paired`:合成多个相关提供商条目的提供商
+- `late`:最后一轮,在其他隐式提供商之后
-后出现的 provider 会在键冲突时胜出,因此插件可以有意用相同 provider id 覆盖某个内置 provider 条目。
+发生键冲突时,较晚的提供商会胜出,因此插件可以有意覆盖拥有相同 provider id 的内置提供商条目。
兼容性:
-- `discovery` 仍可作为 legacy 别名使用
+- `discovery` 仍可作为旧版别名使用
- 如果同时注册了 `catalog` 和 `discovery`,OpenClaw 会使用 `catalog`
## 只读渠道检查
-如果你的插件注册了一个渠道,建议在实现 `resolveAccount(...)` 的同时,也实现 `plugin.config.inspectAccount(cfg, accountId)`。
+如果你的插件注册了某个渠道,请优先在 `resolveAccount(...)` 旁边实现
+`plugin.config.inspectAccount(cfg, accountId)`。
原因如下:
-- `resolveAccount(...)` 是运行时路径。它可以假定凭证已经完全实体化,并且在所需 secret 缺失时快速失败。
-- 像 `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve` 以及 Doctor / 配置修复流程这样的只读命令路径,不应为了描述配置而必须实体化运行时凭证。
+- `resolveAccount(...)` 是运行时路径。它可以假设凭证已被完整实体化,并且在缺少必需密钥时快速失败。
+- 诸如 `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`。
+- 你不需要为了报告只读可用性而返回原始 token 值。返回 `tokenStatus: "available"`(以及对应的来源字段)就足以支持状态类命令。
+- 当凭证通过 SecretRef 配置,但在当前命令路径中不可用时,请使用 `configured_unavailable`。
-这样只读命令就可以报告“已配置,但在当前命令路径中不可用”,而不是崩溃或错误地将账户报告为未配置。
+这样,只读命令就能报告“已配置,但在当前命令路径中不可用”,而不会崩溃或错误地把该账户报告为未配置。
## 包集合
-一个插件目录可以包含带有 `openclaw.extensions` 的 `package.json`:
+插件目录可以包含一个带有 `openclaw.extensions` 的 `package.json`:
```json
{
@@ -997,37 +1036,40 @@ Provider 插件可以通过 `registerProvider({ catalog: { run(...) { ... } } })
}
```
-每个条目都会变成一个插件。如果该集合列出了多个扩展,那么插件 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` 可以指向一个轻量级的仅 setup 模块。当 OpenClaw 需要为某个已禁用的渠道插件提供 setup 接口,或者某个渠道插件虽然已启用但尚未配置时,它会加载 `setupEntry` 而不是完整插件入口。这样当你的主插件入口还会接线工具、钩子或其他仅运行时代码时,就能让启动和 setup 更轻量。
+可选:`openclaw.setupEntry` 可以指向一个轻量级、仅用于设置的模块。当 OpenClaw 需要为一个已禁用的渠道插件提供设置接口,或当某个渠道插件已启用但尚未配置时,它会加载 `setupEntry`,而不是完整插件入口。这样,当你的主插件入口还会接线工具、钩子或其他仅运行时代码时,就能让启动和设置过程更轻量。
-可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` 可以让某个渠道插件在 Gateway 网关预监听启动阶段也走同样的 `setupEntry` 路径,即使该渠道已经配置完成。
+可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen`
+可以让某个渠道插件在 Gateway 网关监听前的启动阶段,即使该渠道已经完成配置,也仍走同样的 `setupEntry` 路径。
-仅当 `setupEntry` 能完全覆盖网关开始监听之前必须存在的启动接口时,才应使用此选项。实践中,这意味着 setup 入口必须注册启动所依赖的每项渠道自有能力,例如:
+只有当 `setupEntry` 完整覆盖了 Gateway 网关开始监听前必须存在的启动接口时,才应使用它。实际上,这意味着设置入口必须注册启动所依赖的每一项渠道自有能力,例如:
- 渠道注册本身
-- 所有必须在 Gateway 网关开始监听前可用的 HTTP 路由
-- 所有必须在同一窗口期内存在的 Gateway 网关方法、工具或服务
+- 任何必须在 Gateway 网关开始监听前可用的 HTTP 路由
+- 任何必须在同一时间窗口内存在的 Gateway 网关方法、工具或服务
-如果你的完整入口仍然拥有任何必需的启动能力,就不要启用此标志。请保持插件使用默认行为,让 OpenClaw 在启动时加载完整入口。
+如果完整入口仍拥有任何必需的启动能力,请不要启用此标志。应保持插件使用默认行为,让 OpenClaw 在启动期间加载完整入口。
-内置渠道还可以发布 setup 专用的契约接口辅助工具,以便核心在完整渠道运行时尚未加载前进行查询。当前的 setup 提升接口包括:
+内置渠道还可以发布仅设置用的契约接口辅助工具,供核心在完整渠道运行时尚未加载前查询。当前的设置提升接口包括:
- `singleAccountKeysToMove`
- `namedAccountPromotionKeys`
- `resolveSingleAccountPromotionTarget(...)`
-当核心需要在不加载完整插件入口的情况下,将 legacy 单账户渠道配置提升到 `channels..accounts.*` 时,就会使用该接口。Matrix 是当前的内置示例:当已存在命名账户时,它只会将认证 / 引导键移动到一个被提升命名的账户中,并且它可以保留一个已配置的、非规范默认账户键,而不是总是创建 `accounts.default`。
+当核心需要在不加载完整插件入口的情况下,将旧版单账户渠道配置提升为 `channels..accounts.*` 时,会使用这组接口。Matrix 是当前的内置示例:当已存在命名账户时,它只会将认证 / bootstrap 键移动到提升后的命名账户中,并且能够保留一个已配置但非规范的默认账户键,而不是总是创建 `accounts.default`。
-这些 setup patch 适配器使得内置契约接口的发现保持懒加载。导入时开销保持很轻;提升接口只会在首次使用时加载,而不会在模块导入时重新进入内置渠道启动流程。
+这些设置补丁适配器使内置契约接口发现保持惰性。导入时保持轻量;提升接口只会在首次使用时加载,而不会在模块导入时重新进入内置渠道启动流程。
-当这些启动接口包含 Gateway 网关 RPC 方法时,请将它们保留在插件特定前缀下。核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且即使某个插件请求了更窄的作用域,它们也始终会解析为 `operator.admin`。
+当这些启动接口包含 Gateway 网关 RPC 方法时,请将它们保留在插件特定前缀下。核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且始终解析为 `operator.admin`,即使某个插件请求更窄的作用域也是如此。
示例:
@@ -1046,7 +1088,7 @@ Provider 插件可以通过 `registerProvider({ catalog: { run(...) { ... } } })
### 渠道目录元数据
-渠道插件可以通过 `openclaw.channel` 公布 setup / 发现元数据,并通过 `openclaw.install` 公布安装提示。这样可以让核心目录保持无数据化。
+渠道插件可以通过 `openclaw.channel` 声明设置 / 发现元数据,并通过 `openclaw.install` 声明安装提示。这样可以让核心目录保持无数据化。
示例:
@@ -1074,32 +1116,31 @@ Provider 插件可以通过 `registerProvider({ catalog: { run(...) { ... } } })
}
```
-除了最小示例之外,其他有用的 `openclaw.channel` 字段还包括:
+除了最小示例外,实用的 `openclaw.channel` 字段还包括:
-- `detailLabel`:用于更丰富目录 / 状态接口的次级标签
-- `docsLabel`:覆盖文档链接的链接文本
-- `preferOver`:该目录条目应优先于哪些低优先级插件 / 渠道 id
+- `detailLabel`:用于更丰富目录 / 状态界面的次级标签
+- `docsLabel`:覆盖文档链接的显示文本
+- `preferOver`:此目录条目应优先于的低优先级插件 / 渠道 id
- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择界面的文案控制
-- `markdownCapable`:将该渠道标记为支持 Markdown,以供 outbound 格式化决策使用
-- `exposure.configured`:设为 `false` 时,在已配置渠道列表界面中隐藏该渠道
-- `exposure.setup`:设为 `false` 时,在交互式 setup / configure 选择器中隐藏该渠道
-- `exposure.docs`:将该渠道标记为内部 / 私有,以供文档导航界面使用
-- `showConfigured` / `showInSetup`:legacy 别名,仍出于兼容性被接受;优先使用 `exposure`
-- `quickstartAllowFrom`:让该渠道加入标准快速开始 `allowFrom` 流程
+- `markdownCapable`:将该渠道标记为支持 Markdown,以供出站格式决策使用
+- `exposure.configured`:设置为 `false` 时,在已配置渠道列表界面中隐藏该渠道
+- `exposure.setup`:设置为 `false` 时,在交互式设置 / 配置选择器中隐藏该渠道
+- `exposure.docs`:在文档导航界面中将该渠道标记为内部 / 私有
+- `showConfigured` / `showInSetup`:旧版别名,出于兼容性仍可接受;优先使用 `exposure`
+- `quickstartAllowFrom`:让该渠道接入标准快速开始 `allowFrom` 流程
- `forceAccountBinding`:即使只有一个账户,也要求显式账户绑定
-- `preferSessionLookupForAnnounceTarget`:在解析 announce 目标时优先使用会话查找
+- `preferSessionLookupForAnnounceTarget`:在解析公告目标时优先使用会话查找
-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"` 键的 legacy 别名。
+或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(使用逗号 / 分号 / `PATH` 分隔)。每个文件应包含
+`{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的旧版别名。
## 上下文引擎插件
-上下文引擎插件拥有用于摄取、组装和压缩的会话上下文编排。请在你的插件中使用 `api.registerContextEngine(id, factory)` 注册它们,然后通过 `plugins.slots.contextEngine` 选择活动引擎。
+上下文引擎插件拥有会话上下文编排,包括摄取、组装和压缩。请在你的插件中通过
+`api.registerContextEngine(id, factory)` 注册它们,然后通过
+`plugins.slots.contextEngine` 选择活动引擎。
当你的插件需要替换或扩展默认上下文流水线,而不仅仅是增加 memory 搜索或钩子时,请使用这种方式。
@@ -1129,7 +1170,7 @@ export default function (api) {
}
```
-如果你的引擎**并不**拥有压缩算法,请保持 `compact()` 已实现,并显式委托它:
+如果你的引擎**不**拥有压缩算法,请保留 `compact()` 的实现,并显式委托它:
```ts
import {
@@ -1166,37 +1207,37 @@ export default function (api) {
## 添加新能力
-当某个插件需要当前 API 无法满足的行为时,不要通过私有内部访问绕过插件系统。请添加缺失的能力。
+当插件需要当前 API 无法覆盖的行为时,不要通过私有内部接入绕过插件系统。应添加缺失的能力。
推荐顺序:
-1. 定义核心契约
- 决定哪些共享行为应由核心拥有:策略、回退、配置合并、生命周期、面向渠道的语义,以及运行时辅助工具形态。
-2. 添加类型化插件注册 / 运行时接口
- 使用最小但有用的类型化能力接口扩展 `OpenClawPluginApi` 和 / 或 `api.runtime`。
-3. 对接核心 + 渠道 / 功能使用方
- 各渠道和功能插件应通过核心消费新能力,而不是直接导入某个厂商实现。
-4. 注册厂商实现
- 然后由厂商插件针对该能力注册它们的后端。
-5. 添加契约覆盖
- 添加测试,以便随着时间推移,归属关系和注册形态仍然保持明确。
+1. 定义核心契约
+ 确定哪些共享行为应由核心拥有:策略、回退、配置合并、生命周期、面向渠道的语义,以及运行时辅助工具的形态。
+2. 添加类型化的插件注册 / 运行时接口
+ 以最小且有用的类型化能力接口扩展 `OpenClawPluginApi` 和 / 或 `api.runtime`。
+3. 接入核心 + 渠道 / 功能消费者
+ 渠道和功能插件应通过核心消费新能力,而不是直接导入某个供应商实现。
+4. 注册供应商实现
+ 然后由供应商插件针对该能力注册它们的后端实现。
+5. 添加契约覆盖
+ 添加测试,以便归属和注册形态能长期保持清晰。
-这正是 OpenClaw 在保持有主见的同时,又不被单一提供商世界观硬编码绑死的方式。具体文件检查清单和完整示例,请参见[能力扩展手册](/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/` 中面向操作员 / 插件的文档
-如果这些接口中有某一个缺失,通常说明该能力尚未被完全集成。
+如果其中某个接口缺失,通常意味着该能力尚未被完整集成。
### 能力模板
@@ -1232,9 +1273,9 @@ const clip = await api.runtime.videoGeneration.generate({
expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]);
```
-这样规则就很简单:
+这样规则就保持简单:
- 核心拥有能力契约 + 编排
-- 厂商插件拥有厂商实现
+- 供应商插件拥有供应商实现
- 功能 / 渠道插件消费运行时辅助工具
-- 契约测试让归属保持明确
+- 契约测试让归属保持清晰
diff --git a/docs/zh-CN/plugins/manifest.md b/docs/zh-CN/plugins/manifest.md
index e7812ddd0..4fe4ee93e 100644
--- a/docs/zh-CN/plugins/manifest.md
+++ b/docs/zh-CN/plugins/manifest.md
@@ -1,14 +1,14 @@
---
read_when:
- 你正在构建一个 OpenClaw 插件
- - 你需要提供插件配置 schema,或调试插件验证错误
-summary: 插件清单 + JSON schema 要求(严格配置验证)
+ - 你需要提供插件配置 schema,或调试插件校验错误
+summary: 插件清单 + JSON schema 要求(严格配置校验)
title: 插件清单
x-i18n:
- generated_at: "2026-04-12T09:53:32Z"
+ generated_at: "2026-04-12T16:25:36Z"
model: gpt-5.4
provider: openai
- source_hash: 08745ead2c2ab83e56dc041ec3187deead6f0439cb8c8423db03c2e3f5c78e9e
+ source_hash: 93b57c7373e4ccd521b10945346db67991543bd2bed4cc8b6641e1f215b48579
source_path: plugins/manifest.md
workflow: 15
---
@@ -17,7 +17,7 @@ x-i18n:
本页仅适用于**原生 OpenClaw 插件清单**。
-关于兼容的 bundle 布局,请参见[插件 bundles](/zh-CN/plugins/bundles)。
+关于兼容的 bundle 布局,请参见 [插件 bundle](/zh-CN/plugins/bundles)。
兼容的 bundle 格式使用不同的清单文件:
@@ -25,14 +25,14 @@ x-i18n:
- Claude bundle:`.claude-plugin/plugin.json`,或不带清单的默认 Claude 组件布局
- Cursor bundle:`.cursor-plugin/plugin.json`
-OpenClaw 也会自动检测这些 bundle 布局,但不会根据这里描述的 `openclaw.plugin.json` schema 对它们进行验证。
+OpenClaw 也会自动检测这些 bundle 布局,但它们不会根据此处描述的 `openclaw.plugin.json` schema 进行校验。
-对于兼容 bundles,当布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据,以及声明的 skill 根目录、Claude 命令根目录、Claude bundle 的 `settings.json` 默认值、Claude bundle 的 LSP 默认值,以及受支持的 hook packs。
+对于兼容 bundle,OpenClaw 当前会在布局符合 OpenClaw 运行时预期时,读取 bundle 元数据,以及已声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值和支持的 hook pack。
-每个原生 OpenClaw 插件**都必须**在**插件根目录**提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码**的情况下验证配置。缺失或无效的清单会被视为插件错误,并阻止配置验证。
+每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码**的情况下校验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。
-参见完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
-关于原生能力模型以及当前的外部兼容性指南:
+请参见完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
+关于原生能力模型和当前外部兼容性指引,请参见:
[能力模型](/zh-CN/plugins/architecture#public-capability-model)。
## 此文件的作用
@@ -42,14 +42,14 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会根据这里描述的
将它用于:
- 插件标识
-- 配置验证
-- 无需启动插件运行时即可获得的认证和新手引导元数据
-- 可供控制平面界面在运行时加载前检查的低成本激活提示
-- 可供设置 / 新手引导界面在运行时加载前检查的低成本设置描述符
+- 配置校验
+- 在无需启动插件运行时的情况下即可使用的认证和新手引导元数据
+- 控制平面可在运行时加载前检查的轻量激活提示
+- 设置 / 新手引导界面可在运行时加载前检查的轻量设置描述符
- 应在插件运行时加载前解析的别名和自动启用元数据
-- 应在插件运行时加载前自动激活插件的简写模型系列归属元数据
+- 应在插件运行时加载前自动激活插件的简写模型家族归属元数据
- 用于内置兼容性接线和契约覆盖的静态能力归属快照
-- 应在不加载运行时的情况下合并到目录和验证界面的渠道特定配置元数据
+- 应在不加载运行时的情况下合并到目录和校验界面中的渠道特定配置元数据
- 配置 UI 提示
不要将它用于:
@@ -58,7 +58,7 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会根据这里描述的
- 声明代码入口点
- npm 安装元数据
-这些应放在你的插件代码和 `package.json` 中。
+这些内容属于你的插件代码和 `package.json`。
## 最小示例
@@ -131,60 +131,60 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会根据这里描述的
## 顶层字段参考
-| 字段 | 必填 | 类型 | 含义 |
-| ----------------------------------- | ---- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `id` | 是 | `string` | 规范插件 id。这是在 `plugins.entries.` 中使用的 id。 |
-| `configSchema` | 是 | `object` | 此插件配置的内联 JSON Schema。 |
-| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或将其设置为任何非 `true` 的值,则该插件默认保持禁用。 |
-| `legacyPluginIds` | 否 | `string[]` | 会规范化为此规范插件 id 的旧版 id。 |
-| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些 provider id 时,应自动启用此插件。 |
-| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明由 `plugins.slots.*` 使用的独占插件类型。 |
-| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于发现和配置验证。 |
-| `providers` | 否 | `string[]` | 由此插件拥有的 provider id。 |
-| `modelSupport` | 否 | `object` | 由清单拥有的简写模型系列元数据,用于在运行时之前自动加载插件。 |
-| `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
-| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称,应在运行时加载前生成带有插件感知的配置和 CLI 诊断信息。 |
-| `providerAuthEnvVars` | 否 | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量 provider 认证环境变量元数据。 |
-| `providerAuthAliases` | 否 | `Record` | 应复用另一个 provider id 进行认证查找的 provider id,例如共享基础 provider API key 和认证配置文件的编码 provider。 |
-| `channelEnvVars` | 否 | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量渠道环境变量元数据。将其用于由环境变量驱动的渠道设置或认证界面,以便通用启动 / 配置辅助工具能够识别。 |
-| `providerAuthChoices` | 否 | `object[]` | 用于新手引导选择器、首选 provider 解析和简单 CLI 标志接线的轻量认证选择元数据。 |
-| `activation` | 否 | `object` | 针对 provider、命令、渠道、路由和能力触发加载的轻量激活提示。仅为元数据;实际行为仍由插件运行时负责。 |
-| `setup` | 否 | `object` | 设备发现和设置界面可在不加载插件运行时的情况下检查的轻量设置 / 新手引导描述符。 |
-| `contracts` | 否 | `object` | 用于语音、实时转写、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属的静态内置能力快照。 |
-| `channelConfigs` | 否 | `Record` | 由清单拥有的渠道配置元数据,在运行时加载前合并到设备发现和验证界面中。 |
-| `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 |
-| `name` | 否 | `string` | 人类可读的插件名称。 |
-| `description` | 否 | `string` | 在插件界面中显示的简短摘要。 |
-| `version` | 否 | `string` | 仅供参考的插件版本。 |
-| `uiHints` | 否 | `Record` | 配置字段的 UI 标签、占位符和敏感性提示。 |
+| Field | Required | Type | What it means |
+| ----------------------------------- | -------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `id` | Yes | `string` | 规范插件 id。这是在 `plugins.entries.` 中使用的 id。 |
+| `configSchema` | Yes | `object` | 此插件配置的内联 JSON Schema。 |
+| `enabledByDefault` | No | `true` | 将内置插件标记为默认启用。省略此字段,或将其设置为任何非 `true` 的值,以使插件默认保持禁用。 |
+| `legacyPluginIds` | No | `string[]` | 会规范化为此规范插件 id 的旧版 id。 |
+| `autoEnableWhenConfiguredProviders` | No | `string[]` | 当认证、配置或模型引用提到这些提供商 id 时,应自动启用此插件。 |
+| `kind` | No | `"memory"` \| `"context-engine"` | 声明由 `plugins.slots.*` 使用的独占插件类型。 |
+| `channels` | No | `string[]` | 此插件拥有的渠道 id。用于设备发现和配置校验。 |
+| `providers` | No | `string[]` | 此插件拥有的提供商 id。 |
+| `modelSupport` | No | `object` | 由清单拥有的简写模型家族元数据,用于在运行时之前自动加载插件。 |
+| `cliBackends` | No | `string[]` | 此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
+| `commandAliases` | No | `object[]` | 此插件拥有的命令名称,应在运行时加载前生成具备插件感知能力的配置和 CLI 诊断信息。 |
+| `providerAuthEnvVars` | No | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量提供商认证环境变量元数据。 |
+| `providerAuthAliases` | No | `Record` | 应复用另一个提供商 id 进行认证查找的提供商 id,例如共享基础提供商 API key 和认证配置文件的 coding 提供商。 |
+| `channelEnvVars` | No | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量渠道环境变量元数据。将其用于由环境变量驱动的渠道设置或认证界面,以便通用的启动 / 配置辅助工具能够识别。 |
+| `providerAuthChoices` | No | `object[]` | 用于新手引导选择器、首选提供商解析和简单 CLI flag 接线的轻量认证选项元数据。 |
+| `activation` | No | `object` | 用于由提供商、命令、渠道、路由和能力触发加载的轻量激活提示。仅元数据;插件运行时仍拥有实际行为。 |
+| `setup` | No | `object` | 设备发现和设置界面可在不加载插件运行时的情况下检查的轻量设置 / 新手引导描述符。 |
+| `contracts` | No | `object` | 用于语音、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、web 获取、web 搜索和工具归属的静态内置能力快照。 |
+| `channelConfigs` | No | `Record` | 由清单拥有的渠道配置元数据,在运行时加载前合并到设备发现和校验界面中。 |
+| `skills` | No | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 |
+| `name` | No | `string` | 人类可读的插件名称。 |
+| `description` | No | `string` | 在插件界面中显示的简短摘要。 |
+| `version` | No | `string` | 信息性插件版本。 |
+| `uiHints` | No | `Record` | 配置字段的 UI 标签、占位符和敏感性提示。 |
## `providerAuthChoices` 参考
每个 `providerAuthChoices` 条目描述一个新手引导或认证选项。
-OpenClaw 会在 provider 运行时加载前读取这些内容。
+OpenClaw 会在提供商运行时加载前读取这些信息。
-| 字段 | 必填 | 类型 | 含义 |
-| --------------------- | ---- | ----------------------------------------------- | -------------------------------------------------------------------------------------------- |
-| `provider` | 是 | `string` | 此选项所属的 provider id。 |
-| `method` | 是 | `string` | 要分发到的认证方法 id。 |
-| `choiceId` | 是 | `string` | 由新手引导和 CLI 流程使用的稳定认证选项 id。 |
-| `choiceLabel` | 否 | `string` | 面向用户的标签。如果省略,OpenClaw 会回退到 `choiceId`。 |
-| `choiceHint` | 否 | `string` | 选择器中显示的简短辅助文本。 |
-| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,值越小排序越靠前。 |
-| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏该选项,但仍允许通过手动 CLI 选择。 |
-| `deprecatedChoiceIds` | 否 | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 |
-| `groupId` | 否 | `string` | 用于对相关选项进行分组的可选分组 id。 |
-| `groupLabel` | 否 | `string` | 该分组面向用户的标签。 |
-| `groupHint` | 否 | `string` | 该分组的简短辅助文本。 |
-| `optionKey` | 否 | `string` | 用于简单单标志认证流程的内部选项键。 |
-| `cliFlag` | 否 | `string` | CLI 标志名称,例如 `--openrouter-api-key`。 |
-| `cliOption` | 否 | `string` | 完整的 CLI 选项形式,例如 `--openrouter-api-key `。 |
-| `cliDescription` | 否 | `string` | 在 CLI 帮助中使用的描述。 |
-| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如果省略,默认值为 `["text-inference"]`。 |
+| Field | Required | Type | What it means |
+| --------------------- | -------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------- |
+| `provider` | Yes | `string` | 此选项所属的提供商 id。 |
+| `method` | Yes | `string` | 要分发到的认证方法 id。 |
+| `choiceId` | Yes | `string` | 由新手引导和 CLI 流程使用的稳定认证选项 id。 |
+| `choiceLabel` | No | `string` | 面向用户的标签。如果省略,OpenClaw 会回退到 `choiceId`。 |
+| `choiceHint` | No | `string` | 选择器中显示的简短辅助文本。 |
+| `assistantPriority` | No | `number` | 在由助手驱动的交互式选择器中,值越小排序越靠前。 |
+| `assistantVisibility` | No | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏该选项,但仍允许手动通过 CLI 选择。 |
+| `deprecatedChoiceIds` | No | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 |
+| `groupId` | No | `string` | 用于对相关选项进行分组的可选分组 id。 |
+| `groupLabel` | No | `string` | 该分组面向用户的标签。 |
+| `groupHint` | No | `string` | 该分组的简短辅助文本。 |
+| `optionKey` | No | `string` | 用于简单单 flag 认证流程的内部选项键。 |
+| `cliFlag` | No | `string` | CLI flag 名称,例如 `--openrouter-api-key`。 |
+| `cliOption` | No | `string` | 完整的 CLI 选项形式,例如 `--openrouter-api-key `。 |
+| `cliDescription` | No | `string` | 用于 CLI 帮助信息中的描述。 |
+| `onboardingScopes` | No | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如果省略,默认值为 `["text-inference"]`。 |
## `commandAliases` 参考
-当插件拥有一个运行时命令名,而用户可能会误把它放进 `plugins.allow` 中,或尝试把它作为根级 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用这些元数据提供诊断信息,而无需导入插件运行时代码。
+当插件拥有某个运行时命令名称,而用户可能会误将其放入 `plugins.allow` 或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用这些元数据在不导入插件运行时代码的情况下提供诊断信息。
```json
{
@@ -198,17 +198,18 @@ OpenClaw 会在 provider 运行时加载前读取这些内容。
}
```
-| 字段 | 必填 | 类型 | 含义 |
-| ------------ | ---- | ----------------- | ------------------------------------------------------------- |
-| `name` | 是 | `string` | 属于此插件的命令名称。 |
-| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根级 CLI 命令。 |
-| `cliCommand` | 否 | `string` | 如果存在,可为 CLI 操作建议的相关根级 CLI 命令。 |
+| Field | Required | Type | What it means |
+| ------------ | -------- | ----------------- | -------------------------------------------------------------- |
+| `name` | Yes | `string` | 属于此插件的命令名称。 |
+| `kind` | No | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根 CLI 命令。 |
+| `cliCommand` | No | `string` | 若存在相关根 CLI 命令,则建议用于 CLI 操作的对应根 CLI 命令。 |
## `activation` 参考
-当插件可以低成本地声明哪些控制平面事件应在之后激活它时,请使用 `activation`。
+当插件可以以低成本声明哪些控制平面事件应在之后激活它时,请使用 `activation`。
-此代码块仅用于元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。当前使用方会在更广泛的插件加载前将其作为收窄提示,因此缺少激活元数据通常只会影响性能;在旧版清单归属回退仍然存在时,它不应影响正确性。
+此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。
+当前使用方会在更广泛的插件加载之前将其作为收窄提示,因此缺少激活元数据通常只会带来性能损耗;在旧版清单归属回退机制仍存在时,它不应改变正确性。
```json
{
@@ -222,25 +223,26 @@ OpenClaw 会在 provider 运行时加载前读取这些内容。
}
```
-| 字段 | 必填 | 类型 | 含义 |
-| ---------------- | ---- | ---------------------------------------------------- | ------------------------------------------------------ |
-| `onProviders` | 否 | `string[]` | 当请求这些 provider id 时应激活此插件。 |
-| `onCommands` | 否 | `string[]` | 应激活此插件的命令 id。 |
-| `onChannels` | 否 | `string[]` | 应激活此插件的渠道 id。 |
-| `onRoutes` | 否 | `string[]` | 应激活此插件的路由类型。 |
-| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的广义能力提示。 |
+| Field | Required | Type | What it means |
+| ---------------- | -------- | ---------------------------------------------------- | ----------------------------------------------------- |
+| `onProviders` | No | `string[]` | 请求这些提供商 id 时应激活此插件。 |
+| `onCommands` | No | `string[]` | 这些命令 id 应激活此插件。 |
+| `onChannels` | No | `string[]` | 这些渠道 id 应激活此插件。 |
+| `onRoutes` | No | `string[]` | 这些路由类型应激活此插件。 |
+| `onCapabilities` | No | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的广义能力提示。 |
-当前正在使用的消费者:
+当前在线使用方:
- 由命令触发的 CLI 规划会回退到旧版
`commandAliases[].cliCommand` 或 `commandAliases[].name`
-- 由 provider 触发的设置 / 运行时规划会在缺少显式 provider
- 激活元数据时,回退到旧版 `providers[]` 和顶层 `cliBackends[]`
+- 由渠道触发的设置 / 渠道规划会在缺少显式渠道激活元数据时,回退到旧版 `channels[]`
归属信息
+- 由提供商触发的设置 / 运行时规划会在缺少显式提供商激活元数据时,回退到旧版
+ `providers[]` 和顶层 `cliBackends[]` 归属信息
## `setup` 参考
-当设置和新手引导界面需要在运行时加载前获取低成本、由插件拥有的元数据时,请使用 `setup`。
+当设置和新手引导界面需要在运行时加载前获取由插件拥有的轻量元数据时,请使用 `setup`。
```json
{
@@ -259,32 +261,32 @@ OpenClaw 会在 provider 运行时加载前读取这些内容。
}
```
-顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是用于控制平面 / 设置流程的设置专用描述符界面,应保持为纯元数据。
+顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是面向控制平面 / 设置流程的设置专用描述符界面,应保持为纯元数据。
-存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现时首选的“描述符优先”查找界面。如果该描述符仅用于收窄候选插件,而设置仍需要更丰富的设置时运行时 hooks,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。
+当存在 `setup.providers` 和 `setup.cliBackends` 时,它们是设置发现过程中优先使用的描述符优先查找界面。如果该描述符仅用于收窄候选插件,而设置仍需要更丰富的设置时运行时 hook,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。
-由于设置查找可能会执行插件拥有的 `setup-api` 代码,因此规范化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值必须在已发现插件之间保持唯一。归属不明确时会以封闭失败的方式处理,而不是根据发现顺序选出一个“胜者”。
+由于设置查找可能会执行由插件拥有的 `setup-api` 代码,因此规范化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值在所有已发现插件中必须保持唯一。归属不明确时会默认失败关闭,而不是按发现顺序选择一个赢家。
### `setup.providers` 参考
-| 字段 | 必填 | 类型 | 含义 |
-| ------------- | ---- | ---------- | -------------------------------------------------------------------- |
-| `id` | 是 | `string` | 在设置或新手引导期间公开的 provider id。保持规范化 id 在全局唯一。 |
-| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置 / 认证方法 id。 |
-| `envVars` | 否 | `string[]` | 通用设置 / 状态界面可在插件运行时加载前检查的环境变量。 |
+| Field | Required | Type | What it means |
+| ------------- | -------- | ---------- | ------------------------------------------------------------------------------ |
+| `id` | Yes | `string` | 在设置或新手引导期间公开的提供商 id。请确保规范化 id 在全局范围内唯一。 |
+| `authMethods` | No | `string[]` | 此提供商在不加载完整运行时的情况下支持的设置 / 认证方法 id。 |
+| `envVars` | No | `string[]` | 通用设置 / 状态界面可在插件运行时加载前检查的环境变量。 |
### `setup` 字段
-| 字段 | 必填 | 类型 | 含义 |
-| ------------------ | ---- | ---------- | -------------------------------------------------------------------------------------------- |
-| `providers` | 否 | `object[]` | 在设置和新手引导期间公开的 provider 设置描述符。 |
-| `cliBackends` | 否 | `string[]` | 用于“描述符优先”设置查找的设置时后端 id。保持规范化 id 在全局唯一。 |
-| `configMigrations` | 否 | `string[]` | 由此插件设置界面拥有的配置迁移 id。 |
-| `requiresRuntime` | 否 | `boolean` | 描述符查找之后,设置是否仍需要执行 `setup-api`。 |
+| Field | Required | Type | What it means |
+| ------------------ | -------- | ---------- | --------------------------------------------------------------------------------------------- |
+| `providers` | No | `object[]` | 在设置和新手引导期间公开的提供商设置描述符。 |
+| `cliBackends` | No | `string[]` | 用于描述符优先设置查找的设置时后端 id。请确保规范化 id 在全局范围内唯一。 |
+| `configMigrations` | No | `string[]` | 由此插件的设置界面拥有的配置迁移 id。 |
+| `requiresRuntime` | No | `boolean` | 描述符查找后,设置是否仍需要执行 `setup-api`。 |
## `uiHints` 参考
-`uiHints` 是从配置字段名到小型渲染提示的映射。
+`uiHints` 是从配置字段名称到小型渲染提示的映射。
```json
{
@@ -301,18 +303,18 @@ OpenClaw 会在 provider 运行时加载前读取这些内容。
每个字段提示可包含:
-| 字段 | 类型 | 含义 |
-| ------------- | ---------- | ------------------------------- |
-| `label` | `string` | 面向用户的字段标签。 |
-| `help` | `string` | 简短辅助文本。 |
-| `tags` | `string[]` | 可选的 UI 标签。 |
-| `advanced` | `boolean` | 将该字段标记为高级项。 |
-| `sensitive` | `boolean` | 将该字段标记为密钥或敏感信息。 |
-| `placeholder` | `string` | 表单输入的占位文本。 |
+| Field | Type | What it means |
+| ------------- | ---------- | ----------------------------------- |
+| `label` | `string` | 面向用户的字段标签。 |
+| `help` | `string` | 简短辅助文本。 |
+| `tags` | `string[]` | 可选 UI 标签。 |
+| `advanced` | `boolean` | 将该字段标记为高级字段。 |
+| `sensitive` | `boolean` | 将该字段标记为密钥或敏感字段。 |
+| `placeholder` | `string` | 表单输入的占位文本。 |
## `contracts` 参考
-仅在 OpenClaw 可以不导入插件运行时就读取静态能力归属元数据时,使用 `contracts`。
+仅在 OpenClaw 可以在不导入插件运行时的情况下读取静态能力归属元数据时使用 `contracts`。
```json
{
@@ -332,21 +334,21 @@ OpenClaw 会在 provider 运行时加载前读取这些内容。
每个列表都是可选的:
-| 字段 | 类型 | 含义 |
-| -------------------------------- | ---------- | ------------------------------------------------------ |
-| `speechProviders` | `string[]` | 此插件拥有的语音 provider id。 |
-| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转写 provider id。 |
-| `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音 provider id。 |
-| `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解 provider id。 |
-| `imageGenerationProviders` | `string[]` | 此插件拥有的图像生成 provider id。 |
-| `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成 provider id。 |
-| `webFetchProviders` | `string[]` | 此插件拥有的网页抓取 provider id。 |
-| `webSearchProviders` | `string[]` | 此插件拥有的网页搜索 provider id。 |
-| `tools` | `string[]` | 此插件拥有的智能体工具名称,用于内置契约检查。 |
+| Field | Type | What it means |
+| -------------------------------- | ---------- | ------------------------------------------------------- |
+| `speechProviders` | `string[]` | 此插件拥有的语音提供商 id。 |
+| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转录提供商 id。 |
+| `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音提供商 id。 |
+| `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解提供商 id。 |
+| `imageGenerationProviders` | `string[]` | 此插件拥有的图像生成提供商 id。 |
+| `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成提供商 id。 |
+| `webFetchProviders` | `string[]` | 此插件拥有的 web 获取提供商 id。 |
+| `webSearchProviders` | `string[]` | 此插件拥有的 web 搜索提供商 id。 |
+| `tools` | `string[]` | 此插件拥有的智能体工具名称,用于内置契约检查。 |
## `channelConfigs` 参考
-当渠道插件需要在运行时加载前提供低成本配置元数据时,请使用 `channelConfigs`。
+当渠道插件需要在运行时加载前提供轻量配置元数据时,请使用 `channelConfigs`。
```json
{
@@ -375,17 +377,17 @@ OpenClaw 会在 provider 运行时加载前读取这些内容。
每个渠道条目可包含:
-| 字段 | 类型 | 含义 |
-| ------------- | ------------------------ | ---------------------------------------------------------------------------------------- |
-| `schema` | `object` | `channels.` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 |
-| `uiHints` | `Record` | 该渠道配置部分的可选 UI 标签 / 占位符 / 敏感性提示。 |
-| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 |
-| `description` | `string` | 用于检查和目录界面的简短渠道描述。 |
-| `preferOver` | `string[]` | 此渠道在选择界面中应优先于的旧版或较低优先级插件 id。 |
+| Field | Type | What it means |
+| ------------- | ------------------------ | --------------------------------------------------------------------------------------- |
+| `schema` | `object` | `channels.` 的 JSON Schema。每个已声明的渠道配置条目都必须提供此字段。 |
+| `uiHints` | `Record` | 该渠道配置部分可选的 UI 标签 / 占位符 / 敏感性提示。 |
+| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 |
+| `description` | `string` | 用于检查和目录界面的简短渠道描述。 |
+| `preferOver` | `string[]` | 在选择界面中,此渠道应优先于的旧版或较低优先级插件 id。 |
## `modelSupport` 参考
-当 OpenClaw 应在插件运行时加载前,根据简写模型 id(如 `gpt-5.4` 或 `claude-sonnet-4.6`)推断出你的 provider 插件时,请使用 `modelSupport`。
+当 OpenClaw 应在插件运行时加载前,从 `gpt-5.4` 或 `claude-sonnet-4.6` 之类的简写模型 id 推断出你的提供商插件时,请使用 `modelSupport`。
```json
{
@@ -396,64 +398,65 @@ OpenClaw 会在 provider 运行时加载前读取这些内容。
}
```
-OpenClaw 按以下优先级应用:
+OpenClaw 按以下优先级应用规则:
-- 显式 `provider/model` 引用使用所属的 `providers` 清单元数据
-- `modelPatterns` 优先于 `modelPrefixes`
+- 显式 `provider/model` 引用使用拥有该模型的 `providers` 清单元数据
+- `modelPatterns` 的优先级高于 `modelPrefixes`
- 如果一个非内置插件和一个内置插件都匹配,则非内置插件胜出
-- 若仍存在歧义,则在用户或配置明确指定 provider 之前忽略
+- 对于剩余的歧义,在用户或配置明确指定提供商之前会被忽略
字段:
-| 字段 | 类型 | 含义 |
-| --------------- | ---------- | -------------------------------------------------------------------------- |
-| `modelPrefixes` | `string[]` | 使用 `startsWith` 与简写模型 id 进行匹配的前缀。 |
-| `modelPatterns` | `string[]` | 在移除 profile 后缀后,用于匹配简写模型 id 的正则表达式源码。 |
+| Field | Type | What it means |
+| --------------- | ---------- | --------------------------------------------------------------------- |
+| `modelPrefixes` | `string[]` | 使用 `startsWith` 与简写模型 id 进行匹配的前缀。 |
+| `modelPatterns` | `string[]` | 在移除配置文件后缀后,与简写模型 id 进行匹配的正则表达式源码。 |
-旧版顶层能力键已弃用。使用 `openclaw doctor --fix` 将
+旧版顶层能力键已弃用。请使用 `openclaw doctor --fix` 将
`speechProviders`、`realtimeTranscriptionProviders`、
`realtimeVoiceProviders`、`mediaUnderstandingProviders`、
`imageGenerationProviders`、`videoGenerationProviders`、
-`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;普通清单加载不再将这些顶层字段视为能力归属信息。
+`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;正常的清单加载不再将这些顶层字段视为能力归属信息。
## 清单与 `package.json` 的区别
-这两个文件承担不同的职责:
+这两个文件承担不同职责:
-| 文件 | 用途 |
-| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
-| `openclaw.plugin.json` | 设备发现、配置验证、认证选项元数据,以及必须在插件代码运行前存在的 UI 提示 |
-| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 代码块 |
+| File | Use it for |
+| ---------------------- | ---------------------------------------------------------------------------------------------------- |
+| `openclaw.plugin.json` | 在插件代码运行前必须存在的设备发现、配置校验、认证选项元数据和 UI 提示 |
+| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 配置块 |
-如果你不确定某项元数据应放在哪里,请使用以下规则:
+如果你不确定某段元数据应放在哪里,请使用以下规则:
-- 如果 OpenClaw 必须在加载插件代码前知道它,就把它放进 `openclaw.plugin.json`
-- 如果它与打包、入口文件或 npm 安装行为有关,就把它放进 `package.json`
+- 如果 OpenClaw 必须在加载插件代码之前知道它,就把它放在 `openclaw.plugin.json` 中
+- 如果它与打包、入口文件或 npm 安装行为有关,就把它放在 `package.json` 中
-### 会影响设备发现的 `package.json` 字段
+### 影响设备发现的 `package.json` 字段
-一些运行时前插件元数据有意放在 `package.json` 的 `openclaw` 代码块下,而不是 `openclaw.plugin.json` 中。
+某些运行时前插件元数据有意放在 `package.json` 的
+`openclaw` 配置块下,而不是 `openclaw.plugin.json` 中。
重要示例:
-| 字段 | 含义 |
-| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
-| `openclaw.extensions` | 声明原生插件入口点。 |
-| `openclaw.setupEntry` | 在新手引导和延迟渠道启动期间使用的轻量级仅设置入口点。 |
-| `openclaw.channel` | 低成本渠道目录元数据,例如标签、文档路径、别名和选择说明文案。 |
-| `openclaw.channel.configuredState` | 轻量级已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已存在仅基于环境变量的设置?”。 |
-| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已有任何已登录状态?”。 |
-| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 用于内置插件和外部发布插件的安装 / 更新提示。 |
-| `openclaw.install.defaultChoice` | 当存在多个安装来源时的首选安装路径。 |
-| `openclaw.install.minHostVersion` | 最低支持的 OpenClaw host 版本,使用类似 `>=2026.3.22` 的 semver 下限。 |
-| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许使用一条范围很窄的内置插件重新安装恢复路径。 |
-| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许仅设置的渠道界面在启动期间于完整渠道插件之前加载。 |
+| Field | What it means |
+| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| `openclaw.extensions` | 声明原生插件入口点。 |
+| `openclaw.setupEntry` | 在新手引导和延迟渠道启动期间使用的轻量级仅设置入口点。 |
+| `openclaw.channel` | 轻量级渠道目录元数据,例如标签、文档路径、别名和选择文案。 |
+| `openclaw.channel.configuredState` | 轻量级已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已存在仅由环境变量驱动的设置?”。 |
+| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已有任何内容处于已登录状态?”。 |
+| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 用于内置插件和外部发布插件的安装 / 更新提示。 |
+| `openclaw.install.defaultChoice` | 当存在多个安装来源时的首选安装路径。 |
+| `openclaw.install.minHostVersion` | 最低支持的 OpenClaw host 版本,使用类似 `>=2026.3.22` 的 semver 下限。 |
+| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许使用狭义的内置插件重新安装恢复路径。 |
+| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置用途的渠道界面,再加载完整的渠道插件。 |
-`openclaw.install.minHostVersion` 会在安装和清单注册表加载期间强制执行。无效值会被拒绝;在旧版 host 上,较新但有效的值会跳过该插件。
+`openclaw.install.minHostVersion` 会在安装期间和清单注册表加载期间强制执行。无效值会被拒绝;较新的但有效的值会在较旧 host 上跳过该插件。
-`openclaw.install.allowInvalidConfigRecovery` 的适用范围被有意限制得很窄。它不会让任意损坏的配置变得可安装。当前它只允许安装流程从特定的陈旧内置插件升级失败中恢复,例如缺失的内置插件路径,或同一内置插件对应的陈旧 `channels.` 条目。无关的配置错误仍会阻止安装,并将操作人员引导到 `openclaw doctor --fix`。
+`openclaw.install.allowInvalidConfigRecovery` 的设计范围是刻意收窄的。它不会让任意损坏的配置变为可安装。当前它仅允许安装流程从特定的陈旧内置插件升级故障中恢复,例如缺失的内置插件路径,或该内置插件对应的陈旧 `channels.` 条目。无关的配置错误仍会阻止安装,并将操作人员引导至 `openclaw doctor --fix`。
-`openclaw.channel.persistedAuthState` 是一个微型检查器模块的包元数据:
+`openclaw.channel.persistedAuthState` 是一个用于微型检查器模块的包元数据:
```json
{
@@ -469,9 +472,9 @@ OpenClaw 按以下优先级应用:
}
```
-当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前执行低成本的是否已认证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 暴露它。
+当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前执行轻量级的是 / 否认证探测时,请使用它。目标导出应是一个仅仅读取持久化状态的小函数;不要通过完整的渠道运行时 barrel 暴露它。
-`openclaw.channel.configuredState` 采用相同的结构,用于低成本的仅环境变量已配置检查:
+`openclaw.channel.configuredState` 使用相同的结构来进行轻量级的仅环境变量已配置检查:
```json
{
@@ -487,41 +490,41 @@ OpenClaw 按以下优先级应用:
}
```
-当渠道可以从环境变量或其他微小的非运行时输入中判断已配置状态时,请使用它。如果检查需要完整配置解析或真实的渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` hook 中。
+当渠道可以仅通过环境变量或其他轻量级非运行时输入来判断已配置状态时,请使用它。如果该检查需要完整配置解析或真实的渠道运行时,请改为将该逻辑保留在插件 `config.hasConfiguredState` hook 中。
## JSON Schema 要求
- **每个插件都必须提供一个 JSON Schema**,即使它不接受任何配置。
- 可以接受空 schema(例如 `{ "type": "object", "additionalProperties": false }`)。
-- Schema 会在配置读取 / 写入时验证,而不是在运行时验证。
+- Schema 会在读取 / 写入配置时进行校验,而不是在运行时进行校验。
-## 验证行为
+## 校验行为
-- 未知的 `channels.*` 键会被视为**错误**,除非该渠道 id 由某个插件清单声明。
+- 未知的 `channels.*` 键会被视为**错误**,除非该渠道 id 已由某个插件清单声明。
- `plugins.entries.`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*`
必须引用**可发现的**插件 id。未知 id 会被视为**错误**。
-- 如果插件已安装,但其清单或 schema 缺失或损坏,验证会失败,Doctor 会报告该插件错误。
-- 如果插件配置存在,但该插件已**禁用**,配置会被保留,并且 Doctor + 日志中会显示**警告**。
+- 如果某个插件已安装,但其清单或 schema 缺失或损坏,则校验会失败,Doctor 会报告该插件错误。
+- 如果插件配置存在,但插件处于**禁用**状态,则配置会被保留,并且 Doctor + 日志中会显示**警告**。
完整的 `plugins.*` schema 请参见[配置参考](/zh-CN/gateway/configuration)。
## 注意事项
-- 清单对于**原生 OpenClaw 插件**是**必需的**,包括本地文件系统加载的插件。
-- 运行时仍会单独加载插件模块;清单仅用于设备发现 + 验证。
+- 对于原生 OpenClaw 插件,清单是**必需的**,包括从本地文件系统加载的插件。
+- 运行时仍会单独加载插件模块;清单仅用于设备发现 + 校验。
- 原生清单使用 JSON5 解析,因此支持注释、尾随逗号和未加引号的键,只要最终值仍然是一个对象即可。
-- 清单加载器只会读取已记录的清单字段。避免在这里添加自定义顶层键。
-- `providerAuthEnvVars` 是用于认证探测、环境变量标记验证以及类似 provider 认证界面的低成本元数据路径,这些场景不应仅为了检查环境变量名称而启动插件运行时。
-- `providerAuthAliases` 允许 provider 变体复用另一个 provider 的认证环境变量、认证配置文件、基于配置的认证和 API key 新手引导选项,而无需在核心中硬编码这种关系。
-- `channelEnvVars` 是用于 shell 环境变量回退、设置提示以及类似渠道界面的低成本元数据路径,这些场景不应仅为了检查环境变量名称而启动插件运行时。
-- `providerAuthChoices` 是用于认证选项选择器、`--auth-choice` 解析、首选 provider 映射,以及在 provider 运行时加载前进行简单新手引导 CLI 标志注册的低成本元数据路径。对于需要 provider 代码的运行时向导元数据,请参见
- [provider 运行时 hooks](/zh-CN/plugins/architecture#provider-runtime-hooks)。
+- 清单加载器只会读取已文档化的清单字段。避免在此添加自定义顶层键。
+- `providerAuthEnvVars` 是用于认证探测、环境变量标记校验以及类似提供商认证界面的轻量元数据路径,这些场景不应仅为了检查环境变量名称而启动插件运行时。
+- `providerAuthAliases` 允许提供商变体复用另一个提供商的认证环境变量、认证配置文件、基于配置的认证以及 API key 新手引导选项,而无需在 core 中硬编码这种关系。
+- `channelEnvVars` 是用于 shell 环境变量回退、设置提示以及类似渠道界面的轻量元数据路径,这些场景不应仅为了检查环境变量名称而启动插件运行时。
+- `providerAuthChoices` 是用于认证选项选择器、`--auth-choice` 解析、首选提供商映射以及在提供商运行时加载前注册简单新手引导 CLI flag 的轻量元数据路径。对于需要提供商代码的运行时向导元数据,请参见
+ [提供商运行时 hook](/zh-CN/plugins/architecture#provider-runtime-hooks)。
- 独占插件类型通过 `plugins.slots.*` 进行选择。
- `kind: "memory"` 通过 `plugins.slots.memory` 选择。
- `kind: "context-engine"` 通过 `plugins.slots.contextEngine`
选择(默认值:内置 `legacy`)。
-- 当插件不需要它们时,可以省略 `channels`、`providers`、`cliBackends` 和 `skills`。
-- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器 allowlist 要求(例如 pnpm `allow-build-scripts`
+- 当插件不需要 `channels`、`providers`、`cliBackends` 和 `skills` 时,可以省略这些字段。
+- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器允许列表要求(例如 pnpm `allow-build-scripts`
- `pnpm rebuild `)。
## 相关内容