From 6af68ebbf338041b6ec1cc5e1cb86023446e0002 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Tue, 7 Apr 2026 06:56:53 +0000 Subject: [PATCH] chore(i18n): refresh zh-CN translations --- docs/zh-CN/channels/groups.md | 154 +-- docs/zh-CN/channels/zalouser.md | 95 +- docs/zh-CN/plugins/architecture.md | 1251 ++++++++------------- docs/zh-CN/plugins/sdk-channel-plugins.md | 233 ++-- docs/zh-CN/plugins/sdk-overview.md | 378 +++---- docs/zh-CN/plugins/sdk-runtime.md | 125 +- 6 files changed, 1042 insertions(+), 1194 deletions(-) diff --git a/docs/zh-CN/channels/groups.md b/docs/zh-CN/channels/groups.md index f3e7fce1c..5162f5284 100644 --- a/docs/zh-CN/channels/groups.md +++ b/docs/zh-CN/channels/groups.md @@ -1,40 +1,40 @@ --- read_when: - - 修改群聊行为或提及门控时 -summary: 跨界面群聊行为(Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo) + - 更改群聊行为或提及门控时 +summary: 跨表面的群聊行为(Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo) title: 群组 x-i18n: - generated_at: "2026-04-06T15:28:01Z" + generated_at: "2026-04-07T06:53:32Z" model: gpt-5.4 provider: openai - source_hash: 83d20f2958ed6ad3354f0078553b3c6a38643ea8ef38573c40e89ebef2fa8421 + source_hash: f5045badbba30587c8f1bf27f6b940c7c471a95c57093c9adb142374413ac81e source_path: channels/groups.md workflow: 15 --- # 群组 -OpenClaw 会在各个界面上一致地处理群聊:Discord、iMessage、Matrix、Microsoft Teams、Signal、Slack、Telegram、WhatsApp、Zalo。 +OpenClaw 会在各个表面上一致地处理群聊:Discord、iMessage、Matrix、Microsoft Teams、Signal、Slack、Telegram、WhatsApp、Zalo。 -## 新手简介(2 分钟) +## 新手介绍(2 分钟) -OpenClaw “运行”在你自己的消息账号上。它不是一个单独的 WhatsApp 机器人用户。 -如果**你**在某个群里,OpenClaw 就可以看到那个群并在那里回复。 +OpenClaw “运行”在你自己的消息账号上。没有单独的 WhatsApp 机器人用户。 +如果**你**在某个群组中,OpenClaw 就能看到该群组并在那里回复。 默认行为: -- 群组是受限的(`groupPolicy: "allowlist"`)。 +- 群组受限(`groupPolicy: "allowlist"`)。 - 回复需要提及,除非你明确禁用提及门控。 -换句话说:在允许列表中的发送者可以通过提及 OpenClaw 来触发它。 +也就是说:在允许列表中的发送者可以通过提及 OpenClaw 来触发它。 -> 简而言之 +> TL;DR > -> - **私信访问**由 `*.allowFrom` 控制。 -> - **群组访问**由 `*.groupPolicy` + 允许列表(`*.groups`、`*.groupAllowFrom`)控制。 -> - **回复触发**由提及门控(`requireMention`、`/activation`)控制。 +> - **私信访问权限**由 `*.allowFrom` 控制。 +> - **群组访问权限**由 `*.groupPolicy` + 允许列表(`*.groups`、`*.groupAllowFrom`)控制。 +> - **回复触发**由提及门控控制(`requireMention`、`/activation`)。 -快速流程(群消息会发生什么): +快速流程(群组消息会发生什么): ``` groupPolicy? disabled -> drop @@ -47,58 +47,58 @@ otherwise -> reply 群组安全涉及两种不同的控制: -- **触发授权**:谁可以触发智能体(`groupPolicy`、`groups`、`groupAllowFrom`、渠道特定允许列表)。 -- **上下文可见性**:哪些补充上下文会注入到模型中(回复文本、引用、线程历史、转发元数据)。 +- **触发授权**:谁可以触发智能体(`groupPolicy`、`groups`、`groupAllowFrom`、特定渠道的允许列表)。 +- **上下文可见性**:哪些补充上下文会被注入到模型中(回复文本、引用、线程历史、转发元数据)。 -默认情况下,OpenClaw 优先保持正常聊天行为,并尽量按接收到的原样保留上下文。这意味着允许列表主要决定谁可以触发操作,而不是对每一段引用或历史片段都进行统一脱敏的边界。 +默认情况下,OpenClaw 优先保证正常聊天行为,并尽量按接收到的原样保留上下文。这意味着允许列表主要决定谁可以触发操作,而不是对每一段引用或历史片段都实行统一脱敏边界。 当前行为因渠道而异: -- 某些渠道已经在特定路径上对补充上下文应用基于发送者的过滤(例如 Slack 线程预载、Matrix 回复/线程查询)。 +- 某些渠道已经在特定路径上对补充上下文应用基于发送者的过滤(例如 Slack 线程种子数据、Matrix 回复/线程查询)。 - 其他渠道仍然会按接收到的原样传递引用/回复/转发上下文。 加固方向(计划中): -- `contextVisibility: "all"`(默认)保持当前“按接收原样处理”的行为。 -- `contextVisibility: "allowlist"` 会将补充上下文过滤为仅限允许列表中的发送者。 -- `contextVisibility: "allowlist_quote"` 等于 `allowlist`,再加上一条显式的引用/回复例外规则。 +- `contextVisibility: "all"`(默认)保持当前按接收原样处理的行为。 +- `contextVisibility: "allowlist"` 会将补充上下文过滤为仅来自允许列表发送者。 +- `contextVisibility: "allowlist_quote"` 等同于 `allowlist`,并额外允许一个显式的引用/回复例外。 -在这一加固模型尚未在所有渠道中一致实现之前,不同界面的行为仍会有所差异。 +在这个加固模型尚未在各渠道中一致实现之前,不同表面之间的行为差异是预期内的。 -![群消息流转](/images/groups-flow.svg) +![群组消息流程](/images/groups-flow.svg) 如果你想要…… -| 目标 | 需要设置什么 | +| 目标 | 应设置内容 | | -------------------------------------------- | ---------------------------------------------------------- | -| 允许所有群组,但只在 @提及时回复 | `groups: { "*": { requireMention: true } }` | +| 允许所有群组,但只在 @ 提及时回复 | `groups: { "*": { requireMention: true } }` | | 禁用所有群组回复 | `groupPolicy: "disabled"` | -| 只允许特定群组 | `groups: { "": { ... } }`(不使用 `"*"` 键) | -| 只有你可以在群组中触发 OpenClaw | `groupPolicy: "allowlist"`, `groupAllowFrom: ["+1555..."]` | +| 仅限特定群组 | `groups: { "": { ... } }`(不使用 `"*"` 键) | +| 只有你可以在群组中触发 | `groupPolicy: "allowlist"`,`groupAllowFrom: ["+1555..."]` | ## 会话键 - 群组会话使用 `agent:::group:` 会话键(房间/频道使用 `agent:::channel:`)。 -- Telegram 论坛主题会在群组 id 后附加 `:topic:`,因此每个主题都有自己的会话。 -- 私聊使用主会话(或在已配置时按发送者分开)。 +- Telegram 论坛话题会在群组 id 后附加 `:topic:`,因此每个话题都有自己的会话。 +- 私聊使用主会话(或按配置使用每发送者单独会话)。 - 群组会话会跳过心跳。 -## 模式:个人私信 + 公开群组(单智能体) +## 模式:个人私信 + 公开群组(单个智能体) -可以——如果你的“个人”流量是**私信**,而“公开”流量是**群组**,这个模式效果很好。 +可以——如果你的“个人”流量是**私信**,而“公开”流量是**群组**,这种方式效果很好。 -原因是:在单智能体模式下,私信通常会进入**主**会话键(`agent:main:main`),而群组始终使用**非主**会话键(`agent:main::group:`)。如果你启用沙箱隔离并设置 `mode: "non-main"`,这些群组会话就会在 Docker 中运行,而你的主私信会话仍然留在主机上运行。 +原因:在单智能体模式下,私信通常会进入**主**会话键(`agent:main:main`),而群组始终使用**非主**会话键(`agent:main::group:`)。如果你启用 `mode: "non-main"` 的沙箱隔离,这些群组会话会在 Docker 中运行,而你的主私信会话则保留在主机上运行。 -这样你就拥有一个智能体“脑”(共享工作区 + 记忆),但两种执行姿态: +这样你就能拥有一个智能体“大脑”(共享工作区 + 记忆),但有两种执行姿态: - **私信**:完整工具(主机) - **群组**:沙箱 + 受限工具(Docker) -> 如果你需要真正独立的工作区/角色(“个人”和“公开”绝不能混在一起),请使用第二个智能体 + 绑定。参见 [Multi-Agent Routing](/zh-CN/concepts/multi-agent)。 +> 如果你需要真正独立的工作区/人格(“个人”和“公开”绝不能混用),请使用第二个智能体 + 绑定。参见 [Multi-Agent Routing](/zh-CN/concepts/multi-agent)。 -示例(私信在主机上,群组使用沙箱隔离且仅允许消息类工具): +示例(私信在主机上运行,群组在沙箱中运行 + 仅消息工具): ```json5 { @@ -123,7 +123,7 @@ otherwise -> reply } ``` -想要实现“群组只能看到文件夹 X”而不是“完全不能访问主机”?保留 `workspaceAccess: "none"`,然后只把允许列表中的路径挂载进沙箱: +如果你想要的是“群组只能看到文件夹 X”,而不是“完全不能访问主机”,请保持 `workspaceAccess: "none"`,并仅将允许列表中的路径挂载到沙箱中: ```json5 { @@ -147,9 +147,9 @@ otherwise -> reply 相关内容: -- 配置键与默认值:[Gateway 配置](/zh-CN/gateway/configuration-reference#agentsdefaultssandbox) -- 调试为什么某个工具被阻止:[沙箱隔离 vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated) -- 绑定挂载详情:[沙箱隔离](/zh-CN/gateway/sandboxing#custom-bind-mounts) +- 配置键和默认值:[Gateway configuration](/zh-CN/gateway/configuration-reference#agentsdefaultssandbox) +- 调试为什么某个工具被阻止:[Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated) +- 绑定挂载详情:[Sandboxing](/zh-CN/gateway/sandboxing#custom-bind-mounts) ## 显示标签 @@ -158,7 +158,7 @@ otherwise -> reply ## 群组策略 -按渠道控制如何处理群组/房间消息: +控制每个渠道如何处理群组/房间消息: ```json5 { @@ -207,34 +207,36 @@ otherwise -> reply | 策略 | 行为 | | ------------- | ------------------------------------------------------------ | -| `"open"` | 群组会绕过允许列表;但提及门控仍然生效。 | +| `"open"` | 群组绕过允许列表;提及门控仍然适用。 | | `"disabled"` | 完全阻止所有群组消息。 | -| `"allowlist"` | 仅允许与已配置允许列表匹配的群组/房间。 | +| `"allowlist"` | 仅允许与配置的允许列表匹配的群组/房间。 | 说明: -- `groupPolicy` 与提及门控是分开的(提及门控要求 @提及)。 -- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo:使用 `groupAllowFrom`(回退:显式 `allowFrom`)。 -- 私信配对审批(`*-allowFrom` 存储项)只适用于私信访问;群组发送者授权仍需要在群组允许列表中显式配置。 +- `groupPolicy` 与提及门控是分开的(后者要求 @ 提及)。 +- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo:使用 `groupAllowFrom`(回退为显式 `allowFrom`)。 +- 私信配对批准(`*-allowFrom` 存储条目)只适用于私信访问;群组发送者授权仍需通过群组允许列表显式配置。 - Discord:允许列表使用 `channels.discord.guilds..channels`。 - Slack:允许列表使用 `channels.slack.channels`。 -- Matrix:允许列表使用 `channels.matrix.groups`。优先使用房间 ID 或别名;已加入房间的名称查询是尽力而为,运行时无法解析的名称会被忽略。使用 `channels.matrix.groupAllowFrom` 来限制发送者;也支持按房间配置的 `users` 允许列表。 +- Matrix:允许列表使用 `channels.matrix.groups`。优先使用房间 ID 或别名;已加入房间的名称查询仅尽力而为,运行时无法解析的名称会被忽略。使用 `channels.matrix.groupAllowFrom` 来限制发送者;也支持按房间配置的 `users` 允许列表。 - 群组私信单独控制(`channels.discord.dm.*`、`channels.slack.dm.*`)。 -- Telegram 允许列表可以匹配用户 ID(`"123456789"`、`"telegram:123456789"`、`"tg:123456789"`)或用户名(`"@alice"` 或 `"alice"`);前缀大小写不敏感。 -- 默认值是 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,群组消息会被阻止。 -- 运行时安全:当某个提供商配置块完全缺失(`channels.` 不存在)时,群组策略会回退到故障关闭模式(通常是 `allowlist`),而不是继承 `channels.defaults.groupPolicy`。 +- Telegram 允许列表可匹配用户 ID(`"123456789"`、`"telegram:123456789"`、`"tg:123456789"`)或用户名(`"@alice"` 或 `"alice"`);前缀大小写不敏感。 +- 默认值是 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,则群组消息会被阻止。 +- 运行时安全:当某个提供商配置块完全缺失时(`channels.` 不存在),群组策略会回退到失效关闭模式(通常是 `allowlist`),而不是继承 `channels.defaults.groupPolicy`。 快速心智模型(群组消息的评估顺序): 1. `groupPolicy`(open/disabled/allowlist) -2. 群组允许列表(`*.groups`、`*.groupAllowFrom`、渠道特定允许列表) +2. 群组允许列表(`*.groups`、`*.groupAllowFrom`、特定渠道允许列表) 3. 提及门控(`requireMention`、`/activation`) ## 提及门控(默认) -群组消息默认需要提及,除非按群组覆盖。默认值按子系统存放在 `*.groups."*"` 下。 +除非按群组覆盖,否则群组消息需要提及。默认值按各子系统存放在 `*.groups."*"` 下。 -回复机器人消息会被视为隐式提及(当渠道支持回复元数据时)。这适用于 Telegram、WhatsApp、Slack、Discord 和 Microsoft Teams。 +回复机器人消息会被视为隐式提及,前提是该渠道支持回复元数据。 +引用机器人消息也可能被视为隐式提及,前提是该渠道公开引用元数据。 +当前内置支持的渠道包括 Telegram、WhatsApp、Slack、Discord、Microsoft Teams 和 ZaloUser。 ```json5 { @@ -275,28 +277,28 @@ otherwise -> reply 说明: - `mentionPatterns` 是大小写不敏感的安全正则模式;无效模式和不安全的嵌套重复形式会被忽略。 -- 提供显式提及的界面仍然会通过;这些模式只是回退方案。 -- 按智能体覆盖:`agents.list[].groupChat.mentionPatterns`(当多个智能体共享一个群组时很有用)。 -- 只有在能够检测提及时,才会强制执行提及门控(原生提及或已配置 `mentionPatterns`)。 -- Discord 默认值位于 `channels.discord.guilds."*"`(可按 guild/channel 覆盖)。 -- 群组历史上下文会在各个渠道中统一包装,并且仅包含**待处理消息**(即因提及门控而跳过的消息);全局默认值使用 `messages.groupChat.historyLimit`,覆盖项使用 `channels..historyLimit`(或 `channels..accounts.*.historyLimit`)。设为 `0` 可禁用。 +- 提供显式提及的表面仍然会通过;这些模式只是回退方案。 +- 按智能体覆盖:`agents.list[].groupChat.mentionPatterns`(多个智能体共享同一群组时很有用)。 +- 只有在可以进行提及检测时,才会强制执行提及门控(原生提及,或已配置 `mentionPatterns`)。 +- Discord 默认值位于 `channels.discord.guilds."*"`(可按 guild/频道覆盖)。 +- 群组历史上下文在各渠道间会被统一包装,并且仅包含**待处理消息**(因提及门控而被跳过的消息);使用 `messages.groupChat.historyLimit` 作为全局默认值,使用 `channels..historyLimit`(或 `channels..accounts.*.historyLimit`)进行覆盖。设为 `0` 可禁用。 ## 群组/频道工具限制(可选) 某些渠道配置支持限制**特定群组/房间/频道内**可用的工具。 -- `tools`:为整个群组允许/拒绝工具。 +- `tools`:对整个群组允许/拒绝工具。 - `toolsBySender`:群组内按发送者覆盖。 使用显式键前缀: `id:`、`e164:`、`username:`、`name:` 和 `"*"` 通配符。 - 旧版无前缀键仍然被接受,但只会按 `id:` 匹配。 + 旧版无前缀键仍然接受,但只会按 `id:` 匹配。 -解析顺序(越具体优先级越高): +解析顺序(越具体越优先): 1. 群组/频道 `toolsBySender` 匹配 2. 群组/频道 `tools` -3. 默认(`"*"`)`toolsBySender` 匹配 -4. 默认(`"*"`)`tools` +3. 默认值(`"*"`)`toolsBySender` 匹配 +4. 默认值(`"*"`)`tools` 示例(Telegram): @@ -320,15 +322,15 @@ otherwise -> reply 说明: -- 群组/频道工具限制是在全局/智能体工具策略之外额外应用的(deny 仍然优先)。 +- 群组/频道工具限制会与全局/智能体工具策略一同应用(拒绝仍然优先)。 - 某些渠道对房间/频道使用不同的嵌套结构(例如 Discord `guilds.*.channels.*`、Slack `channels.*`、Microsoft Teams `teams.*.channels.*`)。 ## 群组允许列表 -当配置了 `channels.whatsapp.groups`、`channels.telegram.groups` 或 `channels.imessage.groups` 时,这些键会充当群组允许列表。使用 `"*"` 可允许所有群组,同时仍然设置默认提及行为。 +配置 `channels.whatsapp.groups`、`channels.telegram.groups` 或 `channels.imessage.groups` 时,这些键会作为群组允许列表。使用 `"*"` 可以允许所有群组,同时仍然设置默认提及行为。 -常见困惑:私信配对审批并不等同于群组授权。 -对于支持私信配对的渠道,配对存储只会解锁私信。群组命令仍然需要通过配置允许列表显式授权群组发送者,例如 `groupAllowFrom` 或该渠道文档说明的回退配置。 +常见混淆:私信配对批准并不等于群组授权。 +对于支持私信配对的渠道,配对存储只会解锁私信。群组命令仍然需要通过配置允许列表显式授权群组发送者,例如 `groupAllowFrom` 或该渠道文档中说明的配置回退项。 常见意图(可直接复制粘贴): @@ -383,12 +385,12 @@ otherwise -> reply ## 激活(仅所有者) -群组所有者可以按群组切换激活模式: +群组所有者可以切换每个群组的激活状态: - `/activation mention` - `/activation always` -所有者由 `channels.whatsapp.allowFrom` 决定(如果未设置,则使用机器人自身的 E.164)。请将命令作为单独一条消息发送。其他界面当前会忽略 `/activation`。 +所有者由 `channels.whatsapp.allowFrom` 决定(未设置时则使用机器人自身的 E.164)。请将命令作为独立消息发送。其他表面当前会忽略 `/activation`。 ## 上下文字段 @@ -398,20 +400,20 @@ otherwise -> reply - `GroupSubject`(如果已知) - `GroupMembers`(如果已知) - `WasMentioned`(提及门控结果) -- Telegram 论坛主题还会包含 `MessageThreadId` 和 `IsForum`。 +- Telegram 论坛话题还会包含 `MessageThreadId` 和 `IsForum` -渠道特定说明: +特定渠道说明: -- BlueBubbles 可以在填充 `GroupMembers` 之前,选择性地从本地 Contacts 数据库中补充未命名的 macOS 群组参与者信息。此功能默认关闭,并且只会在常规群组门控通过后运行。 +- BlueBubbles 可以选择在填充 `GroupMembers` 之前,先从本地联系人数据库中补全未命名的 macOS 群组参与者信息。此功能默认关闭,且只会在正常群组门控通过后运行。 -智能体系统提示会在新群组会话的第一轮加入群组说明。它会提醒模型像人类一样回复、避免使用 Markdown 表格、尽量减少空行、遵循正常聊天间距,并避免输入字面量 `\n` 序列。 +在新群组会话的第一轮中,智能体系统提示词会包含群组介绍。它会提醒模型像人类一样回复、避免使用 Markdown 表格、尽量减少空行、遵循正常聊天间距,并避免输入字面量 `\n` 序列。 ## iMessage 细节 -- 在路由或允许列表中优先使用 `chat_id:`。 +- 在路由或允许列表中,优先使用 `chat_id:`。 - 列出聊天:`imsg chats --limit 20`。 -- 群组回复始终会发回相同的 `chat_id`。 +- 群组回复始终返回到同一个 `chat_id`。 ## WhatsApp 细节 -有关 WhatsApp 专属行为(历史注入、提及处理细节),请参见 [群消息](/zh-CN/channels/group-messages)。 +参见 [Group messages](/zh-CN/channels/group-messages) 了解仅适用于 WhatsApp 的行为(历史注入、提及处理细节)。 diff --git a/docs/zh-CN/channels/zalouser.md b/docs/zh-CN/channels/zalouser.md index 04fc3d7d5..6b188f0fe 100644 --- a/docs/zh-CN/channels/zalouser.md +++ b/docs/zh-CN/channels/zalouser.md @@ -1,45 +1,45 @@ --- read_when: - - 为 OpenClaw 设置 Zalo Personal - - 调试 Zalo Personal 登录或消息流 -summary: 通过原生 `zca-js`(二维码登录)提供 Zalo 个人账号支持,以及相关能力和配置 -title: Zalo Personal + - 为 OpenClaw 设置 Zalo 个人版 + - 调试 Zalo 个人版登录或消息流程 +summary: 通过原生 `zca-js`(二维码登录)提供 Zalo 个人账号支持、能力和配置 +title: Zalo 个人版 x-i18n: - generated_at: "2026-04-05T08:18:17Z" + generated_at: "2026-04-07T06:53:05Z" model: gpt-5.4 provider: openai - source_hash: 331b95041463185472d242cb0a944972f0a8e99df8120bda6350eca86ad5963f + source_hash: 08f50edb2f4c6fe24972efe5e321f5fd0572c7d29af5c1db808151c7c943dc66 source_path: channels/zalouser.md workflow: 15 --- -# Zalo Personal(非官方) +# Zalo 个人版(非官方) 状态:实验性。此集成通过 OpenClaw 内部的原生 `zca-js` 自动化一个 **Zalo 个人账号**。 -> **警告:** 这是一个非官方集成,可能会导致账号被暂停或封禁。请自行承担使用风险。 +> **警告:** 这是一个非官方集成,可能会导致账号被暂停或封禁。使用风险由你自行承担。 ## 内置插件 -Zalo Personal 作为当前 OpenClaw 版本中的内置插件提供,因此普通打包构建无需单独安装。 +Zalo 个人版作为当前 OpenClaw 版本中的内置插件提供,因此常规打包构建无需单独安装。 -如果你使用的是较旧版本,或是不包含 Zalo Personal 的自定义安装,请手动安装: +如果你使用的是较旧版本,或排除了 Zalo 个人版的自定义安装,请手动安装: - 通过 CLI 安装:`openclaw plugins install @openclaw/zalouser` - 或从源码检出安装:`openclaw plugins install ./path/to/local/zalouser-plugin` -- 详情:[插件](/tools/plugin) +- 详情:[插件](/zh-CN/tools/plugin) -不需要额外的 `zca`/`openzca` CLI 二进制文件。 +不需要外部 `zca`/`openzca` CLI 二进制文件。 ## 快速设置(新手) -1. 确保 Zalo Personal 插件可用。 +1. 确保 Zalo 个人版插件可用。 - 当前打包的 OpenClaw 版本已内置该插件。 - - 较旧版本或自定义安装可使用上面的命令手动添加。 + - 较旧版本或自定义安装可使用上述命令手动添加。 2. 登录(二维码,在 Gateway 网关机器上): - `openclaw channels login --channel zalouser` - 使用 Zalo 移动应用扫描二维码。 -3. 启用渠道: +3. 启用该渠道: ```json5 { @@ -57,14 +57,14 @@ Zalo Personal 作为当前 OpenClaw 版本中的内置插件提供,因此普 ## 它是什么 -- 通过 `zca-js` 完全在进程内运行。 +- 完全通过 `zca-js` 在进程内运行。 - 使用原生事件监听器接收入站消息。 - 通过 JS API 直接发送回复(文本/媒体/链接)。 -- 面向无法使用 Zalo Bot API 的“个人账号”使用场景而设计。 +- 适用于无法使用 Zalo Bot API 的“个人账号”场景。 ## 命名 -渠道 id 为 `zalouser`,以明确表示这是在自动化一个 **Zalo 个人用户账号**(非官方)。我们保留 `zalo`,用于未来可能推出的官方 Zalo API 集成。 +渠道 ID 为 `zalouser`,以明确表示这是对 **Zalo 个人用户账号** 的自动化(非官方)。我们保留 `zalo`,供未来可能推出的官方 Zalo API 集成使用。 ## 查找 ID(目录) @@ -78,34 +78,34 @@ openclaw directory groups list --channel zalouser --query "work" ## 限制 -- 出站文本会被分块到约 2000 个字符(Zalo 客户端限制)。 +- 出站文本会被分块为约 2000 个字符(Zalo 客户端限制)。 - 默认阻止流式传输。 ## 访问控制(私信) `channels.zalouser.dmPolicy` 支持:`pairing | allowlist | open | disabled`(默认:`pairing`)。 -`channels.zalouser.allowFrom` 接受用户 ID 或名称。在设置期间,会使用插件的进程内联系人查询将名称解析为 ID。 +`channels.zalouser.allowFrom` 接受用户 ID 或名称。设置期间,名称会通过插件的进程内联系人查找解析为 ID。 -通过以下命令批准: +可通过以下命令批准: - `openclaw pairing list zalouser` - `openclaw pairing approve zalouser ` ## 群组访问(可选) -- 默认:`channels.zalouser.groupPolicy = "open"`(允许群组)。未设置时,可使用 `channels.defaults.groupPolicy` 覆盖默认值。 +- 默认:`channels.zalouser.groupPolicy = "open"`(允许群组)。当未设置时,使用 `channels.defaults.groupPolicy` 覆盖默认值。 - 使用以下配置限制为允许列表: - `channels.zalouser.groupPolicy = "allowlist"` - - `channels.zalouser.groups`(键应为稳定的群组 ID;如果可能,启动时会将名称解析为 ID) - - `channels.zalouser.groupAllowFrom`(控制允许群组中哪些发送者可以触发机器人) + - `channels.zalouser.groups`(键应为稳定的群组 ID;如有可能,名称会在启动时解析为 ID) + - `channels.zalouser.groupAllowFrom`(控制允许的群组中哪些发送者可以触发机器人) - 阻止所有群组:`channels.zalouser.groupPolicy = "disabled"`。 -- 配置向导可以提示你设置群组允许列表。 -- 启动时,OpenClaw 会将允许列表中的群组/用户名称解析为 ID,并记录映射。 -- 默认情况下,群组允许列表匹配仅基于 ID。除非启用 `channels.zalouser.dangerouslyAllowNameMatching: true`,否则无法解析的名称会在鉴权时被忽略。 -- `channels.zalouser.dangerouslyAllowNameMatching: true` 是一种紧急兼容模式,会重新启用可变群组名称匹配。 -- 如果未设置 `groupAllowFrom`,运行时会回退到 `allowFrom` 进行群组发送者检查。 -- 发送者检查同时适用于普通群组消息和控制命令(例如 `/new`、`/reset`)。 +- 配置向导可以提示输入群组允许列表。 +- 启动时,OpenClaw 会将允许列表中的群组/用户名称解析为 ID,并记录映射关系。 +- 默认情况下,群组允许列表匹配仅基于 ID。未解析的名称会在鉴权时被忽略,除非启用 `channels.zalouser.dangerouslyAllowNameMatching: true`。 +- `channels.zalouser.dangerouslyAllowNameMatching: true` 是一种破玻璃兼容模式,会重新启用可变的群组名称匹配。 +- 如果未设置 `groupAllowFrom`,运行时会回退到 `allowFrom` 用于群组发送者检查。 +- 发送者检查同时适用于普通群消息和控制命令(例如 `/new`、`/reset`)。 示例: @@ -126,12 +126,13 @@ openclaw directory groups list --channel zalouser --query "work" ### 群组提及门控 -- `channels.zalouser.groups..requireMention` 控制群组回复是否需要提及。 -- 解析顺序:精确群组 id/名称 -> 标准化群组 slug -> `*` -> 默认值(`true`)。 -- 这同时适用于允许列表中的群组和开放群组模式。 +- `channels.zalouser.groups..requireMention` 控制群组回复是否必须被提及。 +- 解析顺序:精确群组 id/名称 -> 规范化群组 slug -> `*` -> 默认值(`true`)。 +- 这同时适用于允许列表群组和开放群组模式。 +- 引用一条机器人消息会被视为用于激活群组的隐式提及。 - 已授权的控制命令(例如 `/new`)可以绕过提及门控。 -- 当群组消息因需要提及而被跳过时,OpenClaw 会将其存储为待处理的群组历史,并在下一条被处理的群组消息中包含这些内容。 -- 群组历史上限默认使用 `messages.groupChat.historyLimit`(回退值为 `50`)。你可以通过 `channels.zalouser.historyLimit` 为每个账号覆盖此设置。 +- 当群消息因需要提及而被跳过时,OpenClaw 会将其存储为待处理的群组历史,并在下一条被处理的群消息中包含它。 +- 群组历史记录限制默认使用 `messages.groupChat.historyLimit`(回退值为 `50`)。你可以通过 `channels.zalouser.historyLimit` 为每个账号单独覆盖。 示例: @@ -167,13 +168,13 @@ openclaw directory groups list --channel zalouser --query "work" } ``` -## 正在输入、反应和送达确认 +## 正在输入、表情回应和送达确认 -- OpenClaw 会在发送回复前发送“正在输入”事件(尽力而为)。 -- 渠道操作中,`zalouser` 支持消息反应动作 `react`。 - - 使用 `remove: true` 可从消息中移除指定的反应表情。 - - 反应语义:[反应](/tools/reactions) -- 对于包含事件元数据的入站消息,OpenClaw 会发送已送达 + 已查看确认(尽力而为)。 +- OpenClaw 会在分发回复前发送一个正在输入事件(尽力而为)。 +- 消息表情回应动作 `react` 在渠道动作中受 `zalouser` 支持。 + - 使用 `remove: true` 从消息中移除特定的表情回应 emoji。 + - 表情回应语义:[表情回应](/zh-CN/tools/reactions) +- 对于包含事件元数据的入站消息,OpenClaw 会发送送达 + 已读确认(尽力而为)。 ## 故障排除 @@ -188,13 +189,13 @@ openclaw directory groups list --channel zalouser --query "work" **从旧版基于 CLI 的设置升级:** -- 删除任何关于旧外部 `zca` 进程的假设。 +- 移除任何关于旧外部 `zca` 进程的假设。 - 该渠道现在完全在 OpenClaw 内运行,无需外部 CLI 二进制文件。 ## 相关内容 -- [渠道概览](/channels) — 所有支持的渠道 -- [配对](/channels/pairing) — 私信身份验证和配对流程 -- [群组](/channels/groups) — 群聊行为和提及门控 -- [渠道路由](/channels/channel-routing) — 消息的会话路由 -- [安全](/gateway/security) — 访问模型和加固 +- [渠道概览](/zh-CN/channels) — 所有受支持的渠道 +- [配对](/zh-CN/channels/pairing) — 私信身份验证和配对流程 +- [群组](/zh-CN/channels/groups) — 群聊行为和提及门控 +- [渠道路由](/zh-CN/channels/channel-routing) — 消息的会话路由 +- [安全性](/zh-CN/gateway/security) — 访问模型和加固 diff --git a/docs/zh-CN/plugins/architecture.md b/docs/zh-CN/plugins/architecture.md index 9e05289d4..e760a8ccc 100644 --- a/docs/zh-CN/plugins/architecture.md +++ b/docs/zh-CN/plugins/architecture.md @@ -1,17 +1,17 @@ --- read_when: - - 构建或调试原生 OpenClaw 插件时 - - 了解插件能力模型或所有权边界时 - - 处理插件加载流水线或注册表时 - - 实现提供商运行时钩子或渠道插件时 + - 构建或调试原生 OpenClaw 插件 + - 理解插件能力模型或归属边界 + - 处理插件加载流水线或注册表 + - 实现 provider 运行时 hook 或渠道插件 sidebarTitle: Internals -summary: 插件内部机制:能力模型、所有权、契约、加载流水线和运行时辅助工具 +summary: 插件内部机制:能力模型、归属、契约、加载流水线和运行时辅助工具 title: 插件内部机制 x-i18n: - generated_at: "2026-04-06T18:58:18Z" + generated_at: "2026-04-07T06:56:52Z" model: gpt-5.4 provider: openai - source_hash: 9c4b0602df12965a29881eab33b0885f991aeefa2a3fdf3cefc1a7770d6dabe0 + source_hash: ba93f0a748e46ac7c7b9d10d78260e6e13b6e533d85a0b56f3c1ffa8ee5a3850 source_path: plugins/architecture.md workflow: 15 --- @@ -19,166 +19,131 @@ x-i18n: # 插件内部机制 - 这是**深度架构参考**。如需实用指南,请参阅: + 这是**深度架构参考**。实用指南请参见: - [安装并使用插件](/zh-CN/tools/plugin) — 用户指南 - [入门指南](/zh-CN/plugins/building-plugins) — 第一个插件教程 - - [渠道插件](/zh-CN/plugins/sdk-channel-plugins) — 构建一个消息渠道 - - [提供商插件](/zh-CN/plugins/sdk-provider-plugins) — 构建一个模型提供商 + - [渠道插件](/zh-CN/plugins/sdk-channel-plugins) — 构建消息渠道 + - [提供商插件](/zh-CN/plugins/sdk-provider-plugins) — 构建模型提供商 - [SDK 概览](/zh-CN/plugins/sdk-overview) — 导入映射和注册 API -本页介绍 OpenClaw 插件系统的内部架构。 +本页面介绍 OpenClaw 插件系统的内部架构。 ## 公共能力模型 -能力是 OpenClaw 内部公共的**原生插件**模型。每个 -原生 OpenClaw 插件都会针对一个或多个能力类型进行注册: +能力是 OpenClaw 内部公开的**原生插件**模型。每个原生 OpenClaw 插件都会注册到一种或多种能力类型: -| 能力 | 注册方式 | 示例插件 | -| -------------------- | ---------------------------------------------- | ------------------------------------ | -| 文本推理 | `api.registerProvider(...)` | `openai`, `anthropic` | -| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`, `anthropic` | -| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | -| 实时转录 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | -| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | `openai` | -| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | -| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | -| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | -| 视频生成 | `api.registerVideoGenerationProvider(...)` | `qwen` | -| Web 抓取 | `api.registerWebFetchProvider(...)` | `firecrawl` | -| Web 搜索 | `api.registerWebSearchProvider(...)` | `google` | -| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`, `matrix` | +| 能力 | 注册方法 | 示例插件 | +| ---------------------- | ------------------------------------------------ | ------------------------------------ | +| 文本推理 | `api.registerProvider(...)` | `openai`, `anthropic` | +| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`, `anthropic` | +| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | +| 实时转写 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | +| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | `openai` | +| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | +| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | +| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | +| 视频生成 | `api.registerVideoGenerationProvider(...)` | `qwen` | +| Web 抓取 | `api.registerWebFetchProvider(...)` | `firecrawl` | +| Web 搜索 | `api.registerWebSearchProvider(...)` | `google` | +| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`, `matrix` | -一个注册了零个能力、但提供钩子、工具或服务的插件, -属于**仅钩子旧式**插件。该模式仍然被完全支持。 +一个注册了零能力、但提供 hooks、工具或服务的插件,是一种**仅遗留 hook** 插件。这种模式仍然受到完整支持。 ### 外部兼容性立场 -能力模型已经在核心中落地,并且今天已被内置/原生插件使用, -但外部插件兼容性仍然需要比“它已导出,因此它已冻结” -更严格的标准。 +能力模型已经落地到 core 中,并且如今已被内置/原生插件使用,但外部插件兼容性仍需要比“它已导出,因此它已冻结”更严格的标准。 -当前指引: +当前指导原则: -- **现有外部插件:** 保持基于钩子的集成继续工作;把这视为 - 兼容性基线 -- **新的内置/原生插件:** 优先使用显式能力注册,而不是 - 面向供应商的直接内部访问或新的仅钩子设计 -- **采用能力注册的外部插件:** 允许这样做,但除非文档明确将某个契约标记为稳定, - 否则应将能力专用辅助接口视为仍在演进中 +- **现有外部插件:** 保持基于 hook 的集成正常工作;将其视为兼容性基线 +- **新的内置/原生插件:** 优先使用显式能力注册,而不是 vendor 专用的内部接入或新的仅 hook 设计 +- **采用能力注册的外部插件:** 可以,但应将各能力专用的辅助工具 surface 视为仍在演进,除非文档明确将某个契约标记为稳定 -实践规则: +实用规则: -- 能力注册 API 是预期的发展方向 -- 在过渡期间,旧式钩子仍然是外部插件最稳妥、最不易破坏的路径 -- 并非所有导出的辅助子路径都同等稳定;应优先使用范围更窄、已文档化的契约, - 而不是偶然暴露出来的辅助导出 +- 能力注册 API 是预期方向 +- 在过渡期间,遗留 hooks 仍然是对外部插件最安全、最不容易破坏兼容性的路径 +- 导出的辅助工具子路径并不完全等价;优先使用文档说明的窄契约,而不是偶然导出的辅助工具 ### 插件形态 -OpenClaw 会根据插件的实际注册行为,而不是仅根据静态元数据, -将每个已加载插件归类为一种形态: +OpenClaw 会根据每个已加载插件的实际注册行为,而不是仅根据静态元数据,将其归类为一种形态: -- **plain-capability** —— 只注册一种能力类型(例如 - 仅提供商插件 `mistral`) -- **hybrid-capability** —— 注册多种能力类型(例如 - `openai` 同时拥有文本推理、语音、媒体理解和图像 - 生成功能) -- **hook-only** —— 只注册钩子(类型化或自定义),没有能力、 - 工具、命令或服务 -- **non-capability** —— 注册工具、命令、服务或路由,但不注册 - 能力 +- **plain-capability** —— 恰好注册一种能力类型(例如仅 provider 的插件 `mistral`) +- **hybrid-capability** —— 注册多种能力类型(例如 `openai` 同时拥有文本推理、语音、媒体理解和图像生成) +- **hook-only** —— 只注册 hooks(typed 或 custom),不注册能力、工具、命令或服务 +- **non-capability** —— 注册工具、命令、服务或路由,但不注册能力 -使用 `openclaw plugins inspect ` 可查看插件的形态和能力 -细分。详见 [CLI 设置参考](/cli/plugins#inspect)。 +使用 `openclaw plugins inspect ` 可查看插件的形态和能力明细。详情请参见 [CLI 参考](/cli/plugins#inspect)。 -### 旧式钩子 +### 遗留 hooks -`before_agent_start` 钩子仍然作为仅钩子插件的兼容路径被支持。 -现实中的旧插件仍然依赖它。 +`before_agent_start` hook 仍作为仅 hook 插件的兼容路径被支持。现实中的遗留插件仍然依赖它。 方向: -- 保持其正常工作 -- 将其文档化为旧式能力 -- 模型/提供商覆盖工作优先使用 `before_model_resolve` -- Prompt 变更工作优先使用 `before_prompt_build` -- 仅在真实使用量下降且夹具覆盖证明迁移安全后才移除 +- 保持可用 +- 在文档中标记为遗留 +- 对模型/provider 覆盖工作,优先使用 `before_model_resolve` +- 对提示词变更工作,优先使用 `before_prompt_build` +- 仅在真实使用量下降且 fixture 覆盖证明迁移安全后再移除 ### 兼容性信号 -当你运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,可能会看到 -以下标签之一: +当你运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,可能会看到以下标签之一: -| 信号 | 含义 | -| ------------------------ | ------------------------------------------------------------ | -| **config valid** | 配置解析正常,插件可正常解析 | -| **compatibility advisory** | 插件使用的是受支持但较旧的模式(例如 `hook-only`) | -| **legacy warning** | 插件使用了 `before_agent_start`,该能力已弃用 | -| **hard error** | 配置无效或插件加载失败 | +| 信号 | 含义 | +| -------------------------- | ------------------------------------------------------------ | +| **config valid** | 配置解析正常,插件也能正确解析 | +| **compatibility advisory** | 插件使用了受支持但较旧的模式(例如 `hook-only`) | +| **legacy warning** | 插件使用了 `before_agent_start`,该能力已弃用 | +| **hard error** | 配置无效或插件加载失败 | -当前 `hook-only` 和 `before_agent_start` 都不会导致你的插件失效—— -`hook-only` 只是提示性信息,而 `before_agent_start` 只会触发警告。这些 -信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。 +`hook-only` 和 `before_agent_start` 如今都不会破坏你的插件——`hook-only` 只是提示性建议,而 `before_agent_start` 仅会触发警告。这些信号也会显示在 `openclaw status --all` 和 `openclaw plugins doctor` 中。 ## 架构概览 OpenClaw 的插件系统有四层: -1. **清单 + 发现** - OpenClaw 从已配置路径、工作区根目录、 - 全局扩展根目录和内置扩展中查找候选插件。发现阶段会先读取原生 - `openclaw.plugin.json` 清单以及受支持的 bundle 清单。 -2. **启用 + 校验** - 核心决定发现到的插件是已启用、已禁用、已阻止,还是 - 被选入某个独占槽位,例如 memory。 +1. **Manifest + 设备发现** + OpenClaw 会从已配置路径、工作区根目录、全局扩展根目录和内置扩展中查找候选插件。设备发现会先读取原生 `openclaw.plugin.json` manifest,以及受支持 bundle 的 manifest。 +2. **启用 + 验证** + Core 决定一个已发现的插件是启用、禁用、阻止,还是被选中用于某个独占槽位(例如 memory)。 3. **运行时加载** - 原生 OpenClaw 插件通过 jiti 在进程内加载,并将 - 能力注册到中央注册表中。兼容 bundle 会被规范化为 - 注册表记录,而无需导入运行时代码。 -4. **表面消费** - OpenClaw 的其余部分会读取注册表,以暴露工具、渠道、提供商 - 设置、钩子、HTTP 路由、CLI 命令和服务。 + 原生 OpenClaw 插件通过 jiti 在进程内加载,并将能力注册到中央注册表。兼容 bundle 会被标准化为注册表记录,而无需导入运行时代码。 +4. **Surface 消费** + OpenClaw 的其余部分会读取注册表,以暴露工具、渠道、provider 设置、hooks、HTTP 路由、CLI 命令和服务。 -对于插件 CLI,根命令发现专门分为两个阶段: +对于插件 CLI,根命令设备发现专门分为两个阶段: -- 解析时元数据来自 `registerCli(..., { descriptors: [...] })` -- 真正的插件 CLI 模块可以保持懒加载,并在首次调用时再注册 +- 解析期元数据来自 `registerCli(..., { descriptors: [...] })` +- 真正的插件 CLI 模块可以保持惰性加载,并在首次调用时注册 -这样既能让插件自有的 CLI 代码留在插件内部,又能让 OpenClaw -在解析前预留根命令名称。 +这样既能让插件自有的 CLI 代码保留在插件内部,又能让 OpenClaw 在解析前预留根命令名称。 -重要设计边界: +关键设计边界: -- 发现 + 配置校验应当只依赖**清单/模式元数据** - 就能工作,而无需执行插件代码 +- 设备发现 + 配置验证应当能够仅基于 **manifest/schema 元数据** 完成,而无需执行插件代码 - 原生运行时行为来自插件模块的 `register(api)` 路径 -这种拆分让 OpenClaw 能在完整运行时尚未激活前,就完成配置校验、 -解释缺失/禁用插件,并构建 UI/模式提示。 +这种拆分让 OpenClaw 能在完整运行时尚未激活之前,就验证配置、解释插件缺失/禁用原因,并构建 UI/schema 提示。 -### 渠道插件与共享 message 工具 +### 渠道插件和共享 message 工具 -对于常规聊天操作,渠道插件不需要单独注册发送/编辑/反应工具。 -OpenClaw 在核心中保留一个共享的 `message` 工具,而 -渠道插件拥有其背后的渠道专用发现与执行逻辑。 +对于常规聊天动作,渠道插件不需要单独注册发送/编辑/响应工具。OpenClaw 在 core 中保留一个共享的 `message` 工具,而渠道插件则拥有其背后的渠道专用设备发现与执行逻辑。 当前边界如下: -- 核心拥有共享 `message` 工具宿主、Prompt 接线、会话/线程 - 账务跟踪以及执行分发 -- 渠道插件拥有作用域化动作发现、能力发现以及任何 - 渠道专用模式片段 -- 渠道插件拥有提供商专属的会话对话语法,例如 - 对话 id 如何编码线程 id,或如何从父对话继承 +- core 拥有共享 `message` 工具宿主、提示词接线、session/thread 记录和执行分发 +- 渠道插件拥有作用域动作设备发现、能力设备发现以及所有渠道专用 schema 片段 +- 渠道插件拥有 provider 专用的 session 会话语法,例如会话 id 如何编码 thread id,或如何从父会话继承 - 渠道插件通过其动作适配器执行最终动作 -对于渠道插件,SDK 表面是 -`ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现 -调用允许插件将其可见动作、能力以及模式贡献一并返回, -从而避免这些部分彼此漂移。 +对于渠道插件,SDK surface 是 +`ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的设备发现调用允许插件将可见动作、能力和 schema 贡献一起返回,从而避免这些部分彼此漂移。 -核心会把运行时作用域传入该发现步骤。重要字段包括: +Core 会将运行时作用域传入这个设备发现步骤。重要字段包括: - `accountId` - `currentChannelId` @@ -187,127 +152,87 @@ OpenClaw 在核心中保留一个共享的 `message` 工具,而 - `sessionKey` - `sessionId` - `agentId` -- 受信任的入站 `requesterSenderId` +- 可信入站 `requesterSenderId` -这对于上下文敏感插件很重要。一个渠道可以根据当前活跃账户、 -当前房间/线程/消息,或受信任的请求者身份来隐藏或暴露 -消息动作,而无需在核心 `message` 工具中硬编码 -渠道专用分支。 +这对上下文敏感的插件很重要。一个渠道可以根据当前活跃账户、当前房间/thread/message,或可信请求者身份,来隐藏或暴露消息动作,而无需在 core `message` 工具中硬编码渠道专用分支。 -这也是为什么嵌入式 runner 路由变更仍然属于插件工作:runner -负责把当前聊天/会话身份转发到插件发现边界, -这样共享的 `message` 工具才能为当前回合暴露正确的、由渠道拥有的 -表面。 +这也是为什么嵌入式 runner 路由变更仍然属于插件工作:runner 负责把当前聊天/session 身份转发到插件设备发现边界,以便共享的 `message` 工具为当前轮次暴露正确的渠道自有 surface。 -对于渠道自有的执行辅助工具,内置插件应将执行 -运行时保留在其自己的扩展模块中。核心不再拥有位于 -`src/agents/tools` 下的 Discord、Slack、Telegram 或 WhatsApp -消息动作运行时。 -我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置 -插件应直接从其扩展自有模块中导入本地运行时代码。 +对于渠道自有的执行辅助工具,内置插件应将执行运行时保留在自己的扩展模块中。Core 不再拥有位于 `src/agents/tools` 下的 Discord、Slack、Telegram 或 WhatsApp 消息动作运行时。我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置插件应直接从其扩展自有模块导入本地运行时代码。 -同样的边界也适用于一般意义上的提供商命名 SDK 接缝:核心 -不应导入面向 Slack、Discord、Signal、 -WhatsApp 或类似扩展的渠道专用便捷 barrel。如果核心需要某种行为, -要么消费该内置插件自己的 `api.ts` / `runtime-api.ts` barrel, -要么将该需求提升为共享 SDK 中一个范围更窄的通用能力。 +同样的边界也适用于一般性的 provider 命名 SDK seam:core 不应导入面向 Slack、Discord、Signal、WhatsApp 或类似扩展的渠道专用便捷 barrel。如果 core 需要某种行为,要么消费该内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么把需求提升为共享 SDK 中的窄型通用能力。 -对于投票,具体有两条执行路径: +对投票而言,目前有两条执行路径: -- `outbound.sendPoll` 是适用于符合通用 - 投票模型的渠道的共享基线 -- `actions.handleAction("poll")` 是处理渠道专用 - 投票语义或额外投票参数的首选路径 +- `outbound.sendPoll` 是适用于符合通用投票模型渠道的共享基线 +- `actions.handleAction("poll")` 是更推荐的路径,用于渠道专用投票语义或额外投票参数 -现在,核心会在插件投票分发拒绝该动作之后,才继续共享投票解析, -因此插件自有的投票处理器可以接受渠道专用投票字段, -而不会先被通用投票解析器阻挡。 +现在,core 会先等待插件投票分发拒绝该动作之后,才进行共享投票解析,这样插件自有的投票处理器就可以接受渠道专用投票字段,而不会先被通用投票解析器拦住。 -完整启动顺序见[加载流水线](#load-pipeline)。 +完整启动顺序请参见 [加载流水线](#load-pipeline)。 -## 能力所有权模型 +## 能力归属模型 -OpenClaw 将原生插件视为**公司**或**功能**的所有权边界, -而不是一堆互不相关集成的集合。 +OpenClaw 将原生插件视为**公司**或**功能**的归属边界,而不是杂乱无章的一堆无关集成。 这意味着: -- 一个公司插件通常应拥有该公司的所有 OpenClaw 对外 - 表面 -- 一个功能插件通常应拥有它引入的完整功能表面 -- 渠道应消费共享核心能力,而不是临时重复实现 - 提供商行为 +- 一个公司插件通常应拥有该公司的所有 OpenClaw 对接 surface +- 一个功能插件通常应拥有它引入的完整功能 surface +- 渠道应消费共享 core 能力,而不是临时重新实现 provider 行为 -例如: +示例: -- 内置 `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 文本 provider 行为,以及媒体理解和视频生成行为 +- `voice-call` 插件是一个功能插件:它拥有通话传输、工具、CLI、路由和 Twilio media-stream bridge,但它会消费共享的语音、实时转写和实时语音能力,而不是直接导入 vendor 插件 -预期的最终状态是: +预期最终状态是: -- OpenAI 保持在一个插件内,即使它横跨文本模型、语音、图像以及 - 未来的视频 -- 其他供应商也可以对自己的表面区域采用同样做法 -- 渠道不关心哪个供应商插件拥有该提供商;它们只消费由核心暴露的 - 共享能力契约 +- OpenAI 保持在一个插件中,即使它横跨文本模型、语音、图像和未来的视频 +- 其他 vendor 也可以用同样方式管理自己的 surface area +- 渠道不需要关心哪个 vendor 插件拥有该 provider;它们只消费 core 暴露的共享能力契约 -这正是关键区别: +这就是关键区别: -- **plugin** = 所有权边界 -- **capability** = 多个插件可实现或消费的核心契约 +- **plugin** = 归属边界 +- **capability** = 可由多个插件实现或消费的 core 契约 -因此,如果 OpenClaw 增加一个新领域,比如视频, -第一个问题不应是 -“哪个提供商应该硬编码视频处理?”而应是 -“核心的视频能力契约是什么?”一旦该契约存在, -供应商插件就可以针对它注册,渠道/功能插件也可以消费它。 +所以,如果 OpenClaw 增加一个新领域,比如视频,首要问题不是“应该由哪个 provider 硬编码视频处理?”而是“core 的视频能力契约应当是什么?”一旦该契约存在,vendor 插件就可以对其进行注册,而渠道/功能插件也可以消费它。 -如果该能力尚不存在,通常正确的做法是: +如果这个能力还不存在,通常正确的做法是: -1. 在核心中定义缺失的能力 -2. 通过插件 API/运行时以类型化方式公开它 -3. 让渠道/功能围绕该能力进行接线 -4. 允许供应商插件注册实现 +1. 在 core 中定义缺失的能力 +2. 通过类型化方式把它暴露到插件 API/运行时 +3. 让渠道/功能围绕这个能力接线 +4. 让 vendor 插件注册实现 -这样既能保持所有权明确,又能避免核心行为依赖某个 -单一供应商或某条一次性的插件专用代码路径。 +这样既能保持归属清晰,也能避免 core 行为依赖单一 vendor 或一次性的插件专用代码路径。 ### 能力分层 -在决定代码应该放在哪里时,可使用以下心智模型: +在决定代码应当放在哪里时,可以使用这个心智模型: -- **核心能力层**:共享编排、策略、回退、配置 - 合并规则、交付语义和类型化契约 -- **供应商插件层**:供应商专用 API、认证、模型目录、语音 - 合成、图像生成、未来视频后端、用量端点 -- **渠道/功能插件层**:Slack/Discord/voice-call 等集成, - 它们消费核心能力并将其呈现在某个表面上 +- **core 能力层**:共享编排、策略、回退、配置合并规则、交付语义和类型化契约 +- **vendor 插件层**:vendor 专用 API、认证、模型目录、语音合成、图像生成、未来视频后端、用量端点 +- **渠道/功能插件层**:Slack/Discord/voice-call 等集成,它们消费 core 能力并将其呈现到某个 surface 上 -例如,TTS 遵循这种形态: +例如,TTS 采用如下结构: -- 核心拥有回复时 TTS 策略、回退顺序、偏好设置和渠道交付 +- core 拥有回复时 TTS 策略、回退顺序、偏好和渠道交付 - `openai`、`elevenlabs` 和 `microsoft` 拥有合成实现 -- `voice-call` 消费电话 TTS 运行时辅助工具 +- `voice-call` 消费电话场景的 TTS 运行时辅助工具 -未来的能力也应优先遵循同样模式。 +未来能力也应优先遵循同样模式。 ### 多能力公司插件示例 -一个公司插件从外部看应该是连贯统一的。如果 OpenClaw 具有用于模型、 -语音、实时转录、实时语音、媒体理解、图像生成、视频生成、Web 抓取和 Web 搜索的共享 -契约,那么一个供应商可以在一个地方拥有它的全部表面: +一个公司插件从外部看来应当是内聚的。如果 OpenClaw 具备模型、语音、实时转写、实时语音、媒体理解、图像生成、视频生成、Web 抓取和 Web 搜索等共享契约,一个 vendor 就可以在一个地方拥有其所有 surface: ```ts import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry"; @@ -361,179 +286,148 @@ const plugin: OpenClawPluginDefinition = { export default plugin; ``` -重要的不是确切的辅助工具名称,而是这种形态: +重点不在于具体辅助工具名称。关键在于这种结构: -- 一个插件拥有该供应商表面 -- 核心仍然拥有能力契约 -- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是供应商代码 -- 契约测试可以断言插件注册了它所声称拥有的那些能力 +- 一个插件拥有 vendor surface +- core 仍拥有能力契约 +- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是 vendor 代码 +- 契约测试可以断言插件确实注册了它声称拥有的能力 ### 能力示例:视频理解 -OpenClaw 已经将图像/音频/视频理解视为一种共享 -能力。相同的所有权模型也适用于这里: +OpenClaw 已经将图像/音频/视频理解视为一种共享能力。这里同样适用相同的归属模型: -1. 核心定义媒体理解契约 -2. 供应商插件按需注册 `describeImage`、`transcribeAudio` 和 - `describeVideo` -3. 渠道和功能插件消费共享核心行为,而不是 - 直接连到供应商代码 +1. core 定义媒体理解契约 +2. vendor 插件按需注册 `describeImage`、`transcribeAudio` 和 `describeVideo` +3. 渠道和功能插件消费共享的 core 行为,而不是直接接到 vendor 代码 -这避免了把某个提供商对视频的假设硬编码进核心。插件拥有 -供应商表面;核心拥有能力契约和回退行为。 +这样可以避免把某个 provider 的视频假设烘焙进 core 中。插件拥有 vendor surface;core 拥有能力契约和回退行为。 -视频生成也已经遵循相同顺序:核心拥有类型化的 -能力契约和运行时辅助工具,供应商插件通过 -`api.registerVideoGenerationProvider(...)` 注册实现。 +视频生成已经使用同样的顺序:core 拥有类型化的能力契约和运行时辅助工具,而 vendor 插件则针对它注册 `api.registerVideoGenerationProvider(...)` 实现。 -需要一个具体的发布检查清单?请参阅 +需要一个具体的发布清单?请参见 [能力扩展手册](/zh-CN/plugins/architecture)。 -## 契约与约束 +## 契约与约束执行 -插件 API 表面刻意采用类型化设计,并集中定义在 -`OpenClawPluginApi` 中。该契约定义了受支持的注册点,以及 -插件可以依赖的运行时辅助工具。 +插件 API surface 被有意设计为类型化,并集中在 +`OpenClawPluginApi` 中。这个契约定义了受支持的注册点,以及插件可以依赖的运行时辅助工具。 -其重要性在于: +这很重要,原因如下: -- 插件作者获得一个稳定的内部标准 -- 核心可以拒绝重复所有权,例如两个插件注册相同的 - provider id -- 启动时可以为格式错误的注册暴露可操作的诊断信息 -- 契约测试可以强制内置插件的所有权,并防止无声漂移 +- 插件作者可以获得一个稳定的内部标准 +- core 可以拒绝重复归属,例如两个插件注册相同的 provider id +- 启动时可以为格式错误的注册提供可执行的诊断 +- 契约测试可以强制约束内置插件的归属,并防止静默漂移 -有两层约束: +有两层约束执行: -1. **运行时注册约束** - 插件注册表会在插件加载时校验注册内容。例如: - 重复的 provider id、重复的语音 provider id,以及格式错误的 - 注册,都会生成插件诊断,而不是导致未定义行为。 +1. **运行时注册约束执行** + 插件注册表在插件加载时验证各项注册。例如:重复的 provider id、重复的 speech provider id,以及格式错误的注册,都会产生插件诊断,而不是导致未定义行为。 2. **契约测试** - 内置插件会在测试运行时被捕获到契约注册表中,以便 - OpenClaw 明确断言所有权。当前它用于模型 - provider、语音 provider、Web 搜索 provider,以及内置注册 - 所有权。 + 内置插件在测试运行期间会被捕获进契约注册表,以便 OpenClaw 能显式断言归属。当前这一机制用于模型提供商、语音提供商、Web 搜索提供商以及内置注册归属。 -实际效果是,OpenClaw 能够预先知道,哪个插件拥有哪个 -表面。这样核心和渠道就能顺畅组合,因为所有权是 -已声明、已类型化且可测试的,而不是隐式存在。 +实际效果是,OpenClaw 能够预先知道哪个插件拥有哪个 surface。这使得 core 和渠道能够无缝组合,因为归属是声明式、类型化且可测试的,而不是隐式的。 -### 什么内容应该属于契约 +### 什么应该属于契约 好的插件契约应当是: - 类型化的 - 小而精的 -- 面向具体能力的 -- 由核心拥有 +- 能力专用的 +- 由 core 拥有 - 可被多个插件复用 -- 可被渠道/功能消费,而无需了解供应商细节 +- 渠道/功能无需了解 vendor 即可消费 不好的插件契约则是: -- 隐藏在核心中的供应商专用策略 -- 绕过注册表的一次性插件逃生口 -- 渠道代码直接访问供应商实现 -- 不属于 `OpenClawPluginApi` 或 - `api.runtime` 的临时运行时对象 +- 隐藏在 core 中的 vendor 专用策略 +- 绕过注册表的一次性插件逃逸口 +- 渠道代码直接访问某个 vendor 实现 +- 不属于 `OpenClawPluginApi` 或 `api.runtime` 的临时运行时对象 -如果拿不准,就提高抽象层级:先定义能力,再让 -插件接入它。 +如果拿不准,提升抽象层级:先定义能力,再让插件接入它。 ## 执行模型 -原生 OpenClaw 插件与 Gateway 网关**在同一进程内**运行。它们并未进行 -沙箱隔离。已加载的原生插件与核心代码处于同样的 -进程级信任边界。 +原生 OpenClaw 插件会与 Gateway 网关 **在同一进程内** 运行。它们不是沙箱隔离的。已加载的原生插件与 core 代码处于同一进程级信任边界。 -影响包括: +这意味着: -- 原生插件可以注册工具、网络处理器、钩子和服务 -- 原生插件中的 bug 可能导致 Gateway 网关崩溃或不稳定 +- 原生插件可以注册工具、网络处理器、hooks 和服务 +- 原生插件中的 bug 可能导致 gateway 崩溃或不稳定 - 恶意原生插件等同于在 OpenClaw 进程内执行任意代码 -兼容 bundle 默认更安全,因为 OpenClaw 当前将它们 -视为元数据/内容包。在当前版本中,这主要是指内置 -Skills。 +兼容 bundle 默认更安全,因为 OpenClaw 当前将其视为元数据/内容包。就当前版本而言,这主要意味着内置 skills。 -对于非内置插件,请使用 allowlist 和显式安装/加载路径。 -应将工作区插件视为开发期代码,而不是生产环境默认值。 +对于非内置插件,请使用 allowlist 和显式安装/加载路径。应把工作区插件视为开发期代码,而不是生产默认值。 -对于内置工作区包名,请让插件 id 与 npm -名称保持锚定关系:默认使用 `@openclaw/`,或使用获批的类型化后缀,例如 -`-provider`、`-plugin`、`-speech`、`-sandbox` 或 -`-media-understanding`,当该包刻意暴露更窄的插件角色时使用。 +对于内置工作区 package 名称,保持插件 id 锚定在 npm 名称中:默认使用 `@openclaw/`,或在插件刻意暴露更窄角色时,使用已批准的类型化后缀,例如 +`-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`。 重要信任说明: - `plugins.allow` 信任的是**插件 id**,而不是来源出处。 -- 与某个内置插件使用相同 id 的工作区插件,在被启用/加入 allowlist 时, - 会刻意遮蔽对应的内置副本。 -- 这属于正常且有用的行为,适用于本地开发、补丁测试和热修复。 +- 如果某个工作区插件与某个内置插件拥有相同 id,当该工作区插件被启用/加入 allowlist 时,它会有意遮蔽内置副本。 +- 这是正常且有用的,适合本地开发、补丁测试和热修复。 ## 导出边界 -OpenClaw 导出的是能力,而不是实现层面的便捷工具。 +OpenClaw 导出的是能力,而不是实现便利性。 -保持能力注册公开,同时收紧那些不属于契约的辅助导出: +请保持能力注册公开,同时收紧非契约辅助工具导出: -- 内置插件专用的辅助子路径 -- 不打算作为公共 API 的运行时接线子路径 -- 供应商专用的便捷辅助工具 +- 内置插件专用辅助工具子路径 +- 非公共 API 的运行时管线子路径 +- vendor 专用的便利辅助工具 - 属于实现细节的 setup/onboarding 辅助工具 -一些内置插件辅助子路径仍然保留在生成的 SDK 导出 -映射中,以兼容旧代码并服务内置插件维护。当前示例包括 +出于兼容性和内置插件维护原因,一些内置插件辅助工具子路径仍保留在生成的 SDK 导出映射中。当前示例包括 `plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、 -`plugin-sdk/zalo-setup`,以及若干 `plugin-sdk/matrix*` 接缝。应将这些 -视为保留的实现细节导出,而不是新第三方插件推荐使用的 SDK 模式。 +`plugin-sdk/zalo-setup` 以及若干 `plugin-sdk/matrix*` seams。应将这些视为保留的实现细节导出,而不是新第三方插件推荐采用的 SDK 模式。 ## 加载流水线 -启动时,OpenClaw 大致会执行以下步骤: +在启动时,OpenClaw 大致会这样执行: 1. 发现候选插件根目录 -2. 读取原生或兼容 bundle 的清单与包元数据 -3. 拒绝不安全的候选项 -4. 规范化插件配置(`plugins.enabled`、`allow`、`deny`、`entries`、 +2. 读取原生或兼容 bundle 的 manifest 和 package 元数据 +3. 拒绝不安全候选项 +4. 标准化插件配置(`plugins.enabled`、`allow`、`deny`、`entries`、 `slots`、`load.paths`) 5. 为每个候选项决定是否启用 6. 通过 jiti 加载已启用的原生模块 -7. 调用原生 `register(api)`(或 `activate(api)`——旧式别名)钩子,并将注册内容收集到插件注册表中 -8. 将注册表暴露给命令/运行时表面 +7. 调用原生 `register(api)`(或 `activate(api)`——遗留别名)hooks,并把注册项收集到插件注册表中 +8. 将注册表暴露给命令/运行时 surfaces -`activate` 是 `register` 的旧式别名——加载器会解析现有者(`def.register ?? def.activate`)并在同一时机调用。所有内置插件都使用 `register`;新插件请优先使用 `register`。 +`activate` 是 `register` 的遗留别名——加载器会解析当前存在的那个(`def.register ?? def.activate`),并在同一时机调用。所有内置插件都使用 `register`;新插件请优先使用 `register`。 -安全门控发生在**运行时代码执行之前**。当候选项满足以下条件时会被阻止: -入口逃逸出插件根目录、路径对所有人可写,或者对于非内置插件而言 -路径所有权看起来可疑。 +安全关卡发生在**运行时执行之前**。如果入口路径逃逸出插件根目录、路径对所有人可写,或者对于非内置插件而言路径归属可疑,候选项都会被阻止。 -### 清单优先行为 +### Manifest 优先行为 -清单是控制面的事实来源。OpenClaw 用它来: +manifest 是控制平面的事实来源。OpenClaw 使用它来: - 标识插件 -- 发现声明的渠道/Skills/配置模式或 bundle 能力 -- 校验 `plugins.entries..config` +- 发现已声明的 channels/skills/config schema 或 bundle 能力 +- 验证 `plugins.entries..config` - 增强 Control UI 标签/占位符 - 显示安装/目录元数据 -对于原生插件,运行时模块是数据面部分。它会注册 -实际行为,例如钩子、工具、命令或提供商流程。 +对于原生插件,运行时模块是数据平面部分。它会注册实际行为,例如 hooks、tools、commands 或 provider 流程。 -### 加载器会缓存什么 +### 加载器缓存的内容 -OpenClaw 会保留一些短生命周期的进程内缓存,用于: +OpenClaw 会保留以下短生命周期的进程内缓存: -- 发现结果 -- 清单注册表数据 +- 设备发现结果 +- manifest 注册表数据 - 已加载的插件注册表 -这些缓存可减少突发启动和重复命令的开销。你可以把它们 -理解为短期性能缓存,而不是持久化机制。 +这些缓存可减少启动抖动和重复命令开销。可以把它们视为短期性能缓存,而不是持久化。 性能说明: @@ -544,37 +438,33 @@ OpenClaw 会保留一些短生命周期的进程内缓存,用于: ## 注册表模型 -已加载插件不会直接随意修改核心的全局状态。它们会注册到一个 -中央插件注册表中。 +已加载插件不会直接改写各种随机的 core 全局状态。它们会注册到一个中央插件注册表中。 注册表会跟踪: - 插件记录(身份、来源、出处、状态、诊断) - 工具 -- 旧式钩子和类型化钩子 +- 遗留 hooks 和 typed hooks - 渠道 -- 提供商 -- Gateway 网关 RPC 处理器 +- providers +- Gateway RPC 处理器 - HTTP 路由 - CLI 注册器 - 后台服务 - 插件自有命令 -核心功能随后会从该注册表中读取内容,而不是直接与插件模块通信。 -这使加载保持单向: +然后,core 功能会从该注册表读取,而不是直接与插件模块交互。这样可以保持加载的单向性: - 插件模块 -> 注册表注册 -- 核心运行时 -> 注册表消费 +- core 运行时 -> 注册表消费 -这种分离对可维护性至关重要。它意味着大多数核心表面只需要 -一个集成点:“读取注册表”,而不是“对每个插件模块做特殊处理”。 +这种分离对可维护性非常重要。它意味着大多数 core surface 只需要一个集成点:“读取注册表”,而不是“为每个插件模块写特殊分支”。 -## 对话绑定回调 +## 会话绑定回调 -绑定对话的插件可以在批准结果确定后作出响应。 +绑定会话的插件可以在审批结果确定后做出响应。 -使用 `api.onConversationBindingResolved(...)` 可在绑定请求被批准或拒绝后 -接收一个回调: +使用 `api.onConversationBindingResolved(...)` 可在绑定请求被批准或拒绝后接收回调: ```ts export default { @@ -598,23 +488,18 @@ export default { - `status`:`"approved"` 或 `"denied"` - `decision`:`"allow-once"`、`"allow-always"` 或 `"deny"` -- `binding`:适用于已批准请求的已解析绑定 -- `request`:原始请求摘要、detach 提示、sender id,以及 - 对话元数据 +- `binding`:已批准请求对应的解析后绑定 +- `request`:原始请求摘要、detach 提示、sender id 和会话元数据 -此回调仅用于通知。它不会改变谁被允许绑定对话, -并且会在核心批准处理完成后运行。 +这个回调仅用于通知。它不会改变谁有权限绑定会话,并且它会在 core 审批处理完成后才运行。 -## 提供商运行时钩子 +## 提供商运行时 hooks -提供商插件现在有两层: +Provider 插件现在有两层: -- 清单元数据:`providerAuthEnvVars` 用于在运行时加载前 - 以低成本查找提供商环境认证,`channelEnvVars` 用于在运行时加载前 - 以低成本查找渠道环境/setup,`providerAuthChoices` 用于在运行时加载前 - 以低成本提供 onboarding/认证选择标签和 CLI 标志元数据 -- 配置时钩子:`catalog` / 旧式 `discovery` 以及 `applyConfigDefaults` -- 运行时钩子:`normalizeModelId`、`normalizeTransport`、 +- manifest 元数据:`providerAuthEnvVars` 用于在运行时加载前,以低成本查找 provider 的环境变量认证;`channelEnvVars` 用于在运行时加载前,以低成本查找渠道环境变量认证/设置;`providerAuthChoices` 用于在运行时加载前,以低成本提供 onboarding/认证选择标签和 CLI flag 元数据 +- 配置期 hooks:`catalog` / 遗留 `discovery` 以及 `applyConfigDefaults` +- 运行时 hooks:`normalizeModelId`、`normalizeTransport`、 `normalizeConfig`、 `applyNativeStreamingUsageCompat`、`resolveConfigApiKey`、 `resolveSyntheticAuth`、`resolveExternalAuthProfiles`、 @@ -634,87 +519,70 @@ export default { `buildReplayPolicy`、 `sanitizeReplayHistory`、`validateReplayTurns`、`onModelSelected` -OpenClaw 仍然拥有通用智能体循环、故障转移、转录处理以及 -工具策略。这些钩子是供应商专用行为的扩展表面, -无需为此实现完整的自定义推理传输层。 +OpenClaw 仍然拥有通用的智能体循环、故障转移、转录处理和工具策略。这些 hooks 是 provider 专用行为的扩展 surface,而不需要完整自定义的推理传输层。 -当提供商使用基于环境变量的凭证,并且通用的认证/状态/模型选择器路径 -需要在不加载插件运行时的情况下看到这些凭证时,请使用清单中的 `providerAuthEnvVars`。 -当 onboarding/认证选择 CLI 表面 -需要在不加载提供商运行时的情况下知道该提供商的 choice id、 -分组标签和简单单标志认证接线方式时,请使用清单中的 `providerAuthChoices`。 -将提供商运行时中的 `envVars` 保留给面向运维者的提示信息,例如 -onboarding 标签或 OAuth client-id/client-secret 设置变量。 +当 provider 拥有基于环境变量的凭证,且通用认证/状态/模型选择器路径需要在不加载插件运行时的情况下看到它们时,请使用 manifest `providerAuthEnvVars`。当 onboarding/认证选择 CLI surface 需要在不加载 provider 运行时的情况下知道 provider 的 choice id、group 标签和简单单 flag 认证接线时,请使用 manifest `providerAuthChoices`。把 provider 运行时 `envVars` 保留给面向操作员的提示,例如 onboarding 标签或 OAuth client-id/client-secret 设置变量。 -当某个渠道具有由环境变量驱动的认证或 setup,且通用 shell 环境回退、 -配置/状态检查或 setup 提示需要在不加载渠道运行时的情况下看到它时, -请使用清单中的 `channelEnvVars`。 +当某个渠道具有由环境变量驱动的认证或设置,且通用 shell-env 回退、配置/状态检查或设置提示需要在不加载渠道运行时的情况下看到这些内容时,请使用 manifest `channelEnvVars`。 -### 钩子顺序与用法 +### Hook 顺序和使用方式 -对于模型/提供商插件,OpenClaw 大致按以下顺序调用钩子。 +对于模型/provider 插件,OpenClaw 会大致按以下顺序调用 hooks。 “何时使用”列是快速决策指南。 -| # | 钩子 | 作用 | 何时使用 | -| --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `catalog` | 在生成 `models.json` 时,将提供商配置发布到 `models.providers` 中 | 提供商拥有目录或 base URL 默认值 | -| 2 | `applyConfigDefaults` | 在配置物化期间应用提供商自有的全局配置默认值 | 默认值依赖认证模式、环境或提供商模型族语义 | -| -- | _(built-in model lookup)_ | OpenClaw 会先尝试普通的注册表/目录路径 | _(不是插件钩子)_ | -| 3 | `normalizeModelId` | 在查找前规范化旧式或预览版模型 id 别名 | 提供商拥有在规范模型解析前进行别名清理的责任 | -| 4 | `normalizeTransport` | 在通用模型组装前,规范化提供商族的 `api` / `baseUrl` | 提供商拥有同一传输族中自定义 provider id 的传输清理责任 | -| 5 | `normalizeConfig` | 在运行时/提供商解析前,规范化 `models.providers.` | 提供商需要将配置清理逻辑放在插件中;内置 Google 族辅助逻辑也会为受支持的 Google 配置项提供兜底 | -| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式用量兼容性重写 | 提供商需要基于端点对原生流式用量元数据进行修复 | -| 7 | `resolveConfigApiKey` | 在运行时认证加载前,为配置提供商解析环境标记认证 | 提供商拥有基于环境标记的 API key 解析;`amazon-bedrock` 在这里也有一个内置 AWS 环境标记解析器 | -| 8 | `resolveSyntheticAuth` | 在不持久化明文的前提下暴露本地/自托管或配置支持的认证 | 提供商可以使用合成/本地凭证标记运行 | -| 9 | `resolveExternalAuthProfiles` | 叠加提供商自有的外部认证配置文件;默认 `persistence` 为 CLI/应用自有凭证的 `runtime-only` | 提供商复用外部认证凭证,而无需持久化复制的 refresh token | -| 10 | `shouldDeferSyntheticProfileAuth` | 让已存储的合成配置文件占位符在环境/配置支持认证之后降级 | 提供商会存储不应获得优先级的合成占位配置文件 | -| 11 | `resolveDynamicModel` | 为尚未出现在本地注册表中的提供商自有模型 id 提供同步回退 | 提供商接受任意上游模型 id | -| 12 | `prepareDynamicModel` | 先执行异步预热,然后再次运行 `resolveDynamicModel` | 提供商需要先获取网络元数据,才能解析未知 id | -| 13 | `normalizeResolvedModel` | 在嵌入式 runner 使用已解析模型之前进行最终重写 | 提供商需要传输重写,但仍然使用核心传输 | -| 14 | `contributeResolvedModelCompat` | 为位于其他兼容传输之后的供应商模型贡献兼容标志 | 提供商能在不接管该提供商的前提下,于代理传输上识别自己的模型 | -| 15 | `capabilities` | 由共享核心逻辑使用的提供商自有转录/工具元数据 | 提供商需要处理转录/提供商族怪癖 | -| 16 | `normalizeToolSchemas` | 在嵌入式 runner 看到工具模式前进行规范化 | 提供商需要进行传输族级别的模式清理 | -| 17 | `inspectToolSchemas` | 在规范化后暴露提供商自有的模式诊断 | 提供商希望给出关键字警告,而不需要让核心学习提供商专用规则 | -| 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` | 面向代理/回程提供商的 Prompt 缓存策略 | 提供商需要代理专用的缓存 TTL 门控 | -| 30 | `buildMissingAuthMessage` | 替换通用的缺失认证恢复消息 | 提供商需要提供商专用的缺失认证恢复提示 | -| 31 | `suppressBuiltInModel` | 抑制过时上游模型,并可选附带面向用户的错误提示 | 提供商需要隐藏过时上游条目,或用供应商提示替换它们 | -| 32 | `augmentModelCatalog` | 在发现后追加合成/最终目录条目 | 提供商需要在 `models list` 和选择器中提供合成的前向兼容条目 | -| 33 | `isBinaryThinking` | 面向二元 thinking 提供商的开/关推理切换 | 提供商只暴露二元开/关的 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 构建提供商自有的 embedding 适配器 | Memory embedding 行为应与提供商插件绑定 | -| 41 | `buildReplayPolicy` | 返回一个控制转录处理的 replay 策略 | 提供商需要自定义转录策略(例如剥离 thinking 块) | -| 42 | `sanitizeReplayHistory` | 在通用转录清理后重写 replay 历史 | 提供商需要超出共享压缩辅助工具之外的提供商专用 replay 重写 | -| 43 | `validateReplayTurns` | 在嵌入式 runner 之前,对 replay 回合进行最终校验或重塑 | 提供商传输在通用清理之后仍需要更严格的回合校验 | -| 44 | `onModelSelected` | 当模型变为活跃时运行提供商自有的选中后副作用 | 提供商需要在模型激活时记录遥测或维护提供商自有状态 | +| # | Hook | 它的作用 | 何时使用 | +| --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `catalog` | 在生成 `models.json` 期间将 provider 配置发布到 `models.providers` 中 | provider 拥有目录或 base URL 默认值 | +| 2 | `applyConfigDefaults` | 在配置具体化期间应用 provider 自有的全局配置默认值 | 默认值依赖认证模式、环境变量或 provider 模型家族语义 | +| -- | _(built-in model lookup)_ | OpenClaw 先尝试常规的注册表/目录路径 | _(不是插件 hook)_ | +| 3 | `normalizeModelId` | 在查找前标准化遗留或预览版 model-id 别名 | provider 在规范模型解析前拥有别名清理逻辑 | +| 4 | `normalizeTransport` | 在通用模型组装前标准化 provider 家族的 `api` / `baseUrl` | provider 为同一传输家族中的自定义 provider id 拥有传输清理逻辑 | +| 5 | `normalizeConfig` | 在运行时/provider 解析前标准化 `models.providers.` | provider 需要将配置清理逻辑放在插件中;内置的 Google 家族辅助工具也会为受支持的 Google 配置项提供兜底 | +| 6 | `applyNativeStreamingUsageCompat` | 将原生分块流式传输用量兼容性重写应用到配置 providers | provider 需要基于端点的原生分块流式传输用量元数据修复 | +| 7 | `resolveConfigApiKey` | 在加载运行时认证前,为配置 providers 解析 env-marker 认证 | provider 拥有自己的 env-marker API key 解析逻辑;`amazon-bedrock` 在这里还有一个内置 AWS env-marker 解析器 | +| 8 | `resolveSyntheticAuth` | 在不持久化明文的情况下暴露本地/自托管或配置支持的认证 | provider 可以使用 synthetic/local 凭证标记运行 | +| 9 | `resolveExternalAuthProfiles` | 覆盖 provider 自有的外部认证 profile;默认 `persistence` 为 `runtime-only`,适用于 CLI/应用自有凭证 | provider 复用外部认证凭证,而不持久化复制的 refresh token | +| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的 synthetic profile 占位符优先级降到 env/config 支持认证之后 | provider 存储了不应抢占优先级的 synthetic 占位 profile | +| 11 | `resolveDynamicModel` | 针对本地注册表尚不存在的 provider 自有 model id,提供同步回退解析 | provider 接受任意上游 model id | +| 12 | `prepareDynamicModel` | 异步预热,然后再次运行 `resolveDynamicModel` | provider 在解析未知 id 前需要网络元数据 | +| 13 | `normalizeResolvedModel` | 在嵌入式 runner 使用已解析模型前进行最终重写 | provider 需要传输层重写,但仍使用 core 传输 | +| 14 | `contributeResolvedModelCompat` | 为经由其他兼容传输的 vendor 模型贡献兼容标志 | provider 能在代理传输上识别自己的模型,而无需接管该 provider | +| 15 | `capabilities` | 供共享 core 逻辑使用的 provider 自有 transcript/tooling 元数据 | provider 需要 transcript/provider 家族特性处理 | +| 16 | `normalizeToolSchemas` | 在嵌入式 runner 看到工具 schema 前对其进行标准化 | provider 需要传输家族级 schema 清理 | +| 17 | `inspectToolSchemas` | 在标准化后暴露 provider 自有 schema 诊断 | provider 希望给出关键字警告,而不需要 core 学会 provider 专用规则 | +| 18 | `resolveReasoningOutputMode` | 选择原生或带标签的 reasoning-output 契约 | provider 需要带标签的 reasoning/final output,而不是原生字段 | +| 19 | `prepareExtraParams` | 在通用流选项包装器之前标准化请求参数 | provider 需要默认请求参数或每 provider 的参数清理 | +| 20 | `createStreamFn` | 用自定义传输完全替换普通流路径 | provider 需要自定义线协议,而不仅仅是包装器 | +| 21 | `wrapStreamFn` | 在应用通用包装器之后对流进行包装 | provider 需要请求头/请求体/模型兼容包装器,而不是自定义传输 | +| 22 | `resolveTransportTurnState` | 附加原生的每轮传输头或元数据 | provider 希望通用传输发送 provider 原生轮次标识 | +| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 头或 session 冷却策略 | provider 希望通用 WS 传输调优 session 头或回退策略 | +| 24 | `formatApiKey` | auth-profile 格式化器:已存储 profile 会变成运行时 `apiKey` 字符串 | provider 存储额外认证元数据,并需要自定义运行时 token 形态 | +| 25 | `refreshOAuth` | 为自定义 refresh 端点或 refresh 失败策略覆盖 OAuth refresh | provider 不适配共享 `pi-ai` refresh 逻辑 | +| 26 | `buildAuthDoctorHint` | 当 OAuth refresh 失败时附加修复提示 | provider 在 refresh 失败后需要 provider 自有的认证修复指导 | +| 27 | `matchesContextOverflowError` | provider 自有的上下文窗口溢出匹配器 | provider 存在通用启发式无法识别的原始溢出错误 | +| 28 | `classifyFailoverReason` | provider 自有的故障转移原因分类 | provider 能把原始 API/传输错误映射为限流/过载等 | +| 29 | `isCacheTtlEligible` | 面向 proxy/backhaul providers 的提示词缓存策略 | provider 需要 proxy 专用的缓存 TTL 限制 | +| 30 | `buildMissingAuthMessage` | 替换通用缺失认证恢复消息 | provider 需要 provider 专用的缺失认证恢复提示 | +| 31 | `suppressBuiltInModel` | 过期上游模型隐藏,以及可选的面向用户错误提示 | provider 需要隐藏过期上游条目,或用 vendor 提示替换它们 | +| 32 | `augmentModelCatalog` | 在设备发现后附加 synthetic/final 目录条目 | provider 需要在 `models list` 和选择器中添加 synthetic 前向兼容条目 | +| 33 | `isBinaryThinking` | 面向 binary-thinking providers 的开/关推理切换 | provider 只暴露二元开关式 thinking | +| 34 | `supportsXHighThinking` | 为选定模型提供 `xhigh` 推理支持 | provider 只希望部分模型支持 `xhigh` | +| 35 | `resolveDefaultThinkingLevel` | 为特定模型家族提供默认 `/think` 级别 | provider 拥有某模型家族的默认 `/think` 策略 | +| 36 | `isModernModelRef` | 用于 live profile 过滤和 smoke 选择的现代模型匹配器 | provider 拥有 live/smoke 首选模型匹配逻辑 | +| 37 | `prepareRuntimeAuth` | 在推理前,将已配置凭证交换成实际运行时 token/key | provider 需要 token 交换或短期请求凭证 | +| 38 | `resolveUsageAuth` | 为 `/usage` 及相关状态 surface 解析用量/计费凭证 | provider 需要自定义用量/配额 token 解析或不同的用量凭证 | +| 39 | `fetchUsageSnapshot` | 在认证解析后获取并标准化 provider 专用的用量/配额快照 | provider 需要 provider 专用用量端点或负载解析器 | +| 40 | `createEmbeddingProvider` | 为 memory/search 构建 provider 自有 embedding 适配器 | memory embedding 行为应归 provider 插件所有 | +| 41 | `buildReplayPolicy` | 返回控制该 provider transcript 处理方式的 replay 策略 | provider 需要自定义 transcript 策略(例如剥离 thinking block) | +| 42 | `sanitizeReplayHistory` | 在通用 transcript 清理后重写 replay 历史 | provider 需要超出共享压缩辅助工具范围的 provider 专用 replay 重写 | +| 43 | `validateReplayTurns` | 在嵌入式 runner 前对 replay 轮次进行最终验证或整形 | provider 传输在通用清理后仍需更严格的轮次验证 | +| 44 | `onModelSelected` | 当模型变为活动状态时运行 provider 自有的后续副作用 | provider 需要遥测或 provider 自有状态处理 | -`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查 -已匹配的提供商插件,然后继续遍历其他具备钩子能力的提供商插件, -直到其中某一个真正更改了模型 id 或 transport/config 为止。这样能让 -别名/兼容提供商 shim 正常工作,而无需调用方知道是哪个 -内置插件拥有这次重写。如果没有任何提供商钩子重写受支持的 -Google 族配置项,内置 Google 配置规范化器仍会应用该兼容性清理。 +`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配的 provider 插件,然后回落到其他支持 hook 的 provider 插件,直到某个插件真正更改了 model id 或 transport/config。这样可以让 alias/兼容 provider shim 正常工作,而不要求调用方知道哪个内置插件拥有该重写逻辑。如果没有任何 provider hook 重写受支持的 Google 家族配置项,内置的 Google 配置标准化器仍会执行兼容性清理。 -如果提供商需要完全自定义的线协议或自定义请求执行器, -那属于另一类扩展。这些钩子适用于仍运行在 OpenClaw -常规推理循环上的提供商行为。 +如果 provider 需要完全自定义的线协议或自定义请求执行器,那就是另一类扩展。这些 hooks 适用于仍运行在 OpenClaw 常规推理循环上的 provider 行为。 -### 提供商示例 +### Provider 示例 ```ts api.registerProvider({ @@ -772,114 +640,63 @@ api.registerProvider({ - Anthropic 使用 `resolveDynamicModel`、`capabilities`、`buildAuthDoctorHint`、 `resolveUsageAuth`、`fetchUsageSnapshot`、`isCacheTtlEligible`、 - `resolveDefaultThinkingLevel`、`applyConfigDefaults`、`isModernModelRef`, - 以及 `wrapStreamFn`,因为它拥有 Claude 4.6 的前向兼容、 - 提供商族提示、认证修复指引、用量端点集成、 - Prompt 缓存适用性、感知认证的配置默认值、Claude - 默认/自适应 thinking 策略,以及面向 beta headers、 - `/fast` / `serviceTier` 和 `context1m` 的 Anthropic 专用流整形。 -- Anthropic 的 Claude 专用流辅助工具目前仍保留在内置插件自己的 - 公共 `api.ts` / `contract-api.ts` 接缝中。该包表面 - 导出 `wrapAnthropicProviderStream`、`resolveAnthropicBetas`、 - `resolveAnthropicFastMode`、`resolveAnthropicServiceTier` 以及更底层的 - Anthropic 包装器构建器,而不是仅围绕某个提供商的 beta header 规则 - 扩大通用 SDK。 + `resolveDefaultThinkingLevel`、`applyConfigDefaults`、`isModernModelRef` + 和 `wrapStreamFn`,因为它拥有 Claude 4.6 前向兼容、provider 家族提示、认证修复指导、用量端点集成、提示词缓存资格、带认证感知的配置默认值、Claude 默认/自适应 thinking 策略,以及针对 beta headers、`/fast` / `serviceTier` 和 `context1m` 的 Anthropic 专用流整形。 +- Anthropic 的 Claude 专用流辅助工具目前保留在该内置插件自己的公共 `api.ts` / `contract-api.ts` seam 中。该 package surface 导出 `wrapAnthropicProviderStream`、`resolveAnthropicBetas`、 + `resolveAnthropicFastMode`、`resolveAnthropicServiceTier` 以及更底层的 Anthropic wrapper builder,而不是为了某个 provider 的 beta-header 规则扩展通用 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 - 包装器,用于处理归因头、 - `/fast`/`serviceTier`、文本冗长度、原生 Codex Web 搜索、 - reasoning 兼容负载整形,以及 Responses 上下文管理。 + 因为它拥有 GPT-5.4 前向兼容、直接 OpenAI + `openai-completions` -> `openai-responses` 标准化、面向 Codex 的认证提示、Spark 抑制、synthetic OpenAI 列表条目,以及 GPT-5 thinking / live-model 策略;`openai-responses-defaults` 流家族则拥有共享的原生 OpenAI Responses 包装器,用于 attribution headers、 + `/fast`/`serviceTier`、文本冗长度、原生 Codex Web 搜索、reasoning-compat 负载整形和 Responses 上下文管理。 - OpenRouter 使用 `catalog`、`resolveDynamicModel` 和 - `prepareDynamicModel`,因为该提供商是直通型的,并且可能会在 - OpenClaw 静态目录更新之前暴露新的模型 id;它还使用 - `capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,以便将 - 提供商专用请求头、路由元数据、reasoning 修补以及 - Prompt 缓存策略保留在核心之外。其 replay 策略来自 - `passthrough-gemini` 族,而 `openrouter-thinking` 流族 - 拥有代理 reasoning 注入以及对不受支持模型 / `auto` 的跳过逻辑。 + `prepareDynamicModel`,因为这个 provider 是透传型的,可能会在 OpenClaw 静态目录更新之前暴露新的 model id;它还使用 + `capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,以便将 provider 专用请求头、路由元数据、reasoning 补丁和提示词缓存策略从 core 中分离出去。它的 replay 策略来自 + `passthrough-gemini` 家族,而 `openrouter-thinking` 流家族则负责代理推理注入,以及对不支持模型和 `auto` 的跳过处理。 - GitHub Copilot 使用 `catalog`、`auth`、`resolveDynamicModel` 和 - `capabilities`,以及 `prepareRuntimeAuth` 和 `fetchUsageSnapshot`,因为它 - 需要提供商自有的设备登录、模型回退行为、Claude 转录怪癖、 - GitHub token -> Copilot token 交换,以及提供商自有的用量端点。 + `capabilities`,以及 `prepareRuntimeAuth` 和 `fetchUsageSnapshot`,因为它需要 provider 自有的设备登录、模型回退行为、Claude transcript 特性、GitHub token -> Copilot token 交换,以及 provider 自有的用量端点。 - OpenAI Codex 使用 `catalog`、`resolveDynamicModel`、 - `normalizeResolvedModel`、`refreshOAuth` 和 `augmentModelCatalog`,以及 - `prepareExtraParams`、`resolveUsageAuth` 和 `fetchUsageSnapshot`,因为它 - 仍运行在核心 OpenAI 传输之上,但拥有自己的传输/base URL - 规范化、OAuth 刷新回退策略、默认传输选择、 - 合成 Codex 目录条目,以及 ChatGPT 用量端点集成;它与直接 OpenAI - 共享同一个 `openai-responses-defaults` 流族。 + `normalizeResolvedModel`、`refreshOAuth` 和 `augmentModelCatalog`, + 以及 `prepareExtraParams`、`resolveUsageAuth` 和 `fetchUsageSnapshot`, + 因为它仍运行在 core 的 OpenAI 传输上,但拥有自己的 transport/base URL 标准化、OAuth refresh 回退策略、默认传输选择、synthetic Codex 目录条目和 ChatGPT 用量端点集成;它与直接 OpenAI 共享同一个 `openai-responses-defaults` 流家族。 - Google AI Studio 和 Gemini CLI OAuth 使用 `resolveDynamicModel`、 `buildReplayPolicy`、`sanitizeReplayHistory`、 - `resolveReasoningOutputMode`、`wrapStreamFn` 和 `isModernModelRef`,因为 - `google-gemini` replay 族拥有 Gemini 3.1 前向兼容回退、 - 原生 Gemini replay 校验、引导 replay 清理、带标签的 - reasoning 输出模式以及现代模型匹配,而 - `google-thinking` 流族拥有 Gemini thinking 负载规范化; + `resolveReasoningOutputMode`、`wrapStreamFn` 和 `isModernModelRef`, + 因为 `google-gemini` replay 家族拥有 Gemini 3.1 前向兼容回退、原生 Gemini replay 验证、bootstrap replay 清理、带标签的 reasoning-output 模式和现代模型匹配,而 + `google-thinking` 流家族负责 Gemini thinking 负载标准化; Gemini CLI OAuth 还使用 `formatApiKey`、`resolveUsageAuth` 和 `fetchUsageSnapshot` 来处理 token 格式化、token 解析和配额端点接线。 -- Anthropic Vertex 通过 - `anthropic-by-model` replay 族使用 `buildReplayPolicy`, - 这样 Claude 专用 replay 清理就只作用于 Claude id, - 而不是每个 `anthropic-messages` 传输。 +- Anthropic Vertex 通过 `anthropic-by-model` replay 家族使用 + `buildReplayPolicy`,以便把 Claude 专用 replay 清理限定在 Claude id 范围内,而不是所有 `anthropic-messages` 传输。 - Amazon Bedrock 使用 `buildReplayPolicy`、`matchesContextOverflowError`、 - `classifyFailoverReason` 和 `resolveDefaultThinkingLevel`,因为它拥有 - Bedrock 专用的限流/未就绪/上下文溢出错误分类逻辑, - 面向 Anthropic-on-Bedrock 流量;其 replay 策略仍然共享相同的 - 仅限 Claude 的 `anthropic-by-model` 防护。 + `classifyFailoverReason` 和 `resolveDefaultThinkingLevel`,因为它拥有针对 Bedrock 上 Anthropic 流量的 Bedrock 专用 throttle/not-ready/context-overflow 错误分类;它的 replay 策略仍与 Claude 专用的 `anthropic-by-model` guard 共享。 - OpenRouter、Kilocode、Opencode 和 Opencode Go 通过 - `passthrough-gemini` replay 族使用 `buildReplayPolicy`, - 因为它们通过 OpenAI 兼容传输代理 Gemini - 模型,并需要 Gemini 思维签名清理,而不需要原生 Gemini replay 校验或 - 引导重写。 + `passthrough-gemini` replay 家族使用 `buildReplayPolicy`,因为它们通过 OpenAI 兼容传输代理 Gemini 模型,并且需要 Gemini thought-signature 清理,而不需要原生 Gemini replay 验证或 bootstrap 重写。 - MiniMax 通过 - `hybrid-anthropic-openai` replay 族使用 `buildReplayPolicy`, - 因为同一个提供商同时拥有 Anthropic message 和 OpenAI 兼容语义;它让 - 仅限 Claude 的 thinking 块丢弃逻辑保留在 Anthropic 一侧,同时把 reasoning - 输出模式覆盖回原生,而 `minimax-fast-mode` 流族拥有共享流路径上的 - fast-mode 模型重写。 -- Moonshot 使用 `catalog` 和 `wrapStreamFn`,因为它仍使用共享 - OpenAI 传输,但需要提供商自有的 thinking 负载规范化;`moonshot-thinking` - 流族把配置和 `/think` 状态映射到其原生二元 thinking 负载。 + `hybrid-anthropic-openai` replay 家族使用 `buildReplayPolicy`,因为同一个 provider 同时拥有 Anthropic-message 和 OpenAI 兼容语义;它在 Anthropic 一侧保留 Claude 专用 thinking-block 丢弃逻辑,同时把 reasoning output mode 覆盖回原生模式,而 `minimax-fast-mode` 流家族则负责在共享流路径上进行 fast-mode 模型重写。 +- Moonshot 使用 `catalog` 和 `wrapStreamFn`,因为它仍使用共享的 + OpenAI 传输,但需要 provider 自有的 thinking 负载标准化;`moonshot-thinking` 流家族会把配置和 `/think` 状态映射到其原生二元 thinking 负载上。 - Kilocode 使用 `catalog`、`capabilities`、`wrapStreamFn` 和 - `isCacheTtlEligible`,因为它需要提供商自有请求头、 - reasoning 负载规范化、Gemini 转录提示以及 Anthropic - 缓存 TTL 门控;`kilocode-thinking` 流族让 Kilo thinking - 注入保留在共享代理流路径上,同时跳过 `kilo/auto` 和 - 其他不支持显式 reasoning 负载的代理模型 id。 + `isCacheTtlEligible`,因为它需要 provider 自有的请求头、reasoning 负载标准化、Gemini transcript 提示和 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 UX、现代模型匹配,以及 - 用量认证 + 配额获取;`tool-stream-default-on` 流族让默认开启的 - `tool_stream` 包装器不必写进每个提供商的手写胶水代码。 + `tool_stream` 默认值、二元 thinking UX、现代模型匹配,以及用量认证 + 配额抓取;`tool-stream-default-on` 流家族则把默认开启的 `tool_stream` wrapper 从各 provider 手写 glue 中抽离出来。 - xAI 使用 `normalizeResolvedModel`、`normalizeTransport`、 `contributeResolvedModelCompat`、`prepareExtraParams`、`wrapStreamFn`、 `resolveSyntheticAuth`、`resolveDynamicModel` 和 `isModernModelRef`, - 因为它拥有原生 xAI Responses 传输规范化、Grok fast-mode - 别名重写、默认 `tool_stream`、strict-tool / reasoning-payload - 清理、用于插件自有工具的回退认证复用、前向兼容 Grok - 模型解析,以及提供商自有兼容修补,例如 xAI 工具模式 - 配置文件、不受支持的模式关键字、原生 `web_search`,以及 HTML 实体 - 工具调用参数解码。 -- Mistral、OpenCode Zen 和 OpenCode Go 仅使用 `capabilities`, - 以便将转录/工具怪癖保留在核心之外。 -- 仅目录型的内置提供商,如 `byteplus`、`cloudflare-ai-gateway`、 + 因为它拥有原生 xAI Responses 传输标准化、Grok fast-mode 别名重写、默认 `tool_stream`、strict-tool / reasoning-payload 清理、面向插件自有工具的回退认证复用、前向兼容的 Grok 模型解析,以及 provider 自有兼容补丁,例如 xAI 工具 schema 配置、受支持程度不足的 schema 关键字、原生 `web_search` 和 HTML 实体工具调用参数解码。 +- Mistral、OpenCode Zen 和 OpenCode Go 仅使用 `capabilities`,以便将 transcript/tooling 特性从 core 中分离出去。 +- 仅目录型内置 providers,例如 `byteplus`、`cloudflare-ai-gateway`、 `huggingface`、`kimi-coding`、`nvidia`、`qianfan`、 - `synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine`, - 仅使用 `catalog`。 -- Qwen 对其文本提供商使用 `catalog`,并对其多模态表面使用共享的 - 媒体理解和视频生成注册。 -- MiniMax 和 Xiaomi 使用 `catalog` 以及用量钩子,因为它们的 `/usage` - 行为归插件所有,即便推理仍通过共享传输运行。 + `synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine` 仅使用 `catalog`。 +- Qwen 为其文本 provider 使用 `catalog`,并为其多模态 surfaces 共享媒体理解和视频生成注册。 +- MiniMax 和 Xiaomi 使用 `catalog` 加上 usage hooks,因为尽管推理仍通过共享传输运行,但它们的 `/usage` 行为归插件所有。 ## 运行时辅助工具 -插件可以通过 `api.runtime` 访问精选的核心辅助工具。对于 TTS: +插件可以通过 `api.runtime` 访问部分选定的 core 辅助工具。以 TTS 为例: ```ts const clip = await api.runtime.tts.textToSpeech({ @@ -900,14 +717,14 @@ const voices = await api.runtime.tts.listVoices({ 说明: -- `textToSpeech` 返回用于文件/语音备注表面的常规核心 TTS 输出负载。 -- 使用核心 `messages.tts` 配置和提供商选择。 -- 返回 PCM 音频缓冲区 + 采样率。插件必须为提供商重新采样/编码。 -- `listVoices` 对每个提供商来说是可选项。可用于供应商自有语音选择器或 setup 流程。 -- 语音列表可以包含更丰富的元数据,如 locale、gender 和 personality tags,供感知提供商的选择器使用。 -- 当前 OpenAI 和 ElevenLabs 支持电话场景。Microsoft 不支持。 +- `textToSpeech` 返回正常的 core TTS 输出负载,用于文件/语音消息 surface。 +- 使用 core `messages.tts` 配置和 provider 选择。 +- 返回 PCM 音频缓冲区 + 采样率。插件必须自行进行重采样/编码以适配 providers。 +- `listVoices` 对每个 provider 来说都是可选的。可将其用于 vendor 自有语音选择器或设置流程。 +- 语音列表可以包含更丰富的元数据,例如 locale、gender 和 personality 标签,以支持具有 provider 感知的选择器。 +- 目前 OpenAI 和 ElevenLabs 支持电话场景。Microsoft 不支持。 -插件也可以通过 `api.registerSpeechProvider(...)` 注册语音提供商。 +插件也可以通过 `api.registerSpeechProvider(...)` 注册语音 providers。 ```ts api.registerSpeechProvider({ @@ -927,15 +744,13 @@ api.registerSpeechProvider({ 说明: -- 把 TTS 策略、回退和回复交付保留在核心。 -- 对供应商自有的合成行为使用语音提供商。 -- 旧式 Microsoft `edge` 输入会被规范化为 `microsoft` provider id。 -- 首选的所有权模型是面向公司的:随着 OpenClaw 增加这些 - 能力契约,一个供应商插件可以拥有 - 文本、语音、图像和未来媒体提供商。 +- 把 TTS 策略、回退和回复交付保留在 core。 +- 使用 speech providers 处理 vendor 自有的合成行为。 +- 遗留的 Microsoft `edge` 输入会被标准化为 `microsoft` provider id。 +- 推荐的归属模型是面向公司的:随着 OpenClaw 增加这些能力契约,一个 vendor 插件可以统一拥有文本、语音、图像以及未来媒体 providers。 -对于图像/音频/视频理解,插件会注册一个类型化的 -媒体理解提供商,而不是一个通用键值包: +对于图像/音频/视频理解,插件注册的是一个类型化的 +media-understanding provider,而不是通用的键值包: ```ts api.registerMediaUnderstandingProvider({ @@ -949,16 +764,15 @@ api.registerMediaUnderstandingProvider({ 说明: -- 将编排、回退、配置和渠道接线保留在核心。 -- 将供应商行为保留在提供商插件中。 -- 增量扩展应保持类型化:新的可选方法、新的可选 - 结果字段、新的可选能力。 -- 视频生成已经遵循同样模式: - - 核心拥有能力契约和运行时辅助工具 - - 供应商插件注册 `api.registerVideoGenerationProvider(...)` +- 把编排、回退、配置和渠道接线保留在 core。 +- 把 vendor 行为保留在 provider 插件中。 +- 增量扩展应保持类型化:新的可选方法、新的可选结果字段、新的可选能力。 +- 视频生成已经遵循相同模式: + - core 拥有能力契约和运行时辅助工具 + - vendor 插件注册 `api.registerVideoGenerationProvider(...)` - 功能/渠道插件消费 `api.runtime.videoGeneration.*` -对于媒体理解运行时辅助工具,插件可以调用: +对于 media-understanding 运行时辅助工具,插件可以调用: ```ts const image = await api.runtime.mediaUnderstanding.describeImageFile({ @@ -973,8 +787,7 @@ const video = await api.runtime.mediaUnderstanding.describeVideoFile({ }); ``` -对于音频转录,插件可以使用媒体理解运行时 -或较旧的 STT 别名: +对于音频转写,插件可以使用 media-understanding 运行时,也可以使用较旧的 STT 别名: ```ts const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ @@ -987,10 +800,10 @@ const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ 说明: -- `api.runtime.mediaUnderstanding.*` 是图像/音频/视频理解的首选共享表面。 -- 使用核心媒体理解音频配置(`tools.media.audio`)和提供商回退顺序。 -- 当没有产生转录输出时(例如跳过/不支持的输入),返回 `{ text: undefined }`。 -- `api.runtime.stt.transcribeAudioFile(...)` 仍保留为兼容性别名。 +- `api.runtime.mediaUnderstanding.*` 是图像/音频/视频理解的首选共享 surface。 +- 使用 core 的媒体理解音频配置(`tools.media.audio`)和 provider 回退顺序。 +- 当未产生转写输出时(例如输入被跳过/不受支持),返回 `{ text: undefined }`。 +- `api.runtime.stt.transcribeAudioFile(...)` 仍保留作为兼容别名。 插件还可以通过 `api.runtime.subagent` 启动后台子智能体运行: @@ -1006,14 +819,13 @@ const result = await api.runtime.subagent.run({ 说明: -- `provider` 和 `model` 是每次运行的可选覆盖项,不会持久化为会话更改。 -- OpenClaw 仅对受信任调用方应用这些覆盖字段。 -- 对于插件自有回退运行,运维者必须通过 `plugins.entries..subagent.allowModelOverride: true` 显式启用。 -- 使用 `plugins.entries..subagent.allowedModels` 可将受信任插件限制为特定的规范 `provider/model` 目标,或使用 `"*"` 明确允许任意目标。 -- 不受信任的插件子智能体运行仍可工作,但覆盖请求会被拒绝,而不是静默回退。 +- `provider` 和 `model` 是每次运行的可选覆盖项,不是持久化的 session 变更。 +- OpenClaw 仅对受信调用方接受这些覆盖字段。 +- 对于插件自有的回退运行,操作员必须通过 `plugins.entries..subagent.allowModelOverride: true` 显式启用。 +- 使用 `plugins.entries..subagent.allowedModels` 将受信插件限制为特定的规范 `provider/model` 目标,或使用 `"*"` 显式允许任意目标。 +- 不受信插件的子智能体运行仍可工作,但覆盖请求会被拒绝,而不是静默回退。 -对于 Web 搜索,插件可以消费共享运行时辅助工具,而不是 -直接接入智能体工具接线: +对于 Web 搜索,插件可以消费共享运行时辅助工具,而不是直接接入智能体工具接线: ```ts const providers = api.runtime.webSearch.listProviders({ @@ -1030,13 +842,13 @@ const result = await api.runtime.webSearch.search({ ``` 插件也可以通过 -`api.registerWebSearchProvider(...)` 注册 Web 搜索提供商。 +`api.registerWebSearchProvider(...)` 注册 Web 搜索 providers。 说明: -- 将提供商选择、凭证解析和共享请求语义保留在核心。 -- 对供应商专用搜索传输使用 Web 搜索提供商。 -- `api.runtime.webSearch.*` 是功能/渠道插件在需要搜索行为但又不依赖智能体工具包装器时的首选共享表面。 +- 把 provider 选择、凭证解析和共享请求语义保留在 core。 +- 使用 Web 搜索 providers 处理 vendor 专用搜索传输。 +- `api.runtime.webSearch.*` 是功能/渠道插件在需要搜索行为但不依赖智能体工具包装器时的首选共享 surface。 ### `api.runtime.imageGeneration` @@ -1051,12 +863,12 @@ const providers = api.runtime.imageGeneration.listProviders({ }); ``` -- `generate(...)`:使用已配置的图像生成提供商链生成图像。 -- `listProviders(...)`:列出可用的图像生成提供商及其能力。 +- `generate(...)`:使用已配置的图像生成 provider 链生成图像。 +- `listProviders(...)`:列出可用的图像生成 providers 及其能力。 ## Gateway 网关 HTTP 路由 -插件可以通过 `api.registerHttpRoute(...)` 暴露 HTTP 端点。 +插件可以使用 `api.registerHttpRoute(...)` 暴露 HTTP 端点。 ```ts api.registerHttpRoute({ @@ -1074,31 +886,31 @@ api.registerHttpRoute({ 路由字段: - `path`:Gateway 网关 HTTP 服务器下的路由路径。 -- `auth`:必填。使用 `"gateway"` 以要求常规 Gateway 网关认证,或使用 `"plugin"` 以启用插件管理的认证/Webhook 校验。 +- `auth`:必填。使用 `"gateway"` 以要求普通 Gateway 网关认证,或使用 `"plugin"` 以启用插件自主管理的认证/webhook 验证。 - `match`:可选。`"exact"`(默认)或 `"prefix"`。 -- `replaceExisting`:可选。允许同一个插件替换其自己已有的路由注册。 +- `replaceExisting`:可选。允许同一插件替换自己已有的路由注册。 - `handler`:当路由处理了请求时返回 `true`。 说明: - `api.registerHttpHandler(...)` 已被移除,并会导致插件加载错误。请改用 `api.registerHttpRoute(...)`。 - 插件路由必须显式声明 `auth`。 -- 除非设置 `replaceExisting: true`,否则精确的 `path + match` 冲突会被拒绝,并且一个插件不能替换另一个插件的路由。 -- 不同 `auth` 级别的重叠路由会被拒绝。请仅在同一认证级别内保留 `exact`/`prefix` 贯穿链。 -- `auth: "plugin"` 路由**不会**自动获得运维者运行时作用域。它们用于插件管理的 Webhook/签名校验,而不是有特权的 Gateway 网关辅助调用。 -- `auth: "gateway"` 路由会在 Gateway 网关请求运行时作用域内运行,但该作用域有意保持保守: +- 精确的 `path + match` 冲突会被拒绝,除非设置了 `replaceExisting: true`,并且一个插件不能替换另一个插件的路由。 +- 不同 `auth` 级别的重叠路由会被拒绝。请仅在相同 auth 级别内建立 `exact`/`prefix` 的贯穿链。 +- `auth: "plugin"` 路由**不会**自动接收操作员运行时作用域。它们用于插件自主管理的 webhook/签名验证,而不是特权 Gateway 网关辅助工具调用。 +- `auth: "gateway"` 路由会在 Gateway 网关请求运行时作用域内运行,但该作用域刻意保持保守: - 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes` - - 受信任、带身份的 HTTP 模式(例如 `trusted-proxy`,或私有入口上的 `gateway.auth.mode = "none"`)仅在显式提供该头时才会接受 `x-openclaw-scopes` - - 如果这些带身份的插件路由请求缺少 `x-openclaw-scopes`,运行时作用域会回退为 `operator.write` -- 实践规则:不要假设经过 gateway 认证的插件路由天然就是管理员表面。如果你的路由需要仅管理员行为,请要求使用带身份的认证模式,并在文档中说明显式的 `x-openclaw-scopes` 头契约。 + - 可信、带身份的 HTTP 模式(例如 `trusted-proxy` 或私有入口上的 `gateway.auth.mode = "none"`)只有在显式提供该头时,才会尊重 `x-openclaw-scopes` + - 如果这些带身份的插件路由请求未提供 `x-openclaw-scopes`,运行时作用域会回退到 `operator.write` +- 实用规则:不要假设 gateway 认证插件路由天然就是管理员 surface。如果你的路由需要仅管理员可用的行为,请要求使用带身份的认证模式,并记录显式的 `x-openclaw-scopes` 头契约。 ## 插件 SDK 导入路径 -在编写插件时,请使用 SDK 子路径,而不是单体的 `openclaw/plugin-sdk` 导入: +在编写插件时,请使用 SDK 子路径,而不是单体式的 `openclaw/plugin-sdk` 导入: -- `openclaw/plugin-sdk/plugin-entry`:用于插件注册原语。 -- `openclaw/plugin-sdk/core`:用于通用共享的插件面向契约。 -- `openclaw/plugin-sdk/config-schema`:用于根 `openclaw.json` Zod 模式 +- `openclaw/plugin-sdk/plugin-entry` 用于插件注册原语。 +- `openclaw/plugin-sdk/core` 用于通用共享的面向插件契约。 +- `openclaw/plugin-sdk/config-schema` 用于根 `openclaw.json` Zod schema 导出(`OpenClawSchema`)。 - 稳定的渠道原语,例如 `openclaw/plugin-sdk/channel-setup`、 `openclaw/plugin-sdk/setup-runtime`、 @@ -1111,15 +923,13 @@ api.registerHttpRoute({ `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 匹配、 - envelope 格式化和入站 envelope 上下文辅助工具的共享归属地。 - `channel-setup` 是范围更窄的可选安装 setup 接缝。 - `setup-runtime` 是供 `setupEntry` / - 延迟启动使用的运行时安全 setup 表面,其中包含导入安全的 setup patch 适配器。 - `setup-adapter-runtime` 是感知环境的账户 setup 适配器接缝。 - `setup-tools` 是小型 CLI/归档/文档辅助接缝(`formatCliCommand`、 + `openclaw/plugin-sdk/secret-input` 和 + `openclaw/plugin-sdk/webhook-ingress` 用于共享设置/认证/回复/webhook + 接线。`channel-inbound` 是 debounce、mention 匹配、入站 mention-policy 辅助工具、envelope 格式化和入站 envelope 上下文辅助工具的共享归属位置。 + `channel-setup` 是一个窄型可选安装设置 seam。 + `setup-runtime` 是 `setupEntry` / 延迟启动所使用的运行时安全设置 surface,包括导入安全的 setup patch 适配器。 + `setup-adapter-runtime` 是带环境感知的账户设置适配器 seam。 + `setup-tools` 是小型 CLI/archive/docs 辅助工具 seam(`formatCliCommand`、 `detectBinary`、`extractArchive`、`resolveBrewExecutable`、`formatDocsLink`、 `CONFIG_DIR`)。 - 领域子路径,例如 `openclaw/plugin-sdk/channel-config-helpers`、 @@ -1136,183 +946,149 @@ api.registerHttpRoute({ `openclaw/plugin-sdk/routing`、 `openclaw/plugin-sdk/status-helpers`、 `openclaw/plugin-sdk/text-runtime`、 - `openclaw/plugin-sdk/runtime-store`,以及 + `openclaw/plugin-sdk/runtime-store` 和 `openclaw/plugin-sdk/directory-runtime`,用于共享运行时/配置辅助工具。 - `telegram-command-config` 是 Telegram 自定义 - 命令规范化/校验的窄范围公共接缝,即使内置 - Telegram 契约表面暂时不可用,它仍可用。 - `text-runtime` 是共享的文本/Markdown/日志接缝,包括 - 面向 assistant 可见文本的剥离、Markdown 渲染/分块辅助工具、脱敏 - 辅助工具、directive-tag 辅助工具以及 safe-text 实用工具。 -- 与审批相关的渠道接缝应优先采用插件上的单一 `approvalCapability` - 契约。随后核心会通过这一项能力读取审批认证、交付、渲染和 - 原生路由行为,而不是把审批行为混进无关的插件字段中。 -- `openclaw/plugin-sdk/channel-runtime` 已弃用,仅保留为旧插件的 - 兼容性 shim。新代码应改为导入更窄范围的通用原语, - 仓库代码也不应再新增对该 shim 的导入。 + `telegram-command-config` 是 Telegram 自定义命令标准化/验证的窄型公共 seam,即使内置 Telegram 契约 surface 暂时不可用,它也仍可使用。 + `text-runtime` 是共享的文本/Markdown/日志 seam,包括 assistant 可见文本剥离、Markdown 渲染/分块辅助工具、脱敏辅助工具、directive-tag 辅助工具和安全文本工具。 +- 审批专用的渠道 seams 应优先采用插件上的单一 `approvalCapability` + 契约。然后 core 会通过这一种能力读取审批认证、交付、渲染和原生路由行为,而不是把审批行为混入无关的插件字段中。 +- `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/*`。 + `openclaw/plugin-sdk/*` 子路径。OpenClaw core/test 代码可以使用插件 package 根目录下的仓库公共入口点,例如 `index.js`、`api.js`、 + `runtime-api.js`、`setup-entry.js`,以及范围很窄的文件,例如 + `login-qr-api.js`。绝不要从 core 或其他扩展中导入某个插件 package 的 `src/*`。 - 仓库入口点拆分: `/api.js` 是辅助工具/类型 barrel, - `/runtime-api.js` 是纯运行时 barrel, + `/runtime-api.js` 是仅运行时 barrel, `/index.js` 是内置插件入口, `/setup-entry.js` 是 setup 插件入口。 -- 当前内置提供商示例: - - Anthropic 使用 `api.js` / `contract-api.js` 提供 Claude 流辅助工具, - 例如 `wrapAnthropicProviderStream`、beta-header 辅助工具以及 `service_tier` +- 当前内置 provider 示例: + - Anthropic 使用 `api.js` / `contract-api.js` 提供 Claude 流辅助工具,例如 `wrapAnthropicProviderStream`、beta-header 辅助工具和 `service_tier` 解析。 - - OpenAI 使用 `api.js` 提供 provider builder、默认模型辅助工具,以及 - 实时 provider builder。 + - OpenAI 使用 `api.js` 提供 provider builder、默认模型辅助工具和实时 provider builder。 - OpenRouter 使用 `api.js` 提供其 provider builder 以及 onboarding/config - 辅助工具,而 `register.runtime.js` 仍可为仓库本地用途重新导出通用的 + 辅助工具,而 `register.runtime.js` 仍可为仓库内部使用重新导出通用 `plugin-sdk/provider-stream` 辅助工具。 -- 由 facade 加载的公共入口点会优先使用当前活跃的运行时配置快照; - 若 OpenClaw 尚未提供运行时快照,则回退到磁盘上的已解析配置文件。 -- 通用共享原语仍然是首选的公共 SDK 契约。当前仍保留一小组 - 以内置渠道命名的辅助接缝用于兼容性支持。应将它们视为 - 内置维护/兼容接缝,而不是新的第三方导入目标;新的跨渠道契约 - 仍应落在通用 `plugin-sdk/*` 子路径或插件本地的 `api.js` / - `runtime-api.js` barrel 上。 +- 外观加载的公共入口点优先使用当前活动的运行时配置快照;如果 OpenClaw 尚未提供运行时快照,则回退到磁盘上的已解析配置文件。 +- 通用共享原语仍然是首选公共 SDK 契约。当前仍存在一小组保留的、带内置渠道品牌的辅助工具兼容 seams。应将这些视为内置维护/兼容 seams,而不是新的第三方导入目标;新的跨渠道契约仍应落在通用 `plugin-sdk/*` 子路径,或插件本地 `api.js` / + `runtime-api.js` barrels 上。 兼容性说明: -- 新代码应避免使用根 `openclaw/plugin-sdk` barrel。 -- 优先使用范围更窄的稳定原语。较新的 setup/pairing/reply/ +- 新代码请避免使用根级 `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`。 - 消息动作门控和反应消息 id 辅助工具属于 + 目标解析/匹配应归于 `openclaw/plugin-sdk/channel-targets`。 + Message 动作关卡和 reaction message-id 辅助工具应归于 `openclaw/plugin-sdk/channel-actions`。 -- 内置扩展专用辅助 barrel 默认并不稳定。如果某个 - 辅助工具只被内置扩展需要,请将其保留在该扩展本地的 - `api.js` 或 `runtime-api.js` 接缝之后,而不是提升到 +- 默认情况下,内置扩展专用辅助工具 barrel 并不稳定。如果某个辅助工具仅供某个内置扩展使用,应将其保留在该扩展的本地 `api.js` 或 + `runtime-api.js` seam 后面,而不是提升到 `openclaw/plugin-sdk/`。 -- 新的共享辅助接缝应当是通用的,而不是以渠道命名。共享目标 - 解析属于 `openclaw/plugin-sdk/channel-targets`;渠道专用 - 内部逻辑应保留在所属插件本地的 `api.js` 或 `runtime-api.js` - 接缝后面。 -- `image-generation`、 - `media-understanding` 和 `speech` 等能力专用子路径之所以存在, - 是因为当前内置/原生插件正在使用它们。但仅仅存在这些路径, - 并不自动意味着每个导出的辅助工具都是长期冻结的外部契约。 +- 新的共享辅助工具 seam 应该是通用的,而不是带渠道品牌的。共享目标解析应归于 `openclaw/plugin-sdk/channel-targets`;渠道专用内部实现则保留在归属插件的本地 `api.js` 或 `runtime-api.js` + seam 后面。 +- 像 `image-generation`、`media-understanding` 和 `speech` 这样的能力专用子路径之所以存在,是因为当前内置/原生插件正在使用它们。但这并不自动意味着其中导出的每个辅助工具都是长期冻结的外部契约。 -## Message 工具模式 +## Message 工具 schema -插件应拥有渠道专用的 `describeMessageTool(...)` 模式 -贡献。请将提供商专用字段保留在插件中,而不是放到共享核心中。 +插件应拥有渠道专用的 `describeMessageTool(...)` schema 贡献。请把 provider 专用字段保留在插件中,而不是放进共享 core。 -对于共享的可移植模式片段,请复用通过 +对于共享且可移植的 schema 片段,请复用通过 `openclaw/plugin-sdk/channel-actions` 导出的通用辅助工具: -- `createMessageToolButtonsSchema()`:用于按钮网格风格负载 -- `createMessageToolCardSchema()`:用于结构化卡片负载 +- `createMessageToolButtonsSchema()` 用于按钮网格风格的负载 +- `createMessageToolCardSchema()` 用于结构化卡片负载 -如果某个模式形状只适用于一个提供商,应将其定义在该插件 -自身源码中,而不是提升到共享 SDK 中。 +如果某个 schema 形状只对一个 provider 有意义,应将其定义在该插件自己的源码中,而不是把它提升到共享 SDK 中。 ## 渠道目标解析 -渠道插件应拥有渠道专用的目标语义。请保持共享 -outbound 宿主为通用形式,并使用消息适配器表面来承载提供商规则: +渠道插件应拥有渠道专用的目标语义。请保持共享出站宿主通用,并使用消息适配器 surface 处理 provider 规则: -- `messaging.inferTargetChatType({ to })` 用于决定规范化目标在 - 目录查找前应被视为 `direct`、`group` 还是 `channel`。 -- `messaging.targetResolver.looksLikeId(raw, normalized)` 用于告诉核心, - 某个输入是否应直接跳到类似 id 的解析,而不是目录搜索。 -- `messaging.targetResolver.resolveTarget(...)` 是在规范化之后或 - 目录未命中之后,核心需要最终提供商自有解析时使用的插件回退。 -- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后, - 负责提供商专用的会话路由构造。 +- `messaging.inferTargetChatType({ to })` 决定在目录查找之前,标准化目标应被视为 `direct`、`group` 还是 `channel` +- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉 core 某个输入是否应跳过目录搜索,直接进入类似 id 的解析 +- `messaging.targetResolver.resolveTarget(...)` 是插件回退路径,当 core 在标准化之后或目录未命中后需要最终的 provider 自有解析时调用 +- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后,负责 provider 专用的 session 路由构建 -推荐拆分: +推荐拆分方式: -- 对应发生在搜索 peers/groups 之前的类别决策,请使用 `inferTargetChatType`。 -- 对于“将此视为显式/原生目标 id”的检查,请使用 `looksLikeId`。 -- `resolveTarget` 用于提供商专用规范化回退,而不是广义目录搜索。 -- 请将 chat id、thread id、JID、handle 和 room id 等提供商原生 id - 保留在 `target` 值或提供商专用参数中,而不是放入通用 SDK 字段。 +- 用 `inferTargetChatType` 处理应在搜索 peers/groups 前做出的类别决策 +- 用 `looksLikeId` 处理“将此视为显式/原生目标 id”的检查 +- 用 `resolveTarget` 处理 provider 专用标准化回退,而不是进行广泛目录搜索 +- 将 provider 原生 id,如 chat id、thread id、JID、handle 和 room id,保存在 `target` 值或 provider 专用参数中,而不是通用 SDK 字段中 ## 配置支持的目录 -如果插件需要从配置中派生目录条目,应将该逻辑保留在插件内部, -并复用 `openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。 +从配置派生目录项的插件,应把这部分逻辑保留在插件中,并复用 +`openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。 -当某个渠道需要配置支持的 peers/groups 时,应使用此方式,例如: +当某个渠道需要配置支持的 peers/groups 时,应使用这种方式,例如: - 由 allowlist 驱动的私信 peers - 已配置的渠道/群组映射 -- 按账户划分的静态目录回退 +- 账户作用域的静态目录回退 -`directory-runtime` 中的共享辅助工具仅处理通用操作: +`directory-runtime` 中的共享辅助工具只处理通用操作: - 查询过滤 -- 限制应用 -- 去重/规范化辅助工具 +- 限制数量应用 +- 去重/标准化辅助工具 - 构建 `ChannelDirectoryEntry[]` -渠道专用的账户检查和 id 规范化应保留在插件实现中。 +渠道专用的账户检查和 id 标准化应保留在插件实现中。 -## 提供商目录 +## Provider 目录 -提供商插件可以通过 +Provider 插件可以通过 `registerProvider({ catalog: { run(...) { ... } } })` 定义用于推理的模型目录。 -`catalog.run(...)` 返回的形状与 OpenClaw 写入 -`models.providers` 的形状相同: +`catalog.run(...)` 返回的形状与 OpenClaw 写入 `models.providers` 的内容相同: -- `{ provider }`:对应一个 provider 条目 -- `{ providers }`:对应多个 provider 条目 +- `{ provider }` 表示一个 provider 条目 +- `{ providers }` 表示多个 provider 条目 -当插件拥有提供商专用模型 id、base URL 默认值或受认证门控的模型元数据时, -请使用 `catalog`。 +当插件拥有 provider 专用 model id、base URL 默认值或受认证控制的模型元数据时,请使用 `catalog`。 -`catalog.order` 控制插件目录相对于 OpenClaw -内置隐式提供商的合并时机: +`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式 providers 的合并时机: -- `simple`:普通 API key 或环境驱动的提供商 -- `profile`:存在认证配置文件时出现的提供商 -- `paired`:合成多个相关 provider 条目的提供商 -- `late`:最后一轮,在其他隐式提供商之后 +- `simple`:纯 API key 或环境变量驱动的 providers +- `profile`:存在 auth profiles 时出现的 providers +- `paired`:会合成多个相关 provider 条目的 providers +- `late`:最后一轮,在其他隐式 providers 之后 -后出现的 provider 在键冲突时胜出,因此插件可以有意使用相同的 -provider id 覆盖内置 provider 条目。 +后面的 provider 会在键冲突时胜出,因此插件可以有意用相同 provider id 覆盖某个内置 provider 条目。 兼容性: -- `discovery` 仍然作为旧式别名可用 +- `discovery` 仍可作为遗留别名使用 - 如果同时注册了 `catalog` 和 `discovery`,OpenClaw 会使用 `catalog` ## 只读渠道检查 -如果你的插件注册了一个渠道,推荐在 `resolveAccount(...)` 之外 -同时实现 `plugin.config.inspectAccount(cfg, accountId)`。 +如果你的插件注册了一个渠道,请优先实现 +`plugin.config.inspectAccount(cfg, accountId)`,并同时实现 `resolveAccount(...)`。 原因: -- `resolveAccount(...)` 是运行时路径。它可以假定凭证 - 已被完整物化,并且在所需 Secret 缺失时快速失败。 -- 只读命令路径,如 `openclaw status`、`openclaw status --all`、 - `openclaw channels status`、`openclaw channels resolve`,以及 doctor/config - 修复流程,不应为了描述配置而必须物化运行时凭证。 +- `resolveAccount(...)` 是运行时路径。它可以假设凭证已经完全具体化,并在缺失必要 secret 时快速失败。 +- 像 `openclaw status`、`openclaw status --all`、 + `openclaw channels status`、`openclaw channels resolve` 以及 doctor/config + 修复流程这样的只读命令路径,不应为了描述配置而不得不具体化运行时凭证。 推荐的 `inspectAccount(...)` 行为: -- 只返回描述性的账户状态。 +- 仅返回描述性的账户状态。 - 保留 `enabled` 和 `configured`。 - 在相关时包含凭证来源/状态字段,例如: - `tokenSource`、`tokenStatus` - `botTokenSource`、`botTokenStatus` - `appTokenSource`、`appTokenStatus` - `signingSecretSource`、`signingSecretStatus` -- 你不需要为了报告只读可用性而返回原始 token 值。 - 返回 `tokenStatus: "available"`(以及对应的来源字段)就足够用于状态类命令。 -- 当凭证是通过 SecretRef 配置,但在当前命令路径中不可用时,请使用 `configured_unavailable`。 +- 为了报告只读可用性,你不需要返回原始 token 值。返回 + `tokenStatus: "available"`(以及对应的 source 字段)就足够用于状态类命令。 +- 当某个凭证通过 SecretRef 配置,但在当前命令路径中不可用时,请使用 `configured_unavailable`。 -这样,只读命令就可以报告“已配置,但在当前命令路径中不可用”, -而不是崩溃或错误地把账户报告为未配置。 +这样,只读命令就可以报告“已配置,但在此命令路径中不可用”,而不是崩溃或误报账户未配置。 ## Package packs @@ -1328,66 +1104,43 @@ provider id 覆盖内置 provider 条目。 } ``` -每个条目都会成为一个插件。如果该包列出了多个扩展,则插件 id -会变为 `name/`。 +每个条目都会变成一个插件。如果 pack 列出了多个扩展,插件 id +将变为 `name/`。 -如果你的插件导入了 npm 依赖,请在该目录中安装它们, -以便 `node_modules` 可用(`npm install` / `pnpm install`)。 +如果你的插件导入 npm 依赖,请在该目录中安装它们,以便 `node_modules` +可用(`npm install` / `pnpm install`)。 -安全护栏:每个 `openclaw.extensions` 条目在解析符号链接后都必须保持在 -插件目录内部。逃逸出包目录的条目会被 -拒绝。 +安全护栏:每个 `openclaw.extensions` 条目在符号链接解析之后,都必须保留在插件目录内部。任何逃逸出 package 目录的条目都会被拒绝。 安全说明:`openclaw plugins install` 会使用 -`npm install --omit=dev --ignore-scripts` 安装插件依赖 -(运行时不执行生命周期脚本,也不安装 dev dependencies)。请保持插件依赖 -树为“纯 JS/TS”,并避免依赖需要 `postinstall` 构建的包。 +`npm install --omit=dev --ignore-scripts` 安装插件依赖(无生命周期脚本,运行时也不安装开发依赖)。请保持插件依赖树为“纯 JS/TS”,并避免需要 `postinstall` 构建的包。 -可选:`openclaw.setupEntry` 可以指向一个轻量级的仅 setup 模块。 -当 OpenClaw 需要为已禁用的渠道插件提供 setup 表面, -或者某个渠道插件已启用但尚未配置时,它会加载 `setupEntry` -而不是完整插件入口。这样当你的主插件入口还会接入工具、 -钩子或其他仅运行时代码时,可让启动和 setup 更轻量。 +可选:`openclaw.setupEntry` 可以指向一个轻量级、仅 setup 的模块。 +当 OpenClaw 需要为一个已禁用的渠道插件提供 setup surface,或者当某个渠道插件已启用但仍未配置时,它会加载 `setupEntry` 而不是完整插件入口。这样在主插件入口还会接线 tools、hooks 或其他仅运行时代码时,可以让启动和 setup 更轻量。 可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` -可以让渠道插件在 Gateway 网关监听前启动阶段,也使用相同的 `setupEntry` 路径, -即使该渠道已经配置完成。 +可以让某个渠道插件在 Gateway 网关监听前的启动阶段,即使该渠道已配置,也改走同样的 `setupEntry` 路径。 -只有当 `setupEntry` 完整覆盖了在 Gateway 网关开始监听之前 -必须存在的启动表面时,才应使用此选项。实际上,这意味着 setup entry -必须注册启动所依赖的每一种渠道自有能力,例如: +仅当 `setupEntry` 完全覆盖了在 Gateway 网关开始监听前必须存在的启动 surface 时,才使用此选项。实际而言,这意味着 setup 入口必须注册启动依赖的每个渠道自有能力,例如: - 渠道注册本身 -- 在 Gateway 网关开始监听前必须可用的任何 HTTP 路由 -- 在同一时间窗口中必须存在的任何 gateway 方法、工具或服务 +- 任何必须在 Gateway 网关开始监听前就可用的 HTTP 路由 +- 任何在同一窗口内必须存在的 gateway 方法、工具或服务 -如果你的完整入口仍然拥有任何必需的启动能力,请不要启用 -此标志。保持插件采用默认行为,让 OpenClaw 在启动期间加载 -完整入口。 +如果完整入口仍拥有任何必需的启动能力,就不要启用这个标志。请保持默认行为,让 OpenClaw 在启动期间加载完整入口。 -内置渠道还可以发布仅 setup 的契约表面辅助工具, -以便核心在完整渠道运行时加载之前就可以查询它们。当前的 setup -提升表面包括: +内置渠道也可以发布仅 setup 用的契约 surface 辅助工具,以便 core 在完整渠道运行时加载前进行查询。当前 setup 提升 surface 为: - `singleAccountKeysToMove` - `namedAccountPromotionKeys` - `resolveSingleAccountPromotionTarget(...)` -当核心需要将旧式单账户渠道配置提升到 -`channels..accounts.*` 中,而又不加载完整插件入口时, -它会使用该表面。Matrix 是当前的内置示例:当命名账户已存在时, -它只会把认证/引导相关键移动到一个有名称的提升账户中,并且它可以保留 -一个已配置的非规范默认账户键,而不是总是创建 -`accounts.default`。 +当 core 需要在不加载完整插件入口的情况下,把遗留的单账户渠道配置提升到 `channels..accounts.*` 时,就会使用这些 surface。Matrix 是当前的内置示例:当已存在命名账户时,它只会把 auth/bootstrap 键移动到某个已命名提升账户中,并且它可以保留一个已配置的、非规范默认账户键,而不是总是创建 `accounts.default`。 -这些 setup patch 适配器让内置契约表面发现保持懒加载。 -导入时依然轻量;提升表面只会在首次使用时加载, -而不会在模块导入时重新进入内置渠道启动流程。 +这些 setup patch 适配器可以让内置契约 surface 设备发现保持惰性。导入时间保持轻量;提升 surface 只会在首次使用时加载,而不会在模块导入时重新进入内置渠道启动流程。 -当这些启动表面包含 gateway RPC 方法时,请将它们保留在 -插件专用前缀下。核心管理命名空间(`config.*`、 -`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且始终解析为 -`operator.admin`,即使某个插件请求更窄的作用域也是如此。 +当这些启动 surfaces 包含 gateway RPC 方法时,请保持它们位于插件专用前缀下。Core 管理员命名空间(`config.*`、 +`exec.approvals.*`、`wizard.*`、`update.*`)仍然保留,并且始终解析为 `operator.admin`,即使某个插件请求更窄的作用域。 示例: @@ -1406,8 +1159,7 @@ provider id 覆盖内置 provider 条目。 ### 渠道目录元数据 -渠道插件可以通过 `openclaw.channel` 声明 setup/发现元数据,并通过 -`openclaw.install` 声明安装提示。这样可让核心目录不必内置数据。 +渠道插件可以通过 `openclaw.channel` 声明 setup/设备发现元数据,并通过 `openclaw.install` 声明安装提示。这样可以让 core 目录保持无数据化。 示例: @@ -1435,41 +1187,37 @@ provider id 覆盖内置 provider 条目。 } ``` -除了最小示例外,实用的 `openclaw.channel` 字段还包括: +除最小示例外,其他有用的 `openclaw.channel` 字段还包括: -- `detailLabel`:用于更丰富目录/状态表面的次级标签 +- `detailLabel`:用于更丰富目录/状态 surface 的次级标签 - `docsLabel`:覆盖文档链接文本 -- `preferOver`:该目录条目应优先于其之上的低优先级插件/渠道 id -- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择表面文案控制 -- `markdownCapable`:将该渠道标记为支持 Markdown,用于出站格式化决策 -- `exposure.configured`:设置为 `false` 时,在已配置渠道列表表面中隐藏该渠道 -- `exposure.setup`:设置为 `false` 时,在交互式 setup/configure 选择器中隐藏该渠道 -- `exposure.docs`:将该渠道标记为内部/私有,用于文档导航表面 -- `showConfigured` / `showInSetup`:为了兼容仍接受的旧式别名;优先使用 `exposure` -- `quickstartAllowFrom`:让该渠道接入标准快速开始 `allowFrom` 流程 +- `preferOver`:该目录条目应优先于哪些低优先级插件/渠道 id +- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择 surface 文案控制 +- `markdownCapable`:将该渠道标记为支持 Markdown,以供出站格式决策使用 +- `exposure.configured`:设为 `false` 时,在已配置渠道列表 surface 中隐藏该渠道 +- `exposure.setup`:设为 `false` 时,在交互式 setup/configure 选择器中隐藏该渠道 +- `exposure.docs`:在文档导航 surface 中将该渠道标记为内部/私有 +- `showConfigured` / `showInSetup`:出于兼容性仍接受的遗留别名;优先使用 `exposure` +- `quickstartAllowFrom`:将该渠道加入标准快速开始 `allowFrom` 流程 - `forceAccountBinding`:即使只存在一个账户,也要求显式账户绑定 -- `preferSessionLookupForAnnounceTarget`:在解析 announce 目标时优先使用会话查找 +- `preferSessionLookupForAnnounceTarget`:在解析 announce 目标时优先使用 session 查找 OpenClaw 还可以合并**外部渠道目录**(例如 MPM -注册表导出)。将一个 JSON 文件放到以下任一位置: +注册表导出)。将 JSON 文件放在以下任一路径: - `~/.openclaw/mpm/plugins.json` - `~/.openclaw/mpm/catalog.json` - `~/.openclaw/plugins/catalog.json` -或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向 -一个或多个 JSON 文件(以逗号/分号/`PATH` 分隔)。每个文件应 -包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的旧式别名。 +或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(以逗号/分号/`PATH` 分隔)。每个文件都应包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的遗留别名。 ## 上下文引擎插件 -上下文引擎插件拥有会话上下文编排能力,负责摄取、组装 -和压缩。可在你的插件中通过 -`api.registerContextEngine(id, factory)` 注册,然后用 -`plugins.slots.contextEngine` 选择活跃引擎。 +上下文引擎插件拥有 session 上下文编排,包括摄取、组装和压缩。请在你的插件中使用 +`api.registerContextEngine(id, factory)` 进行注册,然后通过 +`plugins.slots.contextEngine` 选择活动引擎。 -当你的插件需要替换或扩展默认上下文 -流水线,而不仅仅是添加 memory search 或钩子时,请使用它。 +当你的插件需要替换或扩展默认上下文流水线,而不仅仅是添加 memory 搜索或 hooks 时,请使用这种方式。 ```ts export default function (api) { @@ -1488,8 +1236,7 @@ export default function (api) { } ``` -如果你的引擎**不**拥有压缩算法,请保持 `compact()` -已实现,并显式委托给它: +如果你的引擎**不**拥有压缩算法,请保持 `compact()` 已实现,并显式委托: ```ts import { delegateCompactionToRuntime } from "openclaw/plugin-sdk/core"; @@ -1514,47 +1261,41 @@ export default function (api) { } ``` -## 添加新能力 +## 添加一个新能力 -当某个插件需要当前 API 无法适配的行为时,不要通过私有内部访问 -绕过插件系统。请添加缺失的能力。 +当插件需要当前 API 无法容纳的行为时,不要通过私有内部接入绕过插件系统。请添加缺失的能力。 推荐顺序: -1. 定义核心契约 - 决定哪些共享行为应由核心拥有:策略、回退、配置合并、 - 生命周期、面向渠道的语义以及运行时辅助工具形态。 -2. 添加类型化的插件注册/运行时表面 - 使用最小但有用的类型化能力表面扩展 `OpenClawPluginApi` 和/或 `api.runtime`。 -3. 接线核心 + 渠道/功能消费者 - 渠道和功能插件应通过核心消费新能力, - 而不是直接导入某个供应商实现。 -4. 注册供应商实现 - 然后让供应商插件针对该能力注册其后端。 +1. 定义 core 契约 + 确定哪些共享行为应由 core 拥有:策略、回退、配置合并、 + 生命周期、面向渠道的语义,以及运行时辅助工具形态。 +2. 添加类型化插件注册/运行时 surface + 以最小且有用的类型化能力 surface 扩展 `OpenClawPluginApi` 和/或 + `api.runtime`。 +3. 接线 core + 渠道/功能消费者 + 渠道和功能插件应通过 core 消费这个新能力,而不是直接导入某个 vendor 实现。 +4. 注册 vendor 实现 + 然后让 vendor 插件针对这个能力注册它们的后端。 5. 添加契约覆盖 - 添加测试,使所有权和注册形态在长期内保持明确。 + 增加测试,使归属和注册形状在长期内保持显式。 -这就是 OpenClaw 在保持主张性的同时,又不会被硬编码到某个 -提供商世界观中的方式。请参阅[能力扩展手册](/zh-CN/plugins/architecture) -获取具体的文件检查清单和完整示例。 +这正是 OpenClaw 能在保持鲜明主张的同时,不会被某一家 provider 的世界观所硬编码绑定的原因。请参见 [能力扩展手册](/zh-CN/plugins/architecture) 获取具体的文件清单和完整示例。 -### 能力检查清单 +### 能力清单 -当你添加一个新能力时,实现通常应同时触及以下 -表面: +当你添加一个新能力时,通常应当一并修改以下 surfaces: -- `src//types.ts` 中的核心契约类型 -- `src//runtime.ts` 中的核心 runner/运行时辅助工具 -- `src/plugins/types.ts` 中的插件 API 注册表面 +- `src//types.ts` 中的 core 契约类型 +- `src//runtime.ts` 中的 core runner/运行时辅助工具 +- `src/plugins/types.ts` 中的插件 API 注册 surface - `src/plugins/registry.ts` 中的插件注册表接线 -- 当功能/渠道插件需要消费它时, - `src/plugins/runtime/*` 中的插件运行时暴露 +- 当功能/渠道插件需要消费时,`src/plugins/runtime/*` 中的插件运行时暴露 - `src/test-utils/plugin-registration.ts` 中的捕获/测试辅助工具 -- `src/plugins/contracts/registry.ts` 中的所有权/契约断言 -- `docs/` 中的运维者/插件文档 +- `src/plugins/contracts/registry.ts` 中的归属/契约断言 +- `docs/` 中的操作员/插件文档 -如果其中某个表面缺失,通常意味着该能力 -尚未完全集成。 +如果这些 surface 中有某个缺失,通常意味着该能力尚未完成完整集成。 ### 能力模板 @@ -1592,7 +1333,7 @@ expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]); 这样规则就很简单: -- 核心拥有能力契约 + 编排 -- 供应商插件拥有供应商实现 +- core 拥有能力契约 + 编排 +- vendor 插件拥有 vendor 实现 - 功能/渠道插件消费运行时辅助工具 -- 契约测试让所有权保持明确 +- 契约测试让归属保持显式 diff --git a/docs/zh-CN/plugins/sdk-channel-plugins.md b/docs/zh-CN/plugins/sdk-channel-plugins.md index cd42d7d45..a372c6070 100644 --- a/docs/zh-CN/plugins/sdk-channel-plugins.md +++ b/docs/zh-CN/plugins/sdk-channel-plugins.md @@ -1,23 +1,23 @@ --- read_when: - 你正在构建一个新的消息渠道插件 - - 你想将 OpenClaw 连接到一个消息平台 - - 你需要了解 ChannelPlugin 适配器接口 + - 你想要将 OpenClaw 连接到一个消息平台 + - 你需要理解 ChannelPlugin 适配器表面 sidebarTitle: Channel Plugins summary: 构建 OpenClaw 消息渠道插件的分步指南 title: 构建渠道插件 x-i18n: - generated_at: "2026-04-06T18:55:42Z" + generated_at: "2026-04-07T06:53:58Z" model: gpt-5.4 provider: openai - source_hash: 25ac0591d9b0ba401925b29ae4b9572f18b2cbffc2b6ca6ed5252740e7cf97e9 + source_hash: 0aab6cc835b292c62e33c52ad0c35f989fb1a5b225511e8bdc2972feb3c64f09 source_path: plugins/sdk-channel-plugins.md workflow: 15 --- # 构建渠道插件 -本指南将带你构建一个把 OpenClaw 连接到消息平台的渠道插件。完成后,你将拥有一个可用的渠道,具备私信安全、配对、回复线程处理以及出站消息发送能力。 +本指南将带你完成一个渠道插件的构建过程,用于将 OpenClaw 连接到消息平台。完成后,你将拥有一个可用的渠道,支持私信安全、配对、回复线程和出站消息。 如果你之前还没有构建过任何 OpenClaw 插件,请先阅读 @@ -26,47 +26,47 @@ x-i18n: ## 渠道插件如何工作 -渠道插件不需要自带发送/编辑/回应工具。OpenClaw 在核心中保留了一个共享的 `message` 工具。你的插件负责: +渠道插件不需要它们自己的发送/编辑/响应工具。OpenClaw 在核心中保留了一个共享的 `message` 工具。你的插件负责: - **配置** — 账户解析和设置向导 - **安全** — 私信策略和允许列表 - **配对** — 私信批准流程 -- **会话语法** — 提供商特定的会话 ID 如何映射到底层聊天、线程 ID 和父级回退 +- **会话语法** — 提供商特定的会话 id 如何映射到基础聊天、线程 id 和父级回退 - **出站** — 向平台发送文本、媒体和投票 -- **线程处理** — 回复如何在线程中传递 +- **线程处理** — 回复如何形成线程 -核心负责共享消息工具、提示词接线、外层会话键形状、通用 `:thread:` 记录以及分发。 +核心负责共享的消息工具、提示词接线、外层会话键形状、通用的 `:thread:` 记录以及分发。 -如果你的平台在会话 ID 中存储了额外作用域,请将该解析逻辑保留在插件中,并使用 `messaging.resolveSessionConversation(...)`。这是将 `rawId` 映射为基础会话 ID、可选线程 ID、显式 `baseConversationId` 以及任意 `parentConversationCandidates` 的规范钩子。 -当你返回 `parentConversationCandidates` 时,请按从最窄父级到最宽泛/基础会话的顺序排列。 +如果你的平台在会话 id 中存储了额外作用域,请将该解析逻辑保留在插件中,并使用 `messaging.resolveSessionConversation(...)`。这是将 `rawId` 映射到基础会话 id、可选线程 id、显式 `baseConversationId` 以及任何 `parentConversationCandidates` 的规范钩子。 +当你返回 `parentConversationCandidates` 时,请保持它们按从最窄父级到最宽/基础会话的顺序排列。 -需要在渠道注册表启动前执行相同解析的内置插件,也可以暴露一个顶层 `session-key-api.ts` 文件,并提供匹配的 `resolveSessionConversation(...)` 导出。只有当运行时插件注册表尚不可用时,核心才会使用这个可安全用于启动流程的接口。 +需要在渠道注册表启动前进行相同解析的内置插件,也可以公开一个顶层 `session-key-api.ts` 文件,并导出匹配的 `resolveSessionConversation(...)`。只有在运行时插件注册表尚不可用时,核心才会使用这个可安全引导的表面。 -当插件只需要在通用/raw ID 之上增加父级回退时,`messaging.resolveParentConversationCandidates(...)` 仍可作为旧版兼容回退方案使用。如果两个钩子都存在,核心会优先使用 `resolveSessionConversation(...).parentConversationCandidates`,仅在该规范钩子省略它们时,才回退到 `resolveParentConversationCandidates(...)`。 +当插件只需要在通用/raw id 之上提供父级回退时,`messaging.resolveParentConversationCandidates(...)` 仍可作为旧版兼容回退使用。如果两个钩子都存在,核心会优先使用 `resolveSessionConversation(...).parentConversationCandidates`,只有在该规范钩子省略它们时,才会回退到 `resolveParentConversationCandidates(...)`。 ## 批准和渠道能力 -大多数渠道插件不需要专门的批准代码。 +大多数渠道插件不需要特定于批准的代码。 - 核心负责同一聊天中的 `/approve`、共享批准按钮负载以及通用回退投递。 -- 当渠道需要批准专用行为时,优先在渠道插件上使用一个 `approvalCapability` 对象。 -- `approvalCapability.authorizeActorAction` 和 `approvalCapability.getActionAvailabilityState` 是规范的批准鉴权接口。 -- 如果你的渠道暴露原生 exec 批准,即使原生传输完全位于 `approvalCapability.native` 下,也要实现 `approvalCapability.getActionAvailabilityState`。核心使用该可用性钩子来区分 `enabled` 与 `disabled`,判断发起渠道是否支持原生批准,并在原生客户端回退指引中包含该渠道。 +- 当渠道需要特定于批准的行为时,优先在渠道插件上使用一个 `approvalCapability` 对象。 +- `approvalCapability.authorizeActorAction` 和 `approvalCapability.getActionAvailabilityState` 是规范的批准鉴权接缝。 +- 如果你的渠道公开原生 exec 批准,请实现 `approvalCapability.getActionAvailabilityState`,即使原生传输完全位于 `approvalCapability.native` 下也是如此。核心使用该可用性钩子来区分 `enabled` 与 `disabled`、判断发起渠道是否支持原生批准,并在原生客户端回退指引中包含该渠道。 - 对于渠道特定的负载生命周期行为,例如隐藏重复的本地批准提示或在投递前发送输入中指示器,请使用 `outbound.shouldSuppressLocalPayloadPrompt` 或 `outbound.beforeDeliverPayload`。 -- 仅在进行原生批准路由或抑制回退时使用 `approvalCapability.delivery`。 -- 仅当某个渠道确实需要自定义批准负载而不是共享渲染器时,才使用 `approvalCapability.render`。 -- 当渠道希望在禁用路径回复中说明启用原生 exec 批准所需的确切配置项时,使用 `approvalCapability.describeExecApprovalSetup`。该钩子接收 `{ channel, channelLabel, accountId }`;具名账户渠道应渲染带账户作用域的路径,例如 `channels..accounts..execApprovals.*`,而不是顶层默认值。 -- 如果一个渠道可以从现有配置中推断出稳定的、类似所有者的私信身份,请使用 `openclaw/plugin-sdk/approval-runtime` 中的 `createResolvedApproverActionAuthAdapter` 来限制同一聊天中的 `/approve`,而无需添加批准专用的核心逻辑。 -- 如果一个渠道需要原生批准投递,请让渠道代码专注于目标规范化和传输钩子。使用 `openclaw/plugin-sdk/approval-runtime` 中的 `createChannelExecApprovalProfile`、`createChannelNativeOriginTargetResolver`、`createChannelApproverDmTargetResolver`、`createApproverRestrictedNativeApprovalCapability` 和 `createChannelNativeApprovalRuntime`,这样核心就能负责请求过滤、路由、去重、过期和 Gateway 网关订阅。 -- 原生批准渠道必须通过这些辅助工具同时传递 `accountId` 和 `approvalKind`。`accountId` 可将多账户批准策略限定到正确的机器人账户,`approvalKind` 则让 exec 与插件批准行为在渠道中可用,而无需在核心中写死分支。 -- 端到端保留已投递的批准 ID 类型。原生客户端不应根据渠道本地状态去猜测或重写 exec 与插件批准路由。 -- 不同的批准类型可以有意暴露不同的原生接口。 +- 仅将 `approvalCapability.delivery` 用于原生批准路由或回退抑制。 +- 仅当渠道确实需要自定义批准负载而不是共享渲染器时,才使用 `approvalCapability.render`。 +- 当渠道希望禁用路径回复解释启用原生 exec 批准所需的确切配置项时,请使用 `approvalCapability.describeExecApprovalSetup`。该钩子接收 `{ channel, channelLabel, accountId }`;具名账户渠道应渲染账户作用域路径,例如 `channels..accounts..execApprovals.*`,而不是顶层默认值。 +- 如果渠道可以从现有配置推断出稳定的类似所有者的私信身份,请使用 `openclaw/plugin-sdk/approval-runtime` 中的 `createResolvedApproverActionAuthAdapter` 来限制同一聊天中的 `/approve`,而无需添加特定于批准的核心逻辑。 +- 如果渠道需要原生批准投递,请让渠道代码专注于目标规范化和传输钩子。使用 `openclaw/plugin-sdk/approval-runtime` 中的 `createChannelExecApprovalProfile`、`createChannelNativeOriginTargetResolver`、`createChannelApproverDmTargetResolver`、`createApproverRestrictedNativeApprovalCapability` 和 `createChannelNativeApprovalRuntime`,这样核心就可以负责请求过滤、路由、去重、过期和 Gateway 网关订阅。 +- 原生批准渠道必须通过这些辅助函数同时路由 `accountId` 和 `approvalKind`。`accountId` 让多账户批准策略限定在正确的机器人账户范围内,而 `approvalKind` 让 exec 与插件批准行为在渠道中可用,而无需在核心中写死分支。 +- 在端到端过程中保留已投递的批准 id 类型。原生客户端不应根据渠道本地状态猜测或重写 exec 与插件批准路由。 +- 不同的批准类型可以有意公开不同的原生表面。 当前内置示例: - - Slack 对 exec 和插件 ID 都保留原生批准路由能力。 - - Matrix 仅为 exec 批准保留原生私信/渠道路由,而将插件批准保留在共享的同一聊天 `/approve` 路径上。 -- `createApproverRestrictedNativeApprovalAdapter` 仍作为兼容封装存在,但新代码应优先使用 capability 构建器,并在插件上暴露 `approvalCapability`。 + - Slack 为 exec 和插件 id 都保留原生批准路由。 + - Matrix 仅为 exec 批准保留原生私信/渠道路由,并将插件批准保留在共享的同一聊天 `/approve` 路径上。 +- `createApproverRestrictedNativeApprovalAdapter` 仍然作为兼容包装器存在,但新代码应优先使用能力构建器,并在插件上公开 `approvalCapability`。 -对于高频渠道入口点,当你只需要这一系列中的某一部分时,优先使用更窄的运行时子路径: +对于高频渠道入口点,如果你只需要该系列中的某一部分,请优先使用更窄的运行时子路径: - `openclaw/plugin-sdk/approval-auth-runtime` - `openclaw/plugin-sdk/approval-client-runtime` @@ -74,60 +74,130 @@ x-i18n: - `openclaw/plugin-sdk/approval-native-runtime` - `openclaw/plugin-sdk/approval-reply-runtime` -同样地,当你不需要更宽泛的总入口接口时,优先使用 `openclaw/plugin-sdk/setup-runtime`、 -`openclaw/plugin-sdk/setup-adapter-runtime`、 -`openclaw/plugin-sdk/reply-runtime`、 -`openclaw/plugin-sdk/reply-dispatch-runtime`、 -`openclaw/plugin-sdk/reply-reference` 和 -`openclaw/plugin-sdk/reply-chunking`。 +同样地,当你不需要更宽泛的总括表面时,请优先使用 `openclaw/plugin-sdk/setup-runtime`、`openclaw/plugin-sdk/setup-adapter-runtime`、`openclaw/plugin-sdk/reply-runtime`、`openclaw/plugin-sdk/reply-dispatch-runtime`、`openclaw/plugin-sdk/reply-reference` 和 `openclaw/plugin-sdk/reply-chunking`。 -特别是在设置方面: +对于设置,具体来说: -- `openclaw/plugin-sdk/setup-runtime` 覆盖运行时安全的设置辅助工具: - 可安全导入的设置补丁适配器(`createPatchedAccountSetupAdapter`、 - `createEnvPatchedAccountSetupAdapter`、 - `createSetupInputPresenceValidator`)、查找说明输出、 - `promptResolvedAllowFrom`、`splitSetupEntries`,以及委托式 - setup-proxy 构建器 -- `openclaw/plugin-sdk/setup-adapter-runtime` 是面向环境变量的窄适配器接口, - 用于 `createEnvPatchedAccountSetupAdapter` -- `openclaw/plugin-sdk/channel-setup` 覆盖可选安装设置 - 构建器以及一些设置安全的基础能力: +- `openclaw/plugin-sdk/setup-runtime` 覆盖运行时安全的设置辅助函数: + 导入安全的设置补丁适配器(`createPatchedAccountSetupAdapter`、`createEnvPatchedAccountSetupAdapter`、`createSetupInputPresenceValidator`)、查询说明输出、 + `promptResolvedAllowFrom`、`splitSetupEntries` 以及委托式 setup-proxy 构建器 +- `openclaw/plugin-sdk/setup-adapter-runtime` 是面向环境变量的窄适配器接缝,用于 `createEnvPatchedAccountSetupAdapter` +- `openclaw/plugin-sdk/channel-setup` 覆盖可选安装的设置构建器以及一些设置安全的基础能力: `createOptionalChannelSetupSurface`、`createOptionalChannelSetupAdapter`、 -如果你的渠道支持由环境变量驱动的设置或认证,并且通用启动/配置流程应在运行时加载前知道这些环境变量名称,请在插件清单中通过 `channelEnvVars` 声明它们。渠道运行时中的 `envVars` 或本地常量仅保留给面向运维人员的文案使用。 +如果你的渠道支持由环境变量驱动的设置或认证,并且通用启动/配置流程应在运行时加载前知道这些环境变量名称,请在插件清单中通过 `channelEnvVars` 声明它们。将渠道运行时 `envVars` 或本地常量仅用于面向操作员的文案。 `createOptionalChannelSetupWizard`、`DEFAULT_ACCOUNT_ID`、 `createTopLevelChannelDmPolicy`、`setSetupChannelEnabled` 和 `splitSetupEntries` -- 仅当你还需要更重的共享设置/配置辅助工具时,才使用更宽泛的 `openclaw/plugin-sdk/setup` 接口,例如 - `moveSingleAccountChannelSectionToDefaultAccount(...)` +- 仅当你还需要更重的共享设置/配置辅助函数,例如 + `moveSingleAccountChannelSectionToDefaultAccount(...)` 时,才使用更宽泛的 `openclaw/plugin-sdk/setup` 接缝 -如果你的渠道只想在设置界面中提示“请先安装此插件”,优先使用 `createOptionalChannelSetupSurface(...)`。生成的适配器/向导会在配置写入和最终完成时采用封闭失败策略,并在校验、完成以及文档链接文案中复用同一条“需要安装”的消息。 +如果你的渠道只想在设置表面中展示“请先安装此插件”,优先使用 `createOptionalChannelSetupSurface(...)`。生成的适配器/向导会在配置写入和最终化上默认关闭,并且会在校验、最终化和文档链接文案中复用同一条安装要求消息。 -对于其他高频渠道路径,也请优先使用窄接口辅助工具,而不是更宽泛的旧版接口: +对于其他高频渠道路径,也应优先使用窄辅助函数,而不是更宽泛的旧版表面: - `openclaw/plugin-sdk/account-core`、 `openclaw/plugin-sdk/account-id`、 `openclaw/plugin-sdk/account-resolution` 和 `openclaw/plugin-sdk/account-helpers`,用于多账户配置和默认账户回退 - `openclaw/plugin-sdk/inbound-envelope` 和 - `openclaw/plugin-sdk/inbound-reply-dispatch`,用于入站路由/信封以及记录并分发的接线 + `openclaw/plugin-sdk/inbound-reply-dispatch`,用于入站路由/封装以及记录与分发接线 - `openclaw/plugin-sdk/messaging-targets`,用于目标解析/匹配 - `openclaw/plugin-sdk/outbound-media` 和 `openclaw/plugin-sdk/outbound-runtime`,用于媒体加载以及出站身份/发送委托 - `openclaw/plugin-sdk/thread-bindings-runtime`,用于线程绑定生命周期和适配器注册 -- 仅当仍需要旧版智能体/媒体负载字段布局时,才使用 `openclaw/plugin-sdk/agent-media-payload` -- `openclaw/plugin-sdk/telegram-command-config`,用于 Telegram 自定义命令规范化、重复/冲突校验,以及具备稳定回退能力的命令配置契约 +- 仅当仍然需要旧版智能体/媒体负载字段布局时,才使用 `openclaw/plugin-sdk/agent-media-payload` +- `openclaw/plugin-sdk/telegram-command-config`,用于 Telegram 自定义命令规范化、重复/冲突校验,以及回退稳定的命令配置契约 -仅认证渠道通常可以停留在默认路径:核心处理批准,而插件只需暴露出站/认证能力。像 Matrix、Slack、Telegram 以及自定义聊天传输这类原生批准渠道,应使用共享的原生辅助工具,而不是自行实现批准生命周期。 +仅认证渠道通常可以停留在默认路径:核心处理批准,插件只需公开出站/认证能力。像 Matrix、Slack、Telegram 和自定义聊天传输这类原生批准渠道,应使用共享的原生辅助函数,而不是自行实现批准生命周期。 -## 操作演练 +## 入站提及策略 + +请将入站提及处理拆分为两层: + +- 插件拥有的证据收集 +- 共享策略评估 + +共享层请使用 `openclaw/plugin-sdk/channel-inbound`。 + +适合放在插件本地逻辑中的内容: + +- 回复机器人检测 +- 引用机器人检测 +- 线程参与检查 +- 服务/系统消息排除 +- 证明机器人参与所需的平台原生缓存 + +适合共享辅助函数处理的内容: + +- `requireMention` +- 显式提及结果 +- 隐式提及允许列表 +- 命令绕过 +- 最终跳过决策 + +推荐流程: + +1. 计算本地提及事实。 +2. 将这些事实传给 `resolveInboundMentionDecision({ facts, policy })`。 +3. 在你的入站闸门中使用 `decision.effectiveWasMentioned`、`decision.shouldBypassMention` 和 `decision.shouldSkip`。 + +```typescript +import { + implicitMentionKindWhen, + matchesMentionWithExplicit, + resolveInboundMentionDecision, +} from "openclaw/plugin-sdk/channel-inbound"; + +const mentionMatch = matchesMentionWithExplicit(text, { + mentionRegexes, + mentionPatterns, +}); + +const facts = { + canDetectMention: true, + wasMentioned: mentionMatch.matched, + hasAnyMention: mentionMatch.hasExplicitMention, + implicitMentionKinds: [ + ...implicitMentionKindWhen("reply_to_bot", isReplyToBot), + ...implicitMentionKindWhen("quoted_bot", isQuoteOfBot), + ], +}; + +const decision = resolveInboundMentionDecision({ + facts, + policy: { + isGroup, + requireMention, + allowedImplicitMentionKinds: requireExplicitMention ? [] : ["reply_to_bot", "quoted_bot"], + allowTextCommands, + hasControlCommand, + commandAuthorized, + }, +}); + +if (decision.shouldSkip) return; +``` + +`api.runtime.channel.mentions` 为已经依赖运行时注入的内置渠道插件公开了同样的共享提及辅助函数: + +- `buildMentionRegexes` +- `matchesMentionPatterns` +- `matchesMentionWithExplicit` +- `implicitMentionKindWhen` +- `resolveInboundMentionDecision` + +较旧的 `resolveMentionGating*` 辅助函数仍保留在 +`openclaw/plugin-sdk/channel-inbound` 中,但仅作为兼容性导出。新代码应使用 +`resolveInboundMentionDecision({ facts, policy })`。 + +## 演练 - 创建标准插件文件。`package.json` 中的 `channel` 字段会将它标记为渠道插件。有关完整的包元数据接口,请参见 + 创建标准插件文件。`package.json` 中的 `channel` 字段决定了这是一个渠道插件。完整的包元数据表面请参见 [插件设置和配置](/zh-CN/plugins/sdk-setup#openclawchannel): @@ -178,7 +248,7 @@ x-i18n: - `ChannelPlugin` 接口包含许多可选适配器接口。先从最小集合开始——`id` 和 `setup`——然后按需添加适配器。 + `ChannelPlugin` 接口有很多可选适配器表面。先从最小集合开始——`id` 和 `setup`——然后按需添加适配器。 创建 `src/channel.ts`: @@ -273,17 +343,17 @@ x-i18n: }); ``` - - 你无需手动实现底层适配器接口,而是传入声明式选项,由构建器进行组合: + + 你无需手动实现底层适配器接口,而是传入声明式选项,由构建器负责组合它们: - | 选项 | 它负责接线的内容 | + | 选项 | 它接线的内容 | | --- | --- | - | `security.dm` | 从配置字段解析带作用域的私信安全策略 | - | `pairing.text` | 通过验证码交换实现基于文本的私信配对流程 | - | `threading` | 回复模式解析器(固定、账户作用域或自定义) | + | `security.dm` | 从配置字段解析的作用域化私信安全解析器 | + | `pairing.text` | 基于文本代码交换的私信配对流程 | + | `threading` | reply-to 模式解析器(固定、账户作用域或自定义) | | `outbound.attachedResults` | 返回结果元数据(消息 ID)的发送函数 | - 如果你需要完全控制,也可以直接传入原始适配器对象,而不是这些声明式选项。 + 如果你需要完全控制,也可以传入原始适配器对象,而不是这些声明式选项。 @@ -324,16 +394,15 @@ x-i18n: }); ``` - 将渠道自有的 CLI 描述符放在 `registerCliMetadata(...)` 中,这样 OpenClaw 就能在不激活完整渠道运行时的情况下,在根帮助中显示它们;而常规完整加载仍会获取相同描述符以进行真实命令注册。将 `registerFull(...)` 保留给仅运行时的工作。 - 如果 `registerFull(...)` 注册 Gateway 网关 RPC 方法,请使用插件专属前缀。核心管理命名空间(`config.*`、 - `exec.approvals.*`、`wizard.*`、`update.*`)保留给系统使用,并始终解析为 `operator.admin`。 + 将渠道拥有的 CLI 描述符放在 `registerCliMetadata(...)` 中,这样 OpenClaw 就能在不激活完整渠道运行时的情况下,在根帮助中显示它们;而正常完整加载时,仍会获取相同描述符来完成真实命令注册。将 `registerFull(...)` 保留给仅运行时工作。 + 如果 `registerFull(...)` 注册 Gateway 网关 RPC 方法,请使用插件特定前缀。核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)保持保留,并始终解析到 `operator.admin`。 `defineChannelPluginEntry` 会自动处理注册模式拆分。有关所有选项,请参见 [入口点](/zh-CN/plugins/sdk-entrypoints#definechannelpluginentry)。 - 创建 `setup-entry.ts`,用于新手引导期间的轻量加载: + 为新手引导期间的轻量加载创建 `setup-entry.ts`: ```typescript setup-entry.ts import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; @@ -342,14 +411,13 @@ x-i18n: export default defineSetupPluginEntry(acmeChatPlugin); ``` - 当渠道被禁用或尚未配置时,OpenClaw 会加载这个入口而不是完整入口。 - 这样可以避免在设置流程中拉入沉重的运行时代码。详情请参见 - [设置和配置](/zh-CN/plugins/sdk-setup#setup-entry)。 + 当渠道被禁用或尚未配置时,OpenClaw 会加载它,而不是完整入口点。 + 这样可以避免在设置流程中拉取沉重的运行时代码。详情请参见 [设置和配置](/zh-CN/plugins/sdk-setup#setup-entry)。 - 你的插件需要从平台接收入站消息,并将其转发给 OpenClaw。典型模式是使用 webhook 校验请求,然后通过你的渠道入站处理器进行分发: + 你的插件需要从平台接收入站消息,并将它们转发给 OpenClaw。典型模式是使用一个 webhook 来验证请求,然后通过你的渠道入站处理器进行分发: ```typescript registerFull(api) { @@ -373,15 +441,15 @@ x-i18n: ``` - 入站消息处理是渠道特定的。每个渠道插件都负责自己的入站处理管线。请查看内置渠道插件 - (例如 Microsoft Teams 或 Google Chat 插件包)了解真实模式。 + 入站消息处理是渠道特定的。每个渠道插件都拥有自己的入站流水线。请查看内置渠道插件 + (例如 Microsoft Teams 或 Google Chat 插件包)以了解真实模式。 -编写同目录测试文件 `src/channel.test.ts`: +编写同目录测试到 `src/channel.test.ts`: ```typescript src/channel.test.ts import { describe, it, expect } from "vitest"; @@ -419,7 +487,7 @@ x-i18n: pnpm test -- /acme-chat/ ``` - 有关共享测试辅助工具,请参见[测试](/zh-CN/plugins/sdk-testing)。 + 共享测试辅助函数请参见 [测试](/zh-CN/plugins/sdk-testing)。 @@ -453,19 +521,18 @@ x-i18n: inferTargetChatType、looksLikeId、resolveTarget - - TTS、STT、媒体、通过 api.runtime 使用 subagent + + TTS、STT、媒体、通过 api.runtime 的子智能体 -一些内置辅助接口仍然存在,用于内置插件维护和兼容性。 -它们不是新渠道插件的推荐模式;除非你正在直接维护该内置插件系列,否则请优先使用通用 SDK 接口中的 channel/setup/reply/runtime 子路径。 +一些内置辅助函数接缝仍然存在,用于内置插件维护和兼容性。它们不是新渠道插件的推荐模式;除非你是在直接维护该内置插件系列,否则请优先使用通用 SDK 表面中的 channel/setup/reply/runtime 子路径。 ## 后续步骤 - [提供商插件](/zh-CN/plugins/sdk-provider-plugins) — 如果你的插件也提供模型 -- [SDK 概览](/zh-CN/plugins/sdk-overview) — 完整子路径导入参考 -- [SDK 测试](/zh-CN/plugins/sdk-testing) — 测试工具和契约测试 +- [SDK 概览](/zh-CN/plugins/sdk-overview) — 完整的子路径导入参考 +- [插件 SDK 测试](/zh-CN/plugins/sdk-testing) — 测试工具和契约测试 - [插件清单](/zh-CN/plugins/manifest) — 完整清单模式 diff --git a/docs/zh-CN/plugins/sdk-overview.md b/docs/zh-CN/plugins/sdk-overview.md index 78382c763..3ad8eac96 100644 --- a/docs/zh-CN/plugins/sdk-overview.md +++ b/docs/zh-CN/plugins/sdk-overview.md @@ -1,29 +1,29 @@ --- read_when: - 你需要知道应从哪个 SDK 子路径导入 - - 你想查看 OpenClawPluginApi 上所有注册方法的参考 + - 你想查阅 OpenClawPluginApi 上所有注册方法的参考 - 你正在查找某个特定的 SDK 导出 sidebarTitle: SDK Overview summary: 导入映射、注册 API 参考和 SDK 架构 title: 插件 SDK 概览 x-i18n: - generated_at: "2026-04-07T06:41:32Z" + generated_at: "2026-04-07T06:54:09Z" model: gpt-5.4 provider: openai - source_hash: be651251bc1d8fc6548cb9efd4b7940be093f7f7cdd70d94dc31d5a1ebde80f3 + source_hash: 533bc3027ed8ad50b706518a4f58e75f6ef717fc8b36f242e928cae54d20985f source_path: plugins/sdk-overview.md workflow: 15 --- # 插件 SDK 概览 -插件 SDK 是插件与核心之间的类型化契约。本页是关于**应导入什么**以及**你可以注册什么**的参考。 +插件 SDK 是插件与核心之间的类型化契约。本页是关于**导入什么**以及**你可以注册什么**的参考。 **在找操作指南吗?** - 第一个插件?从[入门指南](/zh-CN/plugins/building-plugins)开始 - - 渠道插件?参见[渠道插件](/zh-CN/plugins/sdk-channel-plugins) - - 提供商插件?参见[提供商插件](/zh-CN/plugins/sdk-provider-plugins) + - 渠道插件?请参阅[渠道插件](/zh-CN/plugins/sdk-channel-plugins) + - 提供商插件?请参阅[提供商插件](/zh-CN/plugins/sdk-provider-plugins) ## 导入约定 @@ -35,19 +35,19 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; ``` -每个子路径都是一个小型、自包含的模块。这可以保持快速启动,并防止循环依赖问题。对于特定于渠道的入口/构建辅助工具,优先使用 `openclaw/plugin-sdk/channel-core`;将 `openclaw/plugin-sdk/core` 保留给更广泛的总括性接口和共享辅助工具,例如 `buildChannelConfigSchema`。 +每个子路径都是一个小型、独立的模块。这样可以保持快速启动,并防止循环依赖问题。对于特定于渠道的入口/构建辅助工具,优先使用 `openclaw/plugin-sdk/channel-core`;将 `openclaw/plugin-sdk/core` 保留给更广泛的总括性接口和共享辅助工具,例如 `buildChannelConfigSchema`。 -不要添加或依赖带有提供商名称的便捷接口层,例如 `openclaw/plugin-sdk/slack`、`openclaw/plugin-sdk/discord`、`openclaw/plugin-sdk/signal`、`openclaw/plugin-sdk/whatsapp`,或带有渠道品牌的辅助接口层。内置插件应在自己的 `api.ts` 或 `runtime-api.ts` barrel 文件中组合通用 SDK 子路径,而核心则应使用这些插件本地的 barrel 文件,或者仅在需求确实跨渠道时添加一个狭义的通用 SDK 契约。 +不要添加或依赖带有提供商名称的便捷接口,例如 `openclaw/plugin-sdk/slack`、`openclaw/plugin-sdk/discord`、`openclaw/plugin-sdk/signal`、`openclaw/plugin-sdk/whatsapp`,或带有渠道品牌的辅助接口。内置插件应在它们自己的 `api.ts` 或 `runtime-api.ts` barrel 文件中组合通用 SDK 子路径,而核心则应使用这些插件本地 barrel,或在需求确实跨渠道时添加一个窄范围的通用 SDK 契约。 -生成的导出映射仍然包含一小部分内置插件辅助接口层,例如 `plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、`plugin-sdk/zalo-setup` 和 `plugin-sdk/matrix*`。这些子路径仅为内置插件维护和兼容性而存在;它们被有意省略在下面的常用表格之外,也不是新第三方插件的推荐导入路径。 +生成的导出映射仍包含一小组内置插件辅助接口,例如 `plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、`plugin-sdk/zalo-setup` 和 `plugin-sdk/matrix*`。这些子路径仅用于内置插件维护和兼容性;它们在下方的常用表格中被有意省略,也不是新的第三方插件推荐使用的导入路径。 ## 子路径参考 -最常用的子路径,按用途分组。包含 200 多个子路径的生成完整列表位于 `scripts/lib/plugin-sdk-entrypoints.json`。 +最常用的子路径,按用途分组。包含 200 多个子路径的完整生成列表位于 `scripts/lib/plugin-sdk-entrypoints.json`。 -保留的内置插件辅助子路径仍会出现在该生成列表中。除非某个文档页面明确将其作为公共接口推广,否则应将其视为实现细节/兼容性接口。 +保留的内置插件辅助子路径仍会出现在该生成列表中。除非某个文档页面明确将其作为公共接口推广,否则请将它们视为实现细节/兼容性接口。 -### 插件入口点 +### 插件入口 | 子路径 | 关键导出 | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | @@ -62,127 +62,127 @@ import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; | --- | --- | | `plugin-sdk/channel-core` | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | | `plugin-sdk/config-schema` | 根 `openclaw.json` Zod schema 导出(`OpenClawSchema`) | - | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`, `createOptionalChannelSetupWizard`,以及 `DEFAULT_ACCOUNT_ID`, `createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, `splitSetupEntries` | - | `plugin-sdk/setup` | 共享设置向导辅助工具、allowlist 提示、设置状态构建器 | - | `plugin-sdk/setup-runtime` | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | + | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface`、`createOptionalChannelSetupAdapter`、`createOptionalChannelSetupWizard`,以及 `DEFAULT_ACCOUNT_ID`、`createTopLevelChannelDmPolicy`、`setSetupChannelEnabled`、`splitSetupEntries` | + | `plugin-sdk/setup` | 共享的设置向导辅助工具、allowlist 提示、设置状态构建器 | + | `plugin-sdk/setup-runtime` | `createPatchedAccountSetupAdapter`、`createEnvPatchedAccountSetupAdapter`、`createSetupInputPresenceValidator`、`noteChannelLookupFailure`、`noteChannelLookupSummary`、`promptResolvedAllowFrom`、`splitSetupEntries`、`createAllowlistSetupWizardProxy`、`createDelegatedSetupWizardProxy` | | `plugin-sdk/setup-adapter-runtime` | `createEnvPatchedAccountSetupAdapter` | - | `plugin-sdk/setup-tools` | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | - | `plugin-sdk/account-core` | 多账户配置/操作门控辅助工具、默认账户回退辅助工具 | + | `plugin-sdk/setup-tools` | `formatCliCommand`、`detectBinary`、`extractArchive`、`resolveBrewExecutable`、`formatDocsLink`、`CONFIG_DIR` | + | `plugin-sdk/account-core` | 多账户配置/动作门控辅助工具、默认账户回退辅助工具 | | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`、账户 ID 规范化辅助工具 | | `plugin-sdk/account-resolution` | 账户查找 + 默认回退辅助工具 | - | `plugin-sdk/account-helpers` | 狭义账户列表/账户操作辅助工具 | + | `plugin-sdk/account-helpers` | 窄范围的账户列表/账户操作辅助工具 | | `plugin-sdk/channel-pairing` | `createChannelPairingController` | | `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` | | `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` | | `plugin-sdk/channel-config-schema` | 渠道配置 schema 类型 | - | `plugin-sdk/telegram-command-config` | Telegram 自定义命令规范化/校验辅助工具,带内置契约回退 | + | `plugin-sdk/telegram-command-config` | Telegram 自定义命令规范化/验证辅助工具,带内置契约回退 | | `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` | | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink` | - | `plugin-sdk/inbound-envelope` | 共享入站路由 + envelope 构建辅助工具 | - | `plugin-sdk/inbound-reply-dispatch` | 共享入站记录与分发辅助工具 | + | `plugin-sdk/inbound-envelope` | 共享的入站路由 + envelope 构建辅助工具 | + | `plugin-sdk/inbound-reply-dispatch` | 共享的入站记录与分发辅助工具 | | `plugin-sdk/messaging-targets` | 目标解析/匹配辅助工具 | - | `plugin-sdk/outbound-media` | 共享出站媒体加载辅助工具 | + | `plugin-sdk/outbound-media` | 共享的出站媒体加载辅助工具 | | `plugin-sdk/outbound-runtime` | 出站身份/发送委托辅助工具 | - | `plugin-sdk/thread-bindings-runtime` | 线程绑定生命周期和适配器辅助工具 | + | `plugin-sdk/thread-bindings-runtime` | 线程绑定生命周期与适配器辅助工具 | | `plugin-sdk/agent-media-payload` | 旧版智能体媒体负载构建器 | | `plugin-sdk/conversation-runtime` | 会话/线程绑定、配对和已配置绑定辅助工具 | | `plugin-sdk/runtime-config-snapshot` | 运行时配置快照辅助工具 | | `plugin-sdk/runtime-group-policy` | 运行时群组策略解析辅助工具 | - | `plugin-sdk/channel-status` | 共享渠道状态快照/摘要辅助工具 | - | `plugin-sdk/channel-config-primitives` | 狭义渠道配置 schema 基元 | + | `plugin-sdk/channel-status` | 共享的渠道状态快照/摘要辅助工具 | + | `plugin-sdk/channel-config-primitives` | 窄范围的渠道配置 schema 基元 | | `plugin-sdk/channel-config-writes` | 渠道配置写入授权辅助工具 | - | `plugin-sdk/channel-plugin-common` | 共享渠道插件前导导出 | + | `plugin-sdk/channel-plugin-common` | 共享的渠道插件前导导出 | | `plugin-sdk/allowlist-config-edit` | allowlist 配置编辑/读取辅助工具 | - | `plugin-sdk/group-access` | 共享群组访问决策辅助工具 | - | `plugin-sdk/direct-dm` | 共享直接私信凭证/保护辅助工具 | + | `plugin-sdk/group-access` | 共享的群组访问决策辅助工具 | + | `plugin-sdk/direct-dm` | 共享的直接私信认证/保护辅助工具 | | `plugin-sdk/interactive-runtime` | 交互式回复负载规范化/归约辅助工具 | - | `plugin-sdk/channel-inbound` | 去抖动、提及匹配、envelope 辅助工具 | + | `plugin-sdk/channel-inbound` | 入站防抖、提及匹配、提及策略辅助工具,以及 envelope 辅助工具 | | `plugin-sdk/channel-send-result` | 回复结果类型 | - | `plugin-sdk/channel-actions` | `createMessageToolButtonsSchema`, `createMessageToolCardSchema` | + | `plugin-sdk/channel-actions` | `createMessageToolButtonsSchema`、`createMessageToolCardSchema` | | `plugin-sdk/channel-targets` | 目标解析/匹配辅助工具 | | `plugin-sdk/channel-contract` | 渠道契约类型 | | `plugin-sdk/channel-feedback` | 反馈/反应接线 | - | `plugin-sdk/channel-secret-runtime` | 狭义 secret 契约辅助工具,例如 `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment` 和 secret target 类型 | + | `plugin-sdk/channel-secret-runtime` | 窄范围的密钥契约辅助工具,例如 `collectSimpleChannelFieldAssignments`、`getChannelSurface`、`pushAssignment` 和密钥目标类型 | | 子路径 | 关键导出 | | --- | --- | | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | - | `plugin-sdk/provider-setup` | 精选本地/自托管提供商设置辅助工具 | - | `plugin-sdk/self-hosted-provider-setup` | 聚焦于 OpenAI 兼容自托管提供商的设置辅助工具 | + | `plugin-sdk/provider-setup` | 精选的本地/自托管提供商设置辅助工具 | + | `plugin-sdk/self-hosted-provider-setup` | 面向 OpenAI 兼容自托管提供商设置的聚焦辅助工具 | | `plugin-sdk/cli-backend` | CLI 后端默认值 + watchdog 常量 | - | `plugin-sdk/provider-auth-runtime` | 面向提供商插件的运行时 API key 解析辅助工具 | - | `plugin-sdk/provider-auth-api-key` | API key 新手引导/profile 写入辅助工具,例如 `upsertApiKeyProfile` | - | `plugin-sdk/provider-auth-result` | 标准 OAuth auth-result 构建器 | - | `plugin-sdk/provider-auth-login` | 面向提供商插件的共享交互式登录辅助工具 | - | `plugin-sdk/provider-env-vars` | 提供商凭证环境变量查找辅助工具 | - | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile`, `upsertApiKeyProfile`, `writeOAuthCredentials` | - | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`、共享 replay-policy 构建器、provider-endpoint 辅助工具,以及诸如 `normalizeNativeXaiModelId` 之类的 model-id 规范化辅助工具 | - | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | - | `plugin-sdk/provider-http` | 通用提供商 HTTP/endpoint 能力辅助工具 | - | `plugin-sdk/provider-web-fetch` | Web-fetch 提供商注册/缓存辅助工具 | - | `plugin-sdk/provider-web-search-contract` | 狭义 Web 搜索配置/凭证契约辅助工具,例如 `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`,以及作用域化凭证 setter/getter | + | `plugin-sdk/provider-auth-runtime` | 提供商插件的运行时 API 密钥解析辅助工具 | + | `plugin-sdk/provider-auth-api-key` | API 密钥新手引导/profile 写入辅助工具,例如 `upsertApiKeyProfile` | + | `plugin-sdk/provider-auth-result` | 标准 OAuth 认证结果构建器 | + | `plugin-sdk/provider-auth-login` | 提供商插件的共享交互式登录辅助工具 | + | `plugin-sdk/provider-env-vars` | 提供商认证环境变量查找辅助工具 | + | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`、`ensureApiKeyFromOptionEnvOrPrompt`、`upsertAuthProfile`、`upsertApiKeyProfile`、`writeOAuthCredentials` | + | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`、`buildProviderReplayFamilyHooks`、`normalizeModelCompat`、共享 replay-policy 构建器、提供商端点辅助工具,以及像 `normalizeNativeXaiModelId` 这样的模型 ID 规范化辅助工具 | + | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`、`buildSingleProviderApiKeyCatalog`、`supportsNativeStreamingUsageCompat`、`applyProviderNativeStreamingUsageCompat` | + | `plugin-sdk/provider-http` | 通用提供商 HTTP/端点能力辅助工具 | + | `plugin-sdk/provider-web-fetch` | Web 抓取提供商注册/缓存辅助工具 | + | `plugin-sdk/provider-web-search-contract` | 窄范围的 Web 搜索配置/凭证契约辅助工具,例如 `enablePluginInConfig`、`resolveProviderWebSearchPluginConfig` 以及作用域凭证 setter/getter | | `plugin-sdk/provider-web-search` | Web 搜索提供商注册/缓存/运行时辅助工具 | - | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`, Gemini schema 清理 + 诊断,以及 xAI 兼容辅助工具,例如 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` | - | `plugin-sdk/provider-usage` | `fetchClaudeUsage` 及类似工具 | - | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`、流包装器类型,以及共享 Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot 包装器辅助工具 | + | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`、`buildProviderToolCompatFamilyHooks`、Gemini schema 清理 + 诊断,以及 xAI 兼容性辅助工具,例如 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` | + | `plugin-sdk/provider-usage` | `fetchClaudeUsage` 及类似功能 | + | `plugin-sdk/provider-stream` | `ProviderStreamFamily`、`buildProviderStreamFamilyHooks`、`composeProviderStreamWrappers`、流包装器类型,以及共享的 Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot 包装器辅助工具 | | `plugin-sdk/provider-onboard` | 新手引导配置补丁辅助工具 | | `plugin-sdk/global-singleton` | 进程本地 singleton/map/cache 辅助工具 | - + | 子路径 | 关键导出 | | --- | --- | | `plugin-sdk/command-auth` | `resolveControlCommandGate`、命令注册表辅助工具、发送者授权辅助工具 | - | `plugin-sdk/approval-auth-runtime` | 审批人解析和同聊天操作鉴权辅助工具 | - | `plugin-sdk/approval-client-runtime` | 原生 exec 审批 profile/filter 辅助工具 | + | `plugin-sdk/approval-auth-runtime` | 审批人解析和同聊天动作认证辅助工具 | + | `plugin-sdk/approval-client-runtime` | 原生 exec 审批配置文件/过滤辅助工具 | | `plugin-sdk/approval-delivery-runtime` | 原生审批能力/投递适配器 | | `plugin-sdk/approval-native-runtime` | 原生审批目标 + 账户绑定辅助工具 | | `plugin-sdk/approval-reply-runtime` | exec/插件审批回复负载辅助工具 | - | `plugin-sdk/command-auth-native` | 原生命令鉴权 + 原生会话目标辅助工具 | + | `plugin-sdk/command-auth-native` | 原生命令认证 + 原生会话目标辅助工具 | | `plugin-sdk/command-detection` | 共享命令检测辅助工具 | - | `plugin-sdk/command-surface` | 命令体规范化和命令表层辅助工具 | + | `plugin-sdk/command-surface` | 命令体规范化和命令表面辅助工具 | | `plugin-sdk/allow-from` | `formatAllowFromLowercase` | - | `plugin-sdk/channel-secret-runtime` | 面向渠道/插件 secret 表层的狭义 secret 契约收集辅助工具 | - | `plugin-sdk/secret-ref-runtime` | 狭义 `coerceSecretRef` 和用于 secret 契约/配置解析的 SecretRef 类型辅助工具 | - | `plugin-sdk/security-runtime` | 共享信任、私信门控、外部内容和 secret 收集辅助工具 | + | `plugin-sdk/channel-secret-runtime` | 用于渠道/插件密钥接口的窄范围密钥契约收集辅助工具 | + | `plugin-sdk/secret-ref-runtime` | 用于密钥契约/配置解析的窄范围 `coerceSecretRef` 和 SecretRef 类型辅助工具 | + | `plugin-sdk/security-runtime` | 共享的信任、私信门控、外部内容和密钥收集辅助工具 | | `plugin-sdk/ssrf-policy` | 主机 allowlist 和私有网络 SSRF 策略辅助工具 | - | `plugin-sdk/ssrf-runtime` | pinned-dispatcher、SSRF 保护 fetch 和 SSRF 策略辅助工具 | - | `plugin-sdk/secret-input` | secret 输入解析辅助工具 | - | `plugin-sdk/webhook-ingress` | Webhook 请求/目标辅助工具 | + | `plugin-sdk/ssrf-runtime` | pinned-dispatcher、受 SSRF 保护的 fetch 和 SSRF 策略辅助工具 | + | `plugin-sdk/secret-input` | 密钥输入解析辅助工具 | + | `plugin-sdk/webhook-ingress` | webhook 请求/目标辅助工具 | | `plugin-sdk/webhook-request-guards` | 请求体大小/超时辅助工具 | | 子路径 | 关键导出 | | --- | --- | - | `plugin-sdk/runtime` | 广义运行时/日志/备份/插件安装辅助工具 | - | `plugin-sdk/runtime-env` | 狭义运行时 env、logger、timeout、retry 和 backoff 辅助工具 | + | `plugin-sdk/runtime` | 广泛的运行时/日志/备份/插件安装辅助工具 | + | `plugin-sdk/runtime-env` | 窄范围的运行时环境、logger、超时、重试和回退辅助工具 | | `plugin-sdk/runtime-store` | `createPluginRuntimeStore` | | `plugin-sdk/plugin-runtime` | 共享插件命令/hook/http/交互式辅助工具 | - | `plugin-sdk/hook-runtime` | 共享 webhook/internal hook 管道辅助工具 | - | `plugin-sdk/lazy-runtime` | 惰性运行时导入/绑定辅助工具,例如 `createLazyRuntimeModule`, `createLazyRuntimeMethod`, `createLazyRuntimeSurface` | + | `plugin-sdk/hook-runtime` | 共享 webhook/内部 hook 管道辅助工具 | + | `plugin-sdk/lazy-runtime` | 延迟运行时导入/绑定辅助工具,例如 `createLazyRuntimeModule`、`createLazyRuntimeMethod` 和 `createLazyRuntimeSurface` | | `plugin-sdk/process-runtime` | 进程 exec 辅助工具 | | `plugin-sdk/cli-runtime` | CLI 格式化、等待和版本辅助工具 | | `plugin-sdk/gateway-runtime` | Gateway 网关客户端和渠道状态补丁辅助工具 | | `plugin-sdk/config-runtime` | 配置加载/写入辅助工具 | - | `plugin-sdk/telegram-command-config` | Telegram 命令名称/描述规范化以及重复/冲突检查,即使内置 Telegram 契约表层不可用时也是如此 | - | `plugin-sdk/approval-runtime` | exec/插件审批辅助工具、审批能力构建器、鉴权/profile 辅助工具、原生路由/运行时辅助工具 | - | `plugin-sdk/reply-runtime` | 共享入站/回复运行时辅助工具、分块、分发、heartbeat、回复规划器 | - | `plugin-sdk/reply-dispatch-runtime` | 狭义回复分发/完成辅助工具 | - | `plugin-sdk/reply-history` | 共享短时间窗口回复历史辅助工具,例如 `buildHistoryContext`, `recordPendingHistoryEntry`, `clearHistoryEntriesIfEnabled` | + | `plugin-sdk/telegram-command-config` | Telegram 命令名称/描述规范化以及重复/冲突检查,即使内置 Telegram 契约接口不可用时也是如此 | + | `plugin-sdk/approval-runtime` | exec/插件审批辅助工具、审批能力构建器、认证/profile 辅助工具、原生路由/运行时辅助工具 | + | `plugin-sdk/reply-runtime` | 共享的入站/回复运行时辅助工具、分块、分发、心跳、回复规划器 | + | `plugin-sdk/reply-dispatch-runtime` | 窄范围的回复分发/完成辅助工具 | + | `plugin-sdk/reply-history` | 共享的短窗口回复历史辅助工具,例如 `buildHistoryContext`、`recordPendingHistoryEntry` 和 `clearHistoryEntriesIfEnabled` | | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | - | `plugin-sdk/reply-chunking` | 狭义文本/Markdown 分块辅助工具 | + | `plugin-sdk/reply-chunking` | 窄范围的文本/Markdown 分块辅助工具 | | `plugin-sdk/session-store-runtime` | 会话存储路径 + updated-at 辅助工具 | | `plugin-sdk/state-paths` | 状态/OAuth 目录路径辅助工具 | - | `plugin-sdk/routing` | 路由/会话键/账户绑定辅助工具,例如 `resolveAgentRoute`, `buildAgentSessionKey`, `resolveDefaultAgentBoundAccountId` | - | `plugin-sdk/status-helpers` | 共享渠道/账户状态摘要辅助工具、运行时状态默认值和问题元数据辅助工具 | + | `plugin-sdk/routing` | 路由/会话键/账户绑定辅助工具,例如 `resolveAgentRoute`、`buildAgentSessionKey` 和 `resolveDefaultAgentBoundAccountId` | + | `plugin-sdk/status-helpers` | 共享的渠道/账户状态摘要辅助工具、运行时状态默认值和问题元数据辅助工具 | | `plugin-sdk/target-resolver-runtime` | 共享目标解析器辅助工具 | | `plugin-sdk/string-normalization-runtime` | slug/字符串规范化辅助工具 | | `plugin-sdk/request-url` | 从 fetch/request 类输入中提取字符串 URL | - | `plugin-sdk/run-command` | 带定时功能的命令运行器,输出已规范化的 stdout/stderr 结果 | - | `plugin-sdk/param-readers` | 通用工具/CLI 参数读取器 | + | `plugin-sdk/run-command` | 带定时的命令运行器,输出已规范化的 stdout/stderr 结果 | + | `plugin-sdk/param-readers` | 常用工具/CLI 参数读取器 | | `plugin-sdk/tool-send` | 从工具参数中提取规范发送目标字段 | | `plugin-sdk/temp-path` | 共享临时下载路径辅助工具 | | `plugin-sdk/logging-core` | 子系统 logger 和脱敏辅助工具 | @@ -190,24 +190,24 @@ import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; | `plugin-sdk/json-store` | 小型 JSON 状态读写辅助工具 | | `plugin-sdk/file-lock` | 可重入文件锁辅助工具 | | `plugin-sdk/persistent-dedupe` | 基于磁盘的去重缓存辅助工具 | - | `plugin-sdk/acp-runtime` | ACP 运行时/会话和 reply-dispatch 辅助工具 | - | `plugin-sdk/agent-config-primitives` | 狭义智能体运行时配置 schema 基元 | + | `plugin-sdk/acp-runtime` | ACP 运行时/会话和回复分发辅助工具 | + | `plugin-sdk/agent-config-primitives` | 窄范围的智能体运行时配置 schema 基元 | | `plugin-sdk/boolean-param` | 宽松布尔参数读取器 | | `plugin-sdk/dangerous-name-runtime` | 危险名称匹配解析辅助工具 | | `plugin-sdk/device-bootstrap` | 设备引导和配对令牌辅助工具 | | `plugin-sdk/extension-shared` | 共享被动渠道、状态和环境代理辅助基元 | | `plugin-sdk/models-provider-runtime` | `/models` 命令/提供商回复辅助工具 | - | `plugin-sdk/skill-commands-runtime` | Skill 命令列表辅助工具 | + | `plugin-sdk/skill-commands-runtime` | Skills 命令列表辅助工具 | | `plugin-sdk/native-command-registry` | 原生命令注册表/构建/序列化辅助工具 | - | `plugin-sdk/provider-zai-endpoint` | Z.A.I endpoint 检测辅助工具 | - | `plugin-sdk/infra-runtime` | 系统事件/heartbeat 辅助工具 | + | `plugin-sdk/provider-zai-endpoint` | Z.AI 端点检测辅助工具 | + | `plugin-sdk/infra-runtime` | 系统事件/心跳辅助工具 | | `plugin-sdk/collection-runtime` | 小型有界缓存辅助工具 | | `plugin-sdk/diagnostic-runtime` | 诊断标志和事件辅助工具 | - | `plugin-sdk/error-runtime` | 错误图、格式化、共享错误分类辅助工具、`isApprovalNotFoundError` | - | `plugin-sdk/fetch-runtime` | 封装的 fetch、代理和 pinned lookup 辅助工具 | + | `plugin-sdk/error-runtime` | 错误图、格式化、共享错误分类辅助工具,`isApprovalNotFoundError` | + | `plugin-sdk/fetch-runtime` | 包装过的 fetch、代理和 pinned 查找辅助工具 | | `plugin-sdk/host-runtime` | 主机名和 SCP 主机规范化辅助工具 | | `plugin-sdk/retry-runtime` | 重试配置和重试运行器辅助工具 | - | `plugin-sdk/agent-runtime` | 智能体目录/身份/workspace 辅助工具 | + | `plugin-sdk/agent-runtime` | 智能体目录/身份/工作区辅助工具 | | `plugin-sdk/directory-runtime` | 基于配置的目录查询/去重 | | `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` | @@ -216,105 +216,105 @@ import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; | 子路径 | 关键导出 | | --- | --- | | `plugin-sdk/media-runtime` | 共享媒体获取/转换/存储辅助工具以及媒体负载构建器 | - | `plugin-sdk/media-generation-runtime` | 共享媒体生成故障转移辅助工具、候选项选择和缺失模型提示 | - | `plugin-sdk/media-understanding` | 媒体理解提供商类型,以及面向提供商的图像/音频辅助导出 | - | `plugin-sdk/text-runtime` | 共享文本/Markdown/日志辅助工具,例如 assistant-visible-text 剥离、Markdown 渲染/分块/表格辅助工具、脱敏辅助工具、directive-tag 辅助工具和安全文本实用工具 | + | `plugin-sdk/media-generation-runtime` | 共享媒体生成故障转移辅助工具、候选项选择和缺失模型提示信息 | + | `plugin-sdk/media-understanding` | 媒体理解提供商类型以及面向提供商的图像/音频辅助工具导出 | + | `plugin-sdk/text-runtime` | 共享文本/Markdown/日志辅助工具,例如去除对助手可见的文本、Markdown 渲染/分块/表格辅助工具、脱敏辅助工具、指令标签辅助工具和安全文本工具 | | `plugin-sdk/text-chunking` | 出站文本分块辅助工具 | - | `plugin-sdk/speech` | 语音提供商类型,以及面向提供商的 directive、注册表和校验辅助工具 | - | `plugin-sdk/speech-core` | 共享语音提供商类型、注册表、directive 和规范化辅助工具 | + | `plugin-sdk/speech` | 语音提供商类型以及面向提供商的指令、注册表和验证辅助工具 | + | `plugin-sdk/speech-core` | 共享语音提供商类型、注册表、指令和规范化辅助工具 | | `plugin-sdk/realtime-transcription` | 实时转录提供商类型和注册表辅助工具 | | `plugin-sdk/realtime-voice` | 实时语音提供商类型和注册表辅助工具 | | `plugin-sdk/image-generation` | 图像生成提供商类型 | - | `plugin-sdk/image-generation-core` | 共享图像生成类型、故障转移、鉴权和注册表辅助工具 | + | `plugin-sdk/image-generation-core` | 共享图像生成类型、故障转移、认证和注册表辅助工具 | | `plugin-sdk/music-generation` | 音乐生成提供商/请求/结果类型 | | `plugin-sdk/music-generation-core` | 共享音乐生成类型、故障转移辅助工具、提供商查找和 model-ref 解析 | | `plugin-sdk/video-generation` | 视频生成提供商/请求/结果类型 | | `plugin-sdk/video-generation-core` | 共享视频生成类型、故障转移辅助工具、提供商查找和 model-ref 解析 | - | `plugin-sdk/webhook-targets` | Webhook 目标注册表和路由安装辅助工具 | - | `plugin-sdk/webhook-path` | Webhook 路径规范化辅助工具 | + | `plugin-sdk/webhook-targets` | webhook 目标注册表和路由安装辅助工具 | + | `plugin-sdk/webhook-path` | webhook 路径规范化辅助工具 | | `plugin-sdk/web-media` | 共享远程/本地媒体加载辅助工具 | - | `plugin-sdk/zod` | 为插件 SDK 使用者重新导出的 `zod` | - | `plugin-sdk/testing` | `installCommonResolveTargetErrorCases`, `shouldAckReaction` | + | `plugin-sdk/zod` | 为插件 SDK 使用方重新导出的 `zod` | + | `plugin-sdk/testing` | `installCommonResolveTargetErrorCases`、`shouldAckReaction` | - + | 子路径 | 关键导出 | | --- | --- | | `plugin-sdk/memory-core` | 内置 memory-core 辅助接口,用于 manager/config/file/CLI 辅助工具 | - | `plugin-sdk/memory-core-engine-runtime` | Memory 索引/搜索运行时门面 | - | `plugin-sdk/memory-core-host-engine-foundation` | Memory host foundation engine 导出 | - | `plugin-sdk/memory-core-host-engine-embeddings` | Memory host embedding engine 导出 | - | `plugin-sdk/memory-core-host-engine-qmd` | Memory host QMD engine 导出 | - | `plugin-sdk/memory-core-host-engine-storage` | Memory host storage engine 导出 | - | `plugin-sdk/memory-core-host-multimodal` | Memory host 多模态辅助工具 | - | `plugin-sdk/memory-core-host-query` | Memory host 查询辅助工具 | - | `plugin-sdk/memory-core-host-secret` | Memory host secret 辅助工具 | - | `plugin-sdk/memory-core-host-events` | Memory host 事件日志辅助工具 | - | `plugin-sdk/memory-core-host-status` | Memory host 状态辅助工具 | - | `plugin-sdk/memory-core-host-runtime-cli` | Memory host CLI 运行时辅助工具 | - | `plugin-sdk/memory-core-host-runtime-core` | Memory host 核心运行时辅助工具 | - | `plugin-sdk/memory-core-host-runtime-files` | Memory host 文件/运行时辅助工具 | - | `plugin-sdk/memory-host-core` | 面向供应商中立的 memory host 核心运行时辅助工具别名 | - | `plugin-sdk/memory-host-events` | 面向供应商中立的 memory host 事件日志辅助工具别名 | - | `plugin-sdk/memory-host-files` | 面向供应商中立的 memory host 文件/运行时辅助工具别名 | - | `plugin-sdk/memory-host-markdown` | 面向 Memory 邻接插件的共享托管 Markdown 辅助工具 | - | `plugin-sdk/memory-host-search` | 用于 search-manager 访问的 active memory 运行时门面 | - | `plugin-sdk/memory-host-status` | 面向供应商中立的 memory host 状态辅助工具别名 | + | `plugin-sdk/memory-core-engine-runtime` | 记忆索引/搜索运行时门面 | + | `plugin-sdk/memory-core-host-engine-foundation` | 记忆主机 foundation engine 导出 | + | `plugin-sdk/memory-core-host-engine-embeddings` | 记忆主机嵌入 engine 导出 | + | `plugin-sdk/memory-core-host-engine-qmd` | 记忆主机 QMD engine 导出 | + | `plugin-sdk/memory-core-host-engine-storage` | 记忆主机存储 engine 导出 | + | `plugin-sdk/memory-core-host-multimodal` | 记忆主机多模态辅助工具 | + | `plugin-sdk/memory-core-host-query` | 记忆主机查询辅助工具 | + | `plugin-sdk/memory-core-host-secret` | 记忆主机密钥辅助工具 | + | `plugin-sdk/memory-core-host-events` | 记忆主机事件日志辅助工具 | + | `plugin-sdk/memory-core-host-status` | 记忆主机状态辅助工具 | + | `plugin-sdk/memory-core-host-runtime-cli` | 记忆主机 CLI 运行时辅助工具 | + | `plugin-sdk/memory-core-host-runtime-core` | 记忆主机核心运行时辅助工具 | + | `plugin-sdk/memory-core-host-runtime-files` | 记忆主机文件/运行时辅助工具 | + | `plugin-sdk/memory-host-core` | 面向供应商中立的记忆主机核心运行时辅助工具别名 | + | `plugin-sdk/memory-host-events` | 面向供应商中立的记忆主机事件日志辅助工具别名 | + | `plugin-sdk/memory-host-files` | 面向供应商中立的记忆主机文件/运行时辅助工具别名 | + | `plugin-sdk/memory-host-markdown` | 用于记忆相关插件的共享托管 Markdown 辅助工具 | + | `plugin-sdk/memory-host-search` | 用于 search-manager 访问的活动记忆运行时门面 | + | `plugin-sdk/memory-host-status` | 面向供应商中立的记忆主机状态辅助工具别名 | | `plugin-sdk/memory-lancedb` | 内置 memory-lancedb 辅助接口 | - | 家族 | 当前子路径 | 预期用途 | + | 系列 | 当前子路径 | 预期用途 | | --- | --- | --- | - | Browser | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | 内置 browser 插件支持辅助工具(`browser-support` 仍是兼容性 barrel) | - | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | 内置 Matrix 辅助/运行时接口 | - | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | 内置 LINE 辅助/运行时接口 | - | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | 内置 IRC 辅助接口 | - | 特定于渠道的辅助工具 | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | 内置渠道兼容性/辅助接口 | - | 鉴权/特定于插件的辅助工具 | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | 内置功能/插件辅助接口;`plugin-sdk/github-copilot-token` 当前导出 `DEFAULT_COPILOT_API_BASE_URL`, `deriveCopilotApiBaseUrlFromToken` 和 `resolveCopilotApiToken` | + | Browser | `plugin-sdk/browser-cdp`、`plugin-sdk/browser-config-runtime`、`plugin-sdk/browser-config-support`、`plugin-sdk/browser-control-auth`、`plugin-sdk/browser-node-runtime`、`plugin-sdk/browser-profiles`、`plugin-sdk/browser-security-runtime`、`plugin-sdk/browser-setup-tools`、`plugin-sdk/browser-support` | 内置浏览器插件支持辅助工具(`browser-support` 仍是兼容性 barrel) | + | Matrix | `plugin-sdk/matrix`、`plugin-sdk/matrix-helper`、`plugin-sdk/matrix-runtime-heavy`、`plugin-sdk/matrix-runtime-shared`、`plugin-sdk/matrix-runtime-surface`、`plugin-sdk/matrix-surface`、`plugin-sdk/matrix-thread-bindings` | 内置 Matrix 辅助/运行时接口 | + | Line | `plugin-sdk/line`、`plugin-sdk/line-core`、`plugin-sdk/line-runtime`、`plugin-sdk/line-surface` | 内置 LINE 辅助/运行时接口 | + | IRC | `plugin-sdk/irc`、`plugin-sdk/irc-surface` | 内置 IRC 辅助接口 | + | 渠道专用辅助工具 | `plugin-sdk/googlechat`、`plugin-sdk/zalouser`、`plugin-sdk/bluebubbles`、`plugin-sdk/bluebubbles-policy`、`plugin-sdk/mattermost`、`plugin-sdk/mattermost-policy`、`plugin-sdk/feishu-conversation`、`plugin-sdk/msteams`、`plugin-sdk/nextcloud-talk`、`plugin-sdk/nostr`、`plugin-sdk/tlon`、`plugin-sdk/twitch` | 内置渠道兼容性/辅助接口 | + | 认证/插件专用辅助工具 | `plugin-sdk/github-copilot-login`、`plugin-sdk/github-copilot-token`、`plugin-sdk/diagnostics-otel`、`plugin-sdk/diffs`、`plugin-sdk/llm-task`、`plugin-sdk/thread-ownership`、`plugin-sdk/voice-call` | 内置功能/插件辅助接口;`plugin-sdk/github-copilot-token` 当前导出 `DEFAULT_COPILOT_API_BASE_URL`、`deriveCopilotApiBaseUrlFromToken` 和 `resolveCopilotApiToken` | ## 注册 API -`register(api)` 回调会收到一个带有这些方法的 `OpenClawPluginApi` 对象: +`register(api)` 回调会收到一个 `OpenClawPluginApi` 对象,包含以下方法: ### 能力注册 | 方法 | 注册内容 | | ------------------------------------------------ | -------------------------------- | -| `api.registerProvider(...)` | 文本推理(LLM) | -| `api.registerCliBackend(...)` | 本地 CLI 推理后端 | -| `api.registerChannel(...)` | 消息渠道 | -| `api.registerSpeechProvider(...)` | 文本转语音 / STT 合成 | +| `api.registerProvider(...)` | 文本推理(LLM) | +| `api.registerCliBackend(...)` | 本地 CLI 推理后端 | +| `api.registerChannel(...)` | 消息渠道 | +| `api.registerSpeechProvider(...)` | 文本转语音 / STT 合成 | | `api.registerRealtimeTranscriptionProvider(...)` | 流式实时转录 | -| `api.registerRealtimeVoiceProvider(...)` | 双工实时语音会话 | -| `api.registerMediaUnderstandingProvider(...)` | 图像/音频/视频分析 | -| `api.registerImageGenerationProvider(...)` | 图像生成 | -| `api.registerMusicGenerationProvider(...)` | 音乐生成 | -| `api.registerVideoGenerationProvider(...)` | 视频生成 | -| `api.registerWebFetchProvider(...)` | Web 获取 / 抓取提供商 | -| `api.registerWebSearchProvider(...)` | Web 搜索 | +| `api.registerRealtimeVoiceProvider(...)` | 双工实时语音会话 | +| `api.registerMediaUnderstandingProvider(...)` | 图像/音频/视频分析 | +| `api.registerImageGenerationProvider(...)` | 图像生成 | +| `api.registerMusicGenerationProvider(...)` | 音乐生成 | +| `api.registerVideoGenerationProvider(...)` | 视频生成 | +| `api.registerWebFetchProvider(...)` | Web 抓取 / 爬取提供商 | +| `api.registerWebSearchProvider(...)` | Web 搜索 | ### 工具和命令 | 方法 | 注册内容 | | ------------------------------- | --------------------------------------------- | | `api.registerTool(tool, opts?)` | 智能体工具(必需,或 `{ optional: true }`) | -| `api.registerCommand(def)` | 自定义命令(绕过 LLM) | +| `api.registerCommand(def)` | 自定义命令(绕过 LLM) | ### 基础设施 | 方法 | 注册内容 | | ---------------------------------------------- | --------------------------------------- | -| `api.registerHook(events, handler, opts?)` | 事件 hook | -| `api.registerHttpRoute(params)` | Gateway 网关 HTTP endpoint | -| `api.registerGatewayMethod(name, handler)` | Gateway 网关 RPC 方法 | -| `api.registerCli(registrar, opts?)` | CLI 子命令 | -| `api.registerService(service)` | 后台服务 | -| `api.registerInteractiveHandler(registration)` | 交互式处理器 | -| `api.registerMemoryPromptSupplement(builder)` | 追加式 Memory 邻接提示区段 | -| `api.registerMemoryCorpusSupplement(adapter)` | 追加式 Memory 搜索/读取语料 | +| `api.registerHook(events, handler, opts?)` | 事件 hook | +| `api.registerHttpRoute(params)` | Gateway 网关 HTTP 端点 | +| `api.registerGatewayMethod(name, handler)` | Gateway 网关 RPC 方法 | +| `api.registerCli(registrar, opts?)` | CLI 子命令 | +| `api.registerService(service)` | 后台服务 | +| `api.registerInteractiveHandler(registration)` | 交互式处理器 | +| `api.registerMemoryPromptSupplement(builder)` | 增量式记忆相关提示词区段 | +| `api.registerMemoryCorpusSupplement(adapter)` | 增量式记忆搜索/读取语料库 | 保留的核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)始终保持为 `operator.admin`,即使插件尝试分配更窄的 Gateway 网关方法作用域也是如此。对于插件自有方法,优先使用特定于插件的前缀。 @@ -322,10 +322,10 @@ import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; `api.registerCli(registrar, opts?)` 接受两类顶层元数据: -- `commands`:由该 registrar 拥有的显式命令根 -- `descriptors`:用于根 CLI 帮助、路由和惰性插件 CLI 注册的解析期命令描述符 +- `commands`:由 registrar 拥有的显式命令根 +- `descriptors`:用于根 CLI 帮助、路由和延迟插件 CLI 注册的解析时命令描述符 -如果你希望插件命令在普通根 CLI 路径中保持惰性加载,请提供覆盖该 registrar 暴露的每个顶层命令根的 `descriptors`。 +如果你希望插件命令在普通根 CLI 路径中保持延迟加载,请提供 `descriptors`,覆盖该 registrar 暴露的每个顶层命令根。 ```typescript api.registerCli( @@ -337,7 +337,7 @@ api.registerCli( descriptors: [ { name: "matrix", - description: "管理 Matrix 账户、验证、设备和个人资料状态", + description: "管理 Matrix 账户、验证、设备和配置文件状态", hasSubcommands: true, }, ], @@ -345,7 +345,7 @@ api.registerCli( ); ``` -仅在你不需要惰性根 CLI 注册时单独使用 `commands`。这种急切兼容路径仍受支持,但它不会为解析期惰性加载安装基于 descriptor 的占位符。 +仅在你不需要延迟根 CLI 注册时,才单独使用 `commands`。这种急切兼容路径仍受支持,但它不会为解析时延迟加载安装基于 descriptor 的占位符。 ### CLI 后端注册 @@ -353,83 +353,83 @@ api.registerCli( - 后端 `id` 会成为模型引用中的提供商前缀,例如 `codex-cli/gpt-5`。 - 后端 `config` 使用与 `agents.defaults.cliBackends.` 相同的结构。 -- 用户配置仍然优先生效。OpenClaw 会在运行 CLI 之前,将 `agents.defaults.cliBackends.` 合并到插件默认值之上。 -- 当后端在合并后需要兼容性重写时,使用 `normalizeConfig`(例如规范化旧版 flag 结构)。 +- 用户配置仍然优先。OpenClaw 会在运行 CLI 之前,将 `agents.defaults.cliBackends.` 合并到插件默认值之上。 +- 当某个后端在合并后需要兼容性重写时,请使用 `normalizeConfig`(例如规范化旧版 flag 结构)。 ### 独占槽位 | 方法 | 注册内容 | | ------------------------------------------ | ------------------------------------- | -| `api.registerContextEngine(id, factory)` | 上下文引擎(一次只能激活一个) | -| `api.registerMemoryPromptSection(builder)` | Memory 提示区段构建器 | -| `api.registerMemoryFlushPlan(resolver)` | Memory 刷新计划解析器 | -| `api.registerMemoryRuntime(runtime)` | Memory 运行时适配器 | +| `api.registerContextEngine(id, factory)` | 上下文引擎(同一时间仅一个处于活动状态) | +| `api.registerMemoryPromptSection(builder)` | 记忆提示词区段构建器 | +| `api.registerMemoryFlushPlan(resolver)` | 记忆刷新计划解析器 | +| `api.registerMemoryRuntime(runtime)` | 记忆运行时适配器 | -### Memory embedding 适配器 +### 记忆嵌入适配器 | 方法 | 注册内容 | | ---------------------------------------------- | ---------------------------------------------- | -| `api.registerMemoryEmbeddingProvider(adapter)` | 用于活动插件的 Memory embedding 适配器 | +| `api.registerMemoryEmbeddingProvider(adapter)` | 活动插件的记忆嵌入适配器 | -- `registerMemoryPromptSection`、`registerMemoryFlushPlan` 和 `registerMemoryRuntime` 仅适用于 Memory 插件。 -- `registerMemoryEmbeddingProvider` 允许活动 Memory 插件注册一个或多个 embedding adapter ID(例如 `openai`、`gemini` 或自定义插件定义的 ID)。 -- 用户配置,例如 `agents.defaults.memorySearch.provider` 和 `agents.defaults.memorySearch.fallback`,会根据这些已注册的 adapter ID 进行解析。 +- `registerMemoryPromptSection`、`registerMemoryFlushPlan` 和 `registerMemoryRuntime` 是记忆插件专属的独占项。 +- `registerMemoryEmbeddingProvider` 允许活动记忆插件注册一个或多个嵌入适配器 ID(例如 `openai`、`gemini` 或自定义插件定义的 ID)。 +- 用户配置,例如 `agents.defaults.memorySearch.provider` 和 `agents.defaults.memorySearch.fallback`,会根据这些已注册的适配器 ID 进行解析。 -### 事件与生命周期 +### 事件和生命周期 | 方法 | 作用 | | -------------------------------------------- | ----------------------------- | -| `api.on(hookName, handler, opts?)` | 类型化生命周期 hook | +| `api.on(hookName, handler, opts?)` | 类型化生命周期 hook | | `api.onConversationBindingResolved(handler)` | 会话绑定回调 | ### Hook 决策语义 -- `before_tool_call`:返回 `{ block: true }` 是终止性的。一旦任何处理器设置了它,就会跳过更低优先级的处理器。 -- `before_tool_call`:返回 `{ block: false }` 会被视为未作决定(与省略 `block` 相同),而不是覆盖。 -- `before_install`:返回 `{ block: true }` 是终止性的。一旦任何处理器设置了它,就会跳过更低优先级的处理器。 -- `before_install`:返回 `{ block: false }` 会被视为未作决定(与省略 `block` 相同),而不是覆盖。 -- `reply_dispatch`:返回 `{ handled: true, ... }` 是终止性的。一旦任何处理器声明接管分发,就会跳过更低优先级的处理器和默认模型分发路径。 -- `message_sending`:返回 `{ cancel: true }` 是终止性的。一旦任何处理器设置了它,就会跳过更低优先级的处理器。 -- `message_sending`:返回 `{ cancel: false }` 会被视为未作决定(与省略 `cancel` 相同),而不是覆盖。 +- `before_tool_call`:返回 `{ block: true }` 为终止性结果。一旦任何处理器设置该值,将跳过更低优先级的处理器。 +- `before_tool_call`:返回 `{ block: false }` 会被视为未作决策(与省略 `block` 相同),而不是覆盖。 +- `before_install`:返回 `{ block: true }` 为终止性结果。一旦任何处理器设置该值,将跳过更低优先级的处理器。 +- `before_install`:返回 `{ block: false }` 会被视为未作决策(与省略 `block` 相同),而不是覆盖。 +- `reply_dispatch`:返回 `{ handled: true, ... }` 为终止性结果。一旦任何处理器声明已分发,将跳过更低优先级的处理器和默认模型分发路径。 +- `message_sending`:返回 `{ cancel: true }` 为终止性结果。一旦任何处理器设置该值,将跳过更低优先级的处理器。 +- `message_sending`:返回 `{ cancel: false }` 会被视为未作决策(与省略 `cancel` 相同),而不是覆盖。 ### API 对象字段 | 字段 | 类型 | 描述 | | ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------- | -| `api.id` | `string` | 插件 ID | -| `api.name` | `string` | 显示名称 | -| `api.version` | `string?` | 插件版本(可选) | -| `api.description` | `string?` | 插件描述(可选) | -| `api.source` | `string` | 插件源路径 | -| `api.rootDir` | `string?` | 插件根目录(可选) | -| `api.config` | `OpenClawConfig` | 当前配置快照(如可用,则为活动的内存中运行时快照) | -| `api.pluginConfig` | `Record` | 来自 `plugins.entries..config` 的插件专属配置 | -| `api.runtime` | `PluginRuntime` | [运行时辅助工具](/zh-CN/plugins/sdk-runtime) | -| `api.logger` | `PluginLogger` | 作用域化 logger(`debug`、`info`、`warn`、`error`) | -| `api.registrationMode` | `PluginRegistrationMode` | 当前加载模式;`"setup-runtime"` 是完整入口启动/设置前的轻量窗口 | -| `api.resolvePath(input)` | `(string) => string` | 解析相对于插件根目录的路径 | +| `api.id` | `string` | 插件 ID | +| `api.name` | `string` | 显示名称 | +| `api.version` | `string?` | 插件版本(可选) | +| `api.description` | `string?` | 插件描述(可选) | +| `api.source` | `string` | 插件源路径 | +| `api.rootDir` | `string?` | 插件根目录(可选) | +| `api.config` | `OpenClawConfig` | 当前配置快照(可用时为活动内存运行时快照) | +| `api.pluginConfig` | `Record` | 来自 `plugins.entries..config` 的插件专属配置 | +| `api.runtime` | `PluginRuntime` | [运行时辅助工具](/zh-CN/plugins/sdk-runtime) | +| `api.logger` | `PluginLogger` | 作用域 logger(`debug`、`info`、`warn`、`error`) | +| `api.registrationMode` | `PluginRegistrationMode` | 当前加载模式;`"setup-runtime"` 是完整入口前的轻量预启动/设置窗口 | +| `api.resolvePath(input)` | `(string) => string` | 解析相对于插件根目录的路径 | ## 内部模块约定 -在你的插件内部,使用本地 barrel 文件进行内部导入: +在你的插件内部,请使用本地 barrel 文件进行内部导入: ``` my-plugin/ - api.ts # 供外部使用者使用的公共导出 + api.ts # 面向外部使用方的公共导出 runtime-api.ts # 仅供内部使用的运行时导出 index.ts # 插件入口点 - setup-entry.ts # 仅设置用的轻量入口点(可选) + setup-entry.ts # 轻量级仅设置入口(可选) ``` - 永远不要在生产代码中通过 `openclaw/plugin-sdk/` - 导入你自己的插件。内部导入应通过 `./api.ts` 或 - `./runtime-api.ts`。SDK 路径仅是外部契约。 + 不要在生产代码中通过 `openclaw/plugin-sdk/` 导入你自己的插件。 + 请通过 `./api.ts` 或 `./runtime-api.ts` 处理内部导入。 + SDK 路径仅是对外契约。 -由门面加载的内置插件公共接口(`api.ts`、`runtime-api.ts`、`index.ts`、`setup-entry.ts` 以及类似公共入口文件)现在在 OpenClaw 已运行时会优先使用活动的运行时配置快照。如果运行时快照尚不存在,它们会回退到磁盘上已解析的配置文件。 +由门面加载的内置插件公共接口(`api.ts`、`runtime-api.ts`、`index.ts`、`setup-entry.ts` 以及类似的公共入口文件)现在会在 OpenClaw 已经运行时优先使用活动运行时配置快照。如果运行时快照尚不存在,它们会回退到磁盘上解析得到的配置文件。 -当某个辅助工具有意特定于提供商、且暂时不属于通用 SDK 子路径时,提供商插件也可以暴露一个狭义的插件本地契约 barrel。当前内置示例:Anthropic 提供商将其 Claude 流辅助工具保留在自己的公共 `api.ts` / `contract-api.ts` 接口层中,而不是将 Anthropic beta-header 和 `service_tier` 逻辑提升到通用 `plugin-sdk/*` 契约中。 +如果某个辅助工具明确是提供商专用,且尚不适合放入通用 SDK 子路径中,提供商插件也可以暴露一个窄范围的插件本地契约 barrel。当前内置示例:Anthropic 提供商将其 Claude 流辅助工具保留在自己的公共 `api.ts` / `contract-api.ts` 接口中,而不是将 Anthropic beta-header 和 `service_tier` 逻辑提升为通用 `plugin-sdk/*` 契约。 其他当前内置示例: @@ -437,17 +437,17 @@ my-plugin/ - `@openclaw/openrouter-provider`:`api.ts` 导出提供商构建器以及新手引导/配置辅助工具 - 扩展生产代码也应避免导入 `openclaw/plugin-sdk/`。 - 如果某个辅助工具确实需要共享,请将它提升到中立的 SDK 子路径, - 例如 `openclaw/plugin-sdk/speech`、`.../provider-model-shared`,或其他 - 面向能力的接口,而不是将两个插件耦合在一起。 + 扩展生产代码也应避免使用 `openclaw/plugin-sdk/` 导入。 + 如果某个辅助工具确实需要共享,应将其提升到中立的 SDK 子路径, + 例如 `openclaw/plugin-sdk/speech`、`.../provider-model-shared` 或其他 + 面向能力的接口,而不是让两个插件彼此耦合。 ## 相关内容 - [入口点](/zh-CN/plugins/sdk-entrypoints) — `definePluginEntry` 和 `defineChannelPluginEntry` 选项 - [运行时辅助工具](/zh-CN/plugins/sdk-runtime) — 完整的 `api.runtime` 命名空间参考 -- [设置和配置](/zh-CN/plugins/sdk-setup) — 打包、manifest 和配置 schema +- [设置和配置](/zh-CN/plugins/sdk-setup) — 打包、清单、配置 schema - [测试](/zh-CN/plugins/sdk-testing) — 测试工具和 lint 规则 - [SDK 迁移](/zh-CN/plugins/sdk-migration) — 从已弃用接口迁移 -- [插件内部机制](/zh-CN/plugins/architecture) — 深入架构和能力模型 +- [插件内部机制](/zh-CN/plugins/architecture) — 深入的架构与能力模型 diff --git a/docs/zh-CN/plugins/sdk-runtime.md b/docs/zh-CN/plugins/sdk-runtime.md index 7aef6bb93..726c4363c 100644 --- a/docs/zh-CN/plugins/sdk-runtime.md +++ b/docs/zh-CN/plugins/sdk-runtime.md @@ -1,28 +1,28 @@ --- read_when: - - 你需要从插件中调用 core 辅助工具(TTS、STT、图像生成、Web 搜索、子智能体) - - 你想了解 api.runtime 暴露了什么 - - 你正在从插件代码中访问配置、智能体或媒体辅助工具 + - 当你需要从插件调用核心辅助工具时(TTS、STT、图像生成、Web 搜索、subagent) + - 当你想了解 api.runtime 暴露了什么内容时 + - 当你在插件代码中访问 config、智能体或媒体辅助工具时 sidebarTitle: Runtime Helpers -summary: api.runtime —— 注入到插件中的可用运行时辅助工具 +summary: api.runtime —— 在插件中可用的注入式运行时辅助工具 title: 插件运行时辅助工具 x-i18n: - generated_at: "2026-04-05T08:40:23Z" + generated_at: "2026-04-07T06:53:16Z" model: gpt-5.4 provider: openai - source_hash: 667edff734fd30f9b05d55eae6360830a45ae8f3012159f88a37b5e05404e666 + source_hash: acb9e56678e9ed08d0998dfafd7cd1982b592be5bc34d9e2d2c1f70274f8f248 source_path: plugins/sdk-runtime.md workflow: 15 --- # 插件运行时辅助工具 -这是在注册期间注入到每个插件中的 `api.runtime` 对象参考。请使用这些辅助工具,而不是直接导入宿主内部实现。 +这是对在注册期间注入到每个插件中的 `api.runtime` 对象的参考说明。请使用这些辅助工具,而不是直接导入宿主内部实现。 - **想看操作演练?** 请参见 [渠道插件](/plugins/sdk-channel-plugins) - 或 [提供商插件](/plugins/sdk-provider-plugins),其中提供了分步指南, - 展示了这些辅助工具在实际场景中的用法。 + **想看操作演示?** 请参阅 [渠道插件](/zh-CN/plugins/sdk-channel-plugins) + 或 [提供商插件](/zh-CN/plugins/sdk-provider-plugins) 中的分步指南, + 它们会结合上下文展示这些辅助工具的用法。 ```typescript @@ -88,7 +88,7 @@ const provider = api.runtime.agent.defaults.provider; // e.g. "anthropic" ### `api.runtime.subagent` -启动和管理后台子智能体运行。 +启动并管理后台 subagent 运行。 ```typescript // Start a subagent run @@ -116,15 +116,15 @@ await api.runtime.subagent.deleteSession({ ``` - 模型覆盖(`provider`/`model`)需要操作员通过配置中的 + 模型覆盖(`provider`/`model`)需要操作员在 config 中通过 `plugins.entries..subagent.allowModelOverride: true` 明确启用。 - 不受信任的插件仍然可以运行子智能体,但覆盖请求会被拒绝。 + 不受信任的插件仍然可以运行 subagent,但其覆盖请求会被拒绝。 ### `api.runtime.taskFlow` -将 Task Flow 运行时绑定到现有 OpenClaw 会话键或受信任的工具 -上下文,然后在每次调用时无需传入 owner 即可创建和管理 Task Flows。 +将 Task Flow 运行时绑定到现有的 OpenClaw 会话键或受信任的工具上下文, +然后在每次调用时无需传入 owner,即可创建和管理 Task Flows。 ```typescript const taskFlow = api.runtime.taskFlow.fromToolContext(ctx); @@ -151,9 +151,8 @@ const waiting = taskFlow.setWaiting({ }); ``` -当你已经从自己的绑定层获得了受信任的 OpenClaw 会话键时,请使用 -`bindSession({ sessionKey, requesterOrigin })`。不要从原始 -用户输入进行绑定。 +当你已经从自己的绑定层获得一个受信任的 OpenClaw 会话键时,请使用 +`bindSession({ sessionKey, requesterOrigin })`。不要从原始用户输入进行绑定。 ### `api.runtime.tts` @@ -179,8 +178,7 @@ const voices = await api.runtime.tts.listVoices({ }); ``` -使用 core 的 `messages.tts` 配置和提供商选择。返回 PCM 音频 -缓冲区 + 采样率。 +使用核心 `messages.tts` 配置和提供商选择。返回 PCM 音频缓冲区和采样率。 ### `api.runtime.mediaUnderstanding` @@ -214,11 +212,11 @@ const result = await api.runtime.mediaUnderstanding.runFile({ }); ``` -当没有产生输出时,返回 `{ text: undefined }`(例如输入被跳过时)。 +当未生成输出时(例如输入被跳过),返回 `{ text: undefined }`。 - `api.runtime.stt.transcribeAudioFile(...)` 仍然作为 - `api.runtime.mediaUnderstanding.transcribeAudioFile(...)` 的兼容别名保留。 + `api.runtime.stt.transcribeAudioFile(...)` 仍保留为 + `api.runtime.mediaUnderstanding.transcribeAudioFile(...)` 的兼容别名。 ### `api.runtime.imageGeneration` @@ -249,7 +247,7 @@ const result = await api.runtime.webSearch.search({ ### `api.runtime.media` -底层媒体工具。 +底层媒体实用工具。 ```typescript const webMedia = await api.runtime.media.loadWebMedia(url); @@ -262,7 +260,7 @@ const resized = await api.runtime.media.resizeToJpeg(buffer, { maxWidth: 800 }); ### `api.runtime.config` -配置加载和写入。 +Config 加载和写入。 ```typescript const cfg = await api.runtime.config.loadConfig(); @@ -271,7 +269,7 @@ await api.runtime.config.writeConfigFile(cfg); ### `api.runtime.system` -系统级工具。 +系统级实用工具。 ```typescript await api.runtime.system.enqueueSystemEvent(event); @@ -295,7 +293,7 @@ api.runtime.events.onSessionTranscriptUpdate((update) => { ### `api.runtime.logging` -日志。 +日志记录。 ```typescript const verbose = api.runtime.logging.shouldLogVerbose(); @@ -324,7 +322,7 @@ const stateDir = api.runtime.state.resolveStateDir(); ### `api.runtime.tools` -Memory 工具工厂和 CLI。 +内存工具工厂和 CLI。 ```typescript const getTool = api.runtime.tools.createMemoryGetTool(/* ... */); @@ -334,12 +332,51 @@ api.runtime.tools.registerMemoryCli(/* ... */); ### `api.runtime.channel` -渠道特定运行时辅助工具(在加载渠道插件时可用)。 +渠道专用运行时辅助工具(在加载渠道插件时可用)。 + +`api.runtime.channel.mentions` 是供使用运行时注入的内置渠道插件共享的入站提及策略接口: + +```typescript +const mentionMatch = api.runtime.channel.mentions.matchesMentionWithExplicit(text, { + mentionRegexes, + mentionPatterns, +}); + +const decision = api.runtime.channel.mentions.resolveInboundMentionDecision({ + facts: { + canDetectMention: true, + wasMentioned: mentionMatch.matched, + implicitMentionKinds: api.runtime.channel.mentions.implicitMentionKindWhen( + "reply_to_bot", + isReplyToBot, + ), + }, + policy: { + isGroup, + requireMention, + allowTextCommands, + hasControlCommand, + commandAuthorized, + }, +}); +``` + +可用的 mention 辅助工具包括: + +- `buildMentionRegexes` +- `matchesMentionPatterns` +- `matchesMentionWithExplicit` +- `implicitMentionKindWhen` +- `resolveInboundMentionDecision` + +`api.runtime.channel.mentions` 有意不暴露较旧的 +`resolveMentionGating*` 兼容辅助工具。请优先使用标准化的 +`{ facts, policy }` 路径。 ## 存储运行时引用 -使用 `createPluginRuntimeStore` 来存储运行时引用,以便在 -`register` 回调之外使用: +使用 `createPluginRuntimeStore` 存储运行时引用,以便在 `register` +回调之外使用: ```typescript import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; @@ -368,20 +405,20 @@ export function tryGetRuntime() { ## 其他顶层 `api` 字段 -除了 `api.runtime` 之外,API 对象还提供: +除 `api.runtime` 之外,API 对象还提供: -| 字段 | 类型 | 描述 | -| ------------------------ | ------------------------- | ---------------------------------------------------------------------------------------- | -| `api.id` | `string` | 插件 id | -| `api.name` | `string` | 插件显示名称 | -| `api.config` | `OpenClawConfig` | 当前配置快照(可用时为活动的内存中运行时快照) | -| `api.pluginConfig` | `Record` | 来自 `plugins.entries..config` 的插件专用配置 | -| `api.logger` | `PluginLogger` | 作用域日志记录器(`debug`、`info`、`warn`、`error`) | -| `api.registrationMode` | `PluginRegistrationMode` | 当前加载模式;`"setup-runtime"` 是完整入口前的轻量启动/设置窗口 | -| `api.resolvePath(input)` | `(string) => string` | 解析相对于插件根目录的路径 | +| Field | Type | Description | +| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------- | +| `api.id` | `string` | 插件 id | +| `api.name` | `string` | 插件显示名称 | +| `api.config` | `OpenClawConfig` | 当前 config 快照(可用时为活动的内存中运行时快照) | +| `api.pluginConfig` | `Record` | 来自 `plugins.entries..config` 的插件专用 config | +| `api.logger` | `PluginLogger` | 作用域日志记录器(`debug`、`info`、`warn`、`error`) | +| `api.registrationMode` | `PluginRegistrationMode` | 当前加载模式;`"setup-runtime"` 是完整入口启动/设置前的轻量级窗口 | +| `api.resolvePath(input)` | `(string) => string` | 解析相对于插件根目录的路径 | ## 相关内容 -- [SDK 概览](/plugins/sdk-overview) -- 子路径参考 -- [插件入口点](/plugins/sdk-entrypoints) -- `definePluginEntry` 选项 -- [插件内部机制](/plugins/architecture) -- 能力模型和注册表 +- [SDK 概览](/zh-CN/plugins/sdk-overview) —— subpath 参考 +- [插件入口点](/zh-CN/plugins/sdk-entrypoints) —— `definePluginEntry` 选项 +- [插件内部架构](/zh-CN/plugins/architecture) —— 能力模型和注册表