diff --git a/docs/zh-CN/channels/mattermost.md b/docs/zh-CN/channels/mattermost.md index 298397b15..4f045d949 100644 --- a/docs/zh-CN/channels/mattermost.md +++ b/docs/zh-CN/channels/mattermost.md @@ -2,67 +2,77 @@ read_when: - 设置 Mattermost - 调试 Mattermost 路由 +sidebarTitle: Mattermost summary: Mattermost 机器人设置和 OpenClaw 配置 title: Mattermost x-i18n: - generated_at: "2026-04-23T20:41:38Z" + generated_at: "2026-04-26T08:13:18Z" model: gpt-5.4 provider: openai - source_hash: 09c91790a2ea0149c179031b6c08e06358cb4efa5a027778cec87b38444d7718 + source_hash: 22916fcff2eeccf53055f2ebf60fc621d595991d0ca4cd148015b61cce09c52f source_path: channels/mattermost.md workflow: 15 --- -状态:内置插件(bot token + WebSocket 事件)。支持渠道、群组和私信。 -Mattermost 是一个可自托管的团队消息平台;产品详情和下载请参见官方网站 [mattermost.com](https://mattermost.com)。 +Status:内置插件(bot token + WebSocket 事件)。支持渠道、群组和私信。Mattermost 是一个可自托管的团队消息平台;产品详情和下载请参见官方网站 [mattermost.com](https://mattermost.com)。 ## 内置插件 + Mattermost 在当前的 OpenClaw 版本中作为内置插件提供,因此常规打包构建不需要单独安装。 + -如果你使用的是较旧版本或排除了 Mattermost 的自定义安装,请手动安装: +如果你使用的是较旧版本,或排除了 Mattermost 的自定义安装,请手动安装: -通过 CLI 安装(npm registry): - -```bash -openclaw plugins install @openclaw/mattermost -``` - -本地 checkout(从 git 仓库运行时): - -```bash -openclaw plugins install ./path/to/local/mattermost-plugin -``` + + + ```bash + openclaw plugins install @openclaw/mattermost + ``` + + + ```bash + openclaw plugins install ./path/to/local/mattermost-plugin + ``` + + 详情: [Plugins](/zh-CN/tools/plugin) ## 快速设置 -1. 确保 Mattermost 插件可用。 - - 当前打包的 OpenClaw 版本已内置该插件。 - - 较旧/自定义安装可使用上述命令手动添加。 -2. 创建一个 Mattermost bot 账户,并复制 **bot token**。 -3. 复制 Mattermost **base URL**(例如 `https://chat.example.com`)。 -4. 配置 OpenClaw 并启动 gateway。 + + + 当前打包的 OpenClaw 版本已内置该插件。较旧版本或自定义安装可使用上面的命令手动添加。 + + + 创建一个 Mattermost 机器人账户,并复制 **bot token**。 + + + 复制 Mattermost 的 **base URL**(例如 `https://chat.example.com`)。 + + + 最小配置: -最小配置: + ```json5 + { + channels: { + mattermost: { + enabled: true, + botToken: "mm-token", + baseUrl: "https://chat.example.com", + dmPolicy: "pairing", + }, + }, + } + ``` -```json5 -{ - channels: { - mattermost: { - enabled: true, - botToken: "mm-token", - baseUrl: "https://chat.example.com", - dmPolicy: "pairing", - }, - }, -} -``` + + ## 原生斜杠命令 -原生斜杠命令为选择启用。启用后,OpenClaw 会通过 Mattermost API 注册 `oc_*` 斜杠命令,并在 gateway HTTP 服务器上接收回调 POST。 +原生斜杠命令为可选启用。启用后,OpenClaw 会通过 Mattermost API 注册 `oc_*` 斜杠命令,并在 Gateway 网关 HTTP 服务器上接收回调 `POST` 请求。 ```json5 { @@ -72,7 +82,7 @@ openclaw plugins install ./path/to/local/mattermost-plugin native: true, nativeSkills: true, callbackPath: "/api/channels/mattermost/command", - // 当 Mattermost 无法直接访问 gateway 时使用(反向代理/公共 URL)。 + // 当 Mattermost 无法直接访问 Gateway 网关时使用(反向代理/公共 URL)。 callbackUrl: "https://gateway.example.com/api/channels/mattermost/command", }, }, @@ -80,41 +90,61 @@ openclaw plugins install ./path/to/local/mattermost-plugin } ``` -说明: + + + - `native: "auto"` 对 Mattermost 默认禁用。设置 `native: true` 以启用。 + - 如果省略 `callbackUrl`,OpenClaw 会根据 Gateway 网关的 host/port 和 `callbackPath` 推导出一个地址。 + - 对于多账户设置,`commands` 可以设置在顶层,也可以设置在 `channels.mattermost.accounts..commands` 下(账户级值会覆盖顶层字段)。 + - 命令回调会使用 OpenClaw 注册 `oc_*` 命令时 Mattermost 返回的每命令 token 进行校验。 + - 当注册失败、启动不完整,或回调 token 与已注册命令都不匹配时,斜杠命令回调会以失败关闭方式处理。 + + + 回调端点必须可从 Mattermost 服务器访问。 + + - 除非 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间中,否则不要将 `callbackUrl` 设置为 `localhost`。 + - 除非该 URL 会将 `/api/channels/mattermost/command` 反向代理到 OpenClaw,否则不要将 `callbackUrl` 设置为你的 Mattermost 基础 URL。 + - 一个快速检查方法是运行 `curl https:///api/channels/mattermost/command`;`GET` 应返回来自 OpenClaw 的 `405 Method Not Allowed`,而不是 `404`。 + + + + 如果你的回调目标是私有地址、tailnet 地址或内部地址,请将 Mattermost 的 `ServiceSettings.AllowedUntrustedInternalConnections` 设置为包含该回调 host/domain。 + + 使用 host/domain 条目,而不是完整 URL。 -- `native: "auto"` 在 Mattermost 中默认是禁用的。设置 `native: true` 以启用。 -- 如果省略 `callbackUrl`,OpenClaw 会根据 gateway host/port + `callbackPath` 自动推导。 -- 对于多账户设置,`commands` 可以设置在顶层,也可以设置在 `channels.mattermost.accounts..commands` 下(账户级值会覆盖顶层字段)。 -- 命令回调会使用 Mattermost 在 OpenClaw 注册 `oc_*` 命令时返回的每命令 token 进行校验。 -- 当注册失败、启动不完整,或回调 token 与任何已注册命令都不匹配时,斜杠回调会以失败关闭方式处理。 -- 可达性要求:回调端点必须能从 Mattermost 服务器访问。 - - 除非 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间中,否则不要将 `callbackUrl` 设为 `localhost`。 - - 除非该 URL 会将 `/api/channels/mattermost/command` 反向代理到 OpenClaw,否则不要将 `callbackUrl` 设为你的 Mattermost base URL。 - - 快速检查方式是运行 `curl https:///api/channels/mattermost/command`;GET 应返回来自 OpenClaw 的 `405 Method Not Allowed`,而不是 `404`。 -- Mattermost 出站允许列表要求: - - 如果你的回调目标是私有/tailnet/内部地址,请设置 Mattermost 的 `ServiceSettings.AllowedUntrustedInternalConnections` 以包含回调 host/domain。 - - 使用 host/domain 条目,而不是完整 URL。 - 正确:`gateway.tailnet-name.ts.net` - 错误:`https://gateway.tailnet-name.ts.net` + + + ## 环境变量(默认账户) -如果你更喜欢使用环境变量,请在 gateway 主机上设置以下变量: +如果你更喜欢使用环境变量,请在 Gateway 网关主机上设置: - `MATTERMOST_BOT_TOKEN=...` - `MATTERMOST_URL=https://chat.example.com` -环境变量仅适用于 **默认** 账户(`default`)。其他账户必须使用配置值。 + +环境变量仅适用于 **default** 账户(`default`)。其他账户必须使用配置值。 -`MATTERMOST_URL` 不能通过工作区 `.env` 设置;请参阅 [Workspace `.env` files](/zh-CN/gateway/security)。 +`MATTERMOST_URL` 不能通过工作区 `.env` 设置;请参见 [Workspace `.env` files](/zh-CN/gateway/security)。 + ## 聊天模式 Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: -- `oncall`(默认):仅在渠道中被 @提及时响应。 -- `onmessage`:响应每条渠道消息。 -- `onchar`:当消息以触发前缀开头时响应。 + + + 仅在渠道中被 @提及时响应。 + + + 响应每一条渠道消息。 + + + 当消息以触发前缀开头时响应。 + + 配置示例: @@ -132,16 +162,16 @@ Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: 说明: - `onchar` 仍会响应显式的 @提及。 -- `channels.mattermost.requireMention` 仍兼容旧版配置,但更推荐使用 `chatmode`。 +- `channels.mattermost.requireMention` 会继续兼容旧配置,但更推荐使用 `chatmode`。 ## 线程和会话 -使用 `channels.mattermost.replyToMode` 控制渠道和群组回复是保留在主渠道中,还是在触发消息下开启一个线程。 +使用 `channels.mattermost.replyToMode` 控制渠道和群组回复是保留在主渠道中,还是在触发消息下开启线程。 -- `off`(默认):只有当入站消息本身已经在线程中时,才在线程中回复。 -- `first`:对于顶层渠道/群组消息,在该消息下启动一个线程,并将对话路由到线程范围的会话。 -- `all`:在当前 Mattermost 中,其行为与 `first` 相同。 -- 私信会忽略此设置,并保持为非线程模式。 +- `off`(默认):仅当传入消息本身已经在线程中时,才在线程中回复。 +- `first`:对于渠道/群组中的顶层消息,在该消息下开启线程,并将对话路由到线程作用域的会话。 +- `all`:当前在 Mattermost 中与 `first` 行为相同。 +- 私信会忽略此设置,并保持非线程模式。 配置示例: @@ -157,8 +187,8 @@ Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: 说明: -- 线程范围的会话使用触发消息的 post id 作为线程根。 -- `first` 和 `all` 当前是等价的,因为一旦 Mattermost 已有线程根,后续分块和媒体内容都会继续留在同一线程中。 +- 线程作用域的会话使用触发消息的 post id 作为线程根。 +- `first` 和 `all` 当前等价,因为一旦 Mattermost 已有线程根,后续分块和媒体内容都会继续发送到同一线程。 ## 访问控制(私信) @@ -166,17 +196,16 @@ Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: - 通过以下命令批准: - `openclaw pairing list mattermost` - `openclaw pairing approve mattermost ` -- 公开私信:`channels.mattermost.dmPolicy="open"` 加 `channels.mattermost.allowFrom=["*"]`。 +- 公开私信:`channels.mattermost.dmPolicy="open"` 加上 `channels.mattermost.allowFrom=["*"]`。 ## 渠道(群组) -- 默认:`channels.mattermost.groupPolicy = "allowlist"`(需提及门控)。 +- 默认:`channels.mattermost.groupPolicy = "allowlist"`(提及门控)。 - 使用 `channels.mattermost.groupAllowFrom` 将发送者加入允许列表(推荐使用用户 ID)。 -- 每渠道提及覆盖位于 `channels.mattermost.groups..requireMention` - 或 `channels.mattermost.groups["*"].requireMention`(作为默认值)。 -- `@username` 匹配是可变的,并且仅当 `channels.mattermost.dangerouslyAllowNameMatching: true` 时启用。 -- 开放渠道:`channels.mattermost.groupPolicy="open"`(需提及门控)。 -- 运行时说明:如果完全缺少 `channels.mattermost`,运行时在进行群组检查时会回退到 `groupPolicy="allowlist"`(即使设置了 `channels.defaults.groupPolicy` 也是如此)。 +- 每个渠道的提及覆盖配置位于 `channels.mattermost.groups..requireMention`,或者使用 `channels.mattermost.groups["*"].requireMention` 作为默认值。 +- `@username` 匹配是可变的,且仅在 `channels.mattermost.dangerouslyAllowNameMatching: true` 时启用。 +- 公开渠道:`channels.mattermost.groupPolicy="open"`(提及门控)。 +- 运行时说明:如果 `channels.mattermost` 完全缺失,运行时在群组检查中会回退为 `groupPolicy="allowlist"`(即使已设置 `channels.defaults.groupPolicy` 也是如此)。 示例: @@ -194,28 +223,30 @@ Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: } ``` -## 出站交付的目标 +## 出站投递目标 将以下目标格式与 `openclaw message send` 或 cron/webhooks 一起使用: -- `channel:` 表示渠道 -- `user:` 表示私信 -- `@username` 表示私信(通过 Mattermost API 解析) +- `channel:` 表示一个渠道 +- `user:` 表示一个私信 +- `@username` 表示一个私信(通过 Mattermost API 解析) -裸的不透明 ID(如 `64ifufp...`)在 Mattermost 中是 **有歧义的**(用户 ID 与渠道 ID)。 + +裸的不透明 ID(如 `64ifufp...`)在 Mattermost 中是 **有歧义的**(用户 ID 或渠道 ID)。 -OpenClaw 会按 **用户优先** 进行解析: +OpenClaw 会按 **优先用户** 的顺序解析: -- 如果该 ID 作为用户存在(`GET /api/v4/users/` 成功),OpenClaw 会通过 `/api/v4/channels/direct` 解析直连渠道并发送 **私信**。 +- 如果该 ID 作为用户存在(`GET /api/v4/users/` 成功),OpenClaw 会先通过 `/api/v4/channels/direct` 解析直连渠道,然后发送 **私信**。 - 否则,该 ID 会被视为 **渠道 ID**。 -如果你需要确定性的行为,请始终使用显式前缀(`user:` / `channel:`)。 +如果你需要确定性行为,请始终使用显式前缀(`user:` / `channel:`)。 + ## 私信渠道重试 -当 OpenClaw 向 Mattermost 私信目标发送消息并且需要先解析直连渠道时,默认会对瞬时的直连渠道创建失败进行重试。 +当 OpenClaw 向 Mattermost 私信目标发送消息,且需要先解析直连渠道时,默认会重试临时性的直连渠道创建失败。 -使用 `channels.mattermost.dmChannelRetry` 为 Mattermost 插件全局调整该行为,或使用 `channels.mattermost.accounts..dmChannelRetry` 为单个账户调整。 +使用 `channels.mattermost.dmChannelRetry` 可为 Mattermost 插件全局调整该行为,或使用 `channels.mattermost.accounts..dmChannelRetry` 只为某个账户调整。 ```json5 { @@ -234,13 +265,13 @@ OpenClaw 会按 **用户优先** 进行解析: 说明: -- 这仅适用于私信渠道创建(`/api/v4/channels/direct`),而不是所有 Mattermost API 调用。 -- 重试适用于限流、5xx 响应以及网络或超时错误等瞬时失败。 -- 除 `429` 之外的 4xx 客户端错误会被视为永久性错误,不会重试。 +- 这仅适用于私信渠道创建(`/api/v4/channels/direct`),并不适用于每一次 Mattermost API 调用。 +- 重试适用于限流、5xx 响应,以及网络或超时错误等临时性失败。 +- 除 `429` 外的 4xx 客户端错误会被视为永久性错误,不会重试。 ## 预览流式传输 -Mattermost 会将思考、工具活动和部分回复文本流式写入同一个 **草稿预览消息** 中,并在最终答案可安全发送时就地完成。预览会在同一个 post id 上更新,而不是用逐块消息刷屏。媒体/错误类型的最终结果会取消待处理的预览编辑,并使用常规交付,而不是刷新一个一次性的预览消息。 +Mattermost 会将思考过程、工具活动和部分回复文本流式写入单个 **草稿预览消息**,并在最终答案可安全发送时原地完成定稿。预览会在同一个 post id 上更新,而不是通过逐块消息刷屏。媒体/错误类型的最终消息会取消待处理的预览编辑,并改用常规投递,而不是刷新一个无用的预览消息。 通过 `channels.mattermost.streaming` 启用: @@ -254,23 +285,27 @@ Mattermost 会将思考、工具活动和部分回复文本流式写入同一个 } ``` -说明: + + + - `partial` 是常见选择:一个预览消息会随着回复增长而被编辑,最后用完整答案定稿。 + - `block` 在预览消息中使用追加式草稿分块。 + - `progress` 在生成期间显示状态预览,并仅在完成时发送最终答案。 + - `off` 会禁用预览流式传输。 + + + - 如果流无法原地定稿(例如消息在流过程中被删除),OpenClaw 会回退为发送一条新的最终消息,因此回复不会丢失。 + - 纯推理负载不会显示在渠道消息中,包括以 `> Reasoning:` 引述块形式到达的文本。设置 `/reasoning on` 可在其他界面中查看思考过程;Mattermost 的最终消息只保留答案。 + - 渠道映射矩阵请参见 [Streaming](/zh-CN/concepts/streaming#preview-streaming-modes)。 + + -- `partial` 是常见选择:使用一条预览消息,随着回复增长不断编辑,最后以完整答案完成。 -- `block` 在预览消息中使用追加式草稿分块。 -- `progress` 会在生成期间显示状态预览,并仅在完成时发布最终答案。 -- `off` 会禁用预览流式传输。 -- 如果流无法原地完成(例如消息在流过程中被删除),OpenClaw 会回退为发送一条全新的最终消息,以确保回复不会丢失。 -- 仅包含推理的负载不会发布到渠道中,包括以 `> Reasoning:` 引用块形式到达的文本。设置 `/reasoning on` 可在其他界面中查看思考内容;Mattermost 的最终消息仅保留答案。 -- 渠道映射矩阵请参见 [Streaming](/zh-CN/concepts/streaming#preview-streaming-modes)。 +## 表情回应(消息工具) -## Reactions(message 工具) - -- 使用 `message action=react` 并设置 `channel=mattermost`。 +- 使用 `message action=react`,并设置 `channel=mattermost`。 - `messageId` 是 Mattermost 的 post id。 - `emoji` 接受如 `thumbsup` 或 `:+1:` 之类的名称(冒号可选)。 -- 设置 `remove=true`(布尔值)可移除 reaction。 -- Reaction 添加/移除事件会作为系统事件转发到已路由的智能体会话。 +- 设置 `remove=true`(布尔值)可移除一个回应。 +- 添加/移除表情回应事件会作为系统事件转发到已路由的智能体会话。 示例: @@ -281,14 +316,14 @@ message action=react channel=mattermost target=channel: messageId=.actions.reactions`。 +- `channels.mattermost.actions.reactions`:启用/禁用表情回应操作(默认 true)。 +- 每账户覆盖:`channels.mattermost.accounts..actions.reactions`。 -## 交互式按钮(message 工具) +## 交互式按钮(消息工具) -发送带有可点击按钮的消息。当用户点击按钮时,智能体会收到该选择并可以作出响应。 +发送带可点击按钮的消息。当用户点击按钮时,智能体会收到所选内容并可作出响应。 -通过将 `inlineButtons` 添加到渠道能力中来启用按钮: +通过在渠道能力中添加 `inlineButtons` 来启用按钮: ```json5 { @@ -300,7 +335,7 @@ message action=react channel=mattermost target=channel: messageId= buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]] @@ -308,40 +343,46 @@ message action=send channel=mattermost target=channel: buttons=[[{"te 按钮字段: -- `text`(必填):显示标签。 -- `callback_data`(必填):点击后回传的值(用作 action ID)。 -- `style`(可选):`"default"`、`"primary"` 或 `"danger"`。 + + 显示标签。 + + + 点击后回传的值(用作动作 ID)。 + + + 按钮样式。 + 当用户点击按钮时: -1. 所有按钮都会被替换为一行确认文本(例如 “✓ **Yes** selected by @user”)。 -2. 智能体会将该选择作为入站消息接收并作出响应。 + + + 所有按钮都会被替换为一行确认文本(例如:“✓ **Yes** selected by @user”)。 + + + 智能体会将该选择作为一条入站消息接收,并作出响应。 + + -说明: - -- 按钮回调使用 HMAC-SHA256 校验(自动完成,无需配置)。 -- Mattermost 会从其 API 响应中移除 callback data(安全特性),因此点击后所有按钮都会被移除——无法部分移除。 -- 包含连字符或下划线的 action ID 会被自动清理 - (Mattermost 路由限制)。 - -配置: - -- `channels.mattermost.capabilities`:能力字符串数组。添加 `"inlineButtons"` 以在智能体系统提示中启用按钮工具描述。 -- `channels.mattermost.interactions.callbackBaseUrl`:按钮回调的可选外部 base URL - (例如 `https://gateway.example.com`)。当 Mattermost 无法直接通过其绑定 host 访问 gateway 时使用此项。 -- 在多账户设置中,你也可以在 - `channels.mattermost.accounts..interactions.callbackBaseUrl` 下设置相同字段。 -- 如果省略 `interactions.callbackBaseUrl`,OpenClaw 会先根据 - `gateway.customBindHost` + `gateway.port` 推导回调 URL,然后回退到 `http://localhost:`。 -- 可达性规则:按钮回调 URL 必须能从 Mattermost 服务器访问。 - 只有在 Mattermost 和 OpenClaw 运行于同一主机/网络命名空间时,`localhost` 才可用。 -- 如果你的回调目标是私有/tailnet/内部地址,请将其 host/domain 添加到 Mattermost 的 - `ServiceSettings.AllowedUntrustedInternalConnections`。 + + + - 按钮回调使用 HMAC-SHA256 校验(自动完成,无需配置)。 + - Mattermost 会从其 API 响应中移除回调数据(安全特性),因此按钮在点击后都会被移除——无法只移除部分按钮。 + - 包含连字符或下划线的动作 ID 会被自动净化处理(Mattermost 路由限制)。 + + + - `channels.mattermost.capabilities`:能力字符串数组。添加 `"inlineButtons"` 可在智能体系统提示词中启用按钮工具描述。 + - `channels.mattermost.interactions.callbackBaseUrl`:按钮回调可选的外部基础 URL(例如 `https://gateway.example.com`)。当 Mattermost 无法直接访问 Gateway 网关绑定的 host 时使用此项。 + - 在多账户设置中,你也可以在 `channels.mattermost.accounts..interactions.callbackBaseUrl` 下设置相同字段。 + - 如果省略 `interactions.callbackBaseUrl`,OpenClaw 会根据 `gateway.customBindHost` + `gateway.port` 推导回调 URL,然后回退到 `http://localhost:`。 + - 可达性规则:按钮回调 URL 必须可从 Mattermost 服务器访问。只有当 Mattermost 和 OpenClaw 运行在同一主机/网络命名空间中时,`localhost` 才可用。 + - 如果你的回调目标是私有地址、tailnet 地址或内部地址,请将其 host/domain 添加到 Mattermost 的 `ServiceSettings.AllowedUntrustedInternalConnections` 中。 + + ### 直接 API 集成(外部脚本) -外部脚本和 webhook 可以直接通过 Mattermost REST API 发布按钮, -而不必通过智能体的 `message` 工具。尽可能使用插件中的 `buildButtonAttachments()`;如果直接发送原始 JSON,请遵循以下规则: +外部脚本和 webhooks 可以直接通过 Mattermost REST API 发送按钮,而不必经过智能体的 `message` 工具。尽量使用插件中的 `buildButtonAttachments()`;如果直接发送原始 JSON,请遵循以下规则: **负载结构:** @@ -354,17 +395,17 @@ message action=send channel=mattermost target=channel: buttons=[[{"te { actions: [ { - id: "mybutton01", // 仅允许字母数字 —— 见下文 + id: "mybutton01", // 仅限字母数字 —— 见下文 type: "button", // 必填,否则点击会被静默忽略 name: "Approve", // 显示标签 style: "primary", // 可选:"default"、"primary"、"danger" integration: { url: "https://gateway.example.com/mattermost/interactions/default", context: { - action_id: "mybutton01", // 必须与按钮 id 匹配(用于名称查找) + action_id: "mybutton01", // 必须与按钮 id 一致(用于名称查找) action: "approve", - // ... 任意自定义字段 ... - _token: "", // 见下方 HMAC 章节 + // ... any custom fields ... + _token: "", // 见下方 HMAC 小节 }, }, }, @@ -375,28 +416,38 @@ message action=send channel=mattermost target=channel: buttons=[[{"te } ``` -**关键规则:** + +**关键规则** -1. Attachments 放在 `props.attachments` 中,而不是顶层 `attachments`(否则会被静默忽略)。 -2. 每个 action 都需要 `type: "button"` —— 否则点击会被静默吞掉。 -3. 每个 action 都需要 `id` 字段 —— 没有 ID 的 action 会被 Mattermost 忽略。 -4. Action `id` 必须是 **仅字母数字**(`[a-zA-Z0-9]`)。连字符和下划线会破坏 - Mattermost 服务端的 action 路由(返回 404)。使用前请移除它们。 -5. `context.action_id` 必须与按钮的 `id` 匹配,这样确认消息才会显示按钮名称 - (例如 “Approve”),而不是原始 ID。 +1. attachments 放在 `props.attachments` 中,而不是顶层 `attachments`(否则会被静默忽略)。 +2. 每个动作都需要 `type: "button"` —— 没有它,点击会被静默吞掉。 +3. 每个动作都需要 `id` 字段 —— 没有 ID 的动作会被 Mattermost 忽略。 +4. 动作 `id` 必须 **仅包含字母数字**(`[a-zA-Z0-9]`)。连字符和下划线会破坏 Mattermost 服务端动作路由(返回 404)。使用前请先移除它们。 +5. `context.action_id` 必须与按钮的 `id` 一致,这样确认消息才会显示按钮名称(例如 “Approve”),而不是原始 ID。 6. `context.action_id` 是必填项 —— 没有它,交互处理器会返回 400。 + -**HMAC token 生成:** +**HMAC token 生成** -Gateway 网关使用 HMAC-SHA256 校验按钮点击。外部脚本必须生成与 gateway 校验逻辑匹配的 token: +Gateway 网关使用 HMAC-SHA256 校验按钮点击。外部脚本必须生成与 Gateway 网关校验逻辑一致的 token: -1. 从 bot token 派生密钥: - `HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)` -2. 使用除 `_token` 之外的所有字段构建 context 对象。 -3. 使用 **已排序的键** 和 **无空格** 进行序列化(gateway 使用带排序键的 `JSON.stringify`, - 会生成紧凑输出)。 -4. 签名:`HMAC-SHA256(key=secret, data=serializedContext)` -5. 将生成的十六进制摘要作为 `_token` 添加到 context 中。 + + + `HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)` + + + 构建包含除 `_token` 之外所有字段的 context 对象。 + + + 使用 **已排序的键** 且 **不带空格** 进行序列化(Gateway 网关使用带排序键的 `JSON.stringify`,输出为紧凑格式)。 + + + `HMAC-SHA256(key=secret, data=serializedContext)` + + + 将生成的十六进制摘要作为 `_token` 添加到 context 中。 + + Python 示例: @@ -415,24 +466,20 @@ token = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest() context = {**ctx, "_token": token} ``` -常见 HMAC 陷阱: - -- Python 的 `json.dumps` 默认会添加空格(`{"key": "val"}`)。请使用 - `separators=(",", ":")` 以匹配 JavaScript 的紧凑输出(`{"key":"val"}`)。 -- 始终对 **所有** context 字段(除 `_token` 外)进行签名。Gateway 网关会移除 `_token`, - 然后对剩余的所有内容进行签名。只对其中一部分签名会导致静默校验失败。 -- 使用 `sort_keys=True` —— gateway 会在签名前对键排序,而 Mattermost 在存储负载时 - 可能会重排 context 字段。 -- 从 bot token 派生密钥(确定性),而不是使用随机字节。创建按钮的进程与执行校验的 gateway - 必须使用同一个密钥。 + + + - Python 的 `json.dumps` 默认会添加空格(`{"key": "val"}`)。使用 `separators=(",", ":")` 以匹配 JavaScript 的紧凑输出(`{"key":"val"}`)。 + - 始终对 **所有** context 字段(除 `_token` 外)进行签名。Gateway 网关会先移除 `_token`,然后对剩余全部字段签名。只签名子集会导致静默校验失败。 + - 使用 `sort_keys=True` —— Gateway 网关会在签名前对键排序,而 Mattermost 在存储负载时可能会重排 context 字段。 + - 应从 bot token 派生 secret(确定性),而不是使用随机字节。创建按钮的进程和负责校验的 Gateway 网关必须使用相同的 secret。 + + ## 目录适配器 -Mattermost 插件包含一个目录适配器,可通过 Mattermost API 解析渠道名和用户名。 -这使得你可以在 `openclaw message send` 以及 cron/webhook 交付中使用 -`#channel-name` 和 `@username` 目标。 +Mattermost 插件包含一个目录适配器,可通过 Mattermost API 解析渠道名和用户名。这使得在 `openclaw message send` 和 cron/webhook 投递中可以使用 `#channel-name` 和 `@username` 目标。 -无需额外配置——该适配器会使用账户配置中的 bot token。 +无需配置——该适配器会使用账户配置中的 bot token。 ## 多账户 @@ -453,34 +500,38 @@ Mattermost 支持在 `channels.mattermost.accounts` 下配置多个账户: ## 故障排除 -- 渠道中没有回复:确保 bot 已加入该渠道,并提及它(oncall)、使用触发前缀(onchar),或设置 `chatmode: "onmessage"`。 -- 认证错误:检查 bot token、base URL,以及该账户是否已启用。 -- 多账户问题:环境变量仅适用于 `default` 账户。 -- 原生斜杠命令返回 `Unauthorized: invalid command token.`:OpenClaw - 未接受回调 token。常见原因: - - 斜杠命令注册失败,或启动时只完成了部分注册 - - 回调命中了错误的 gateway/账户 - - Mattermost 仍保留指向旧回调目标的旧命令 - - gateway 重启后未重新激活斜杠命令 -- 如果原生斜杠命令停止工作,请检查日志中是否有 - `mattermost: failed to register slash commands` 或 - `mattermost: native slash commands enabled but no commands could be registered`。 -- 如果省略了 `callbackUrl`,且日志警告回调被解析为 - `http://127.0.0.1:18789/...`,这个 URL 很可能只有在 - Mattermost 与 OpenClaw 运行于同一主机/网络命名空间时才可访问。请改为设置一个 - 显式的、外部可访问的 `commands.callbackUrl`。 -- 按钮显示为白框:智能体发送的按钮数据可能格式错误。请检查每个按钮是否同时具有 `text` 和 `callback_data` 字段。 -- 按钮能渲染但点击无反应:请确认 Mattermost 服务器配置中的 `AllowedUntrustedInternalConnections` 包含 `127.0.0.1 localhost`,并且 `ServiceSettings` 中的 `EnablePostActionIntegration` 为 `true`。 -- 按钮点击后返回 404:按钮 `id` 很可能包含连字符或下划线。Mattermost 的 action 路由器无法处理非字母数字 ID。请仅使用 `[a-zA-Z0-9]`。 -- Gateway 网关日志显示 `invalid _token`:HMAC 不匹配。请检查你是否对所有 context 字段(而非子集)进行了签名、是否使用了排序键、以及是否使用了紧凑 JSON(无空格)。详见上文 HMAC 章节。 -- Gateway 网关日志显示 `missing _token in context`:按钮的 context 中没有 `_token` 字段。请确保在构建 integration 负载时包含它。 -- 确认消息显示的是原始 ID 而不是按钮名称:`context.action_id` 与按钮的 `id` 不匹配。请将两者设置为同一个已清理的值。 -- 智能体不知道按钮功能:在 Mattermost 渠道配置中添加 `capabilities: ["inlineButtons"]`。 + + + 确保机器人已加入该渠道,并提及它(oncall),使用触发前缀(onchar),或设置 `chatmode: "onmessage"`。 + + + - 检查 bot token、base URL,以及账户是否已启用。 + - 多账户问题:环境变量仅适用于 `default` 账户。 + + + - `Unauthorized: invalid command token.`:OpenClaw 未接受该回调 token。常见原因: + - 斜杠命令注册失败,或启动时仅部分完成 + - 回调命中了错误的 Gateway 网关/账户 + - Mattermost 仍保留指向旧回调目标的旧命令 + - Gateway 网关重启后未重新激活斜杠命令 + - 如果原生斜杠命令停止工作,请检查日志中是否有 `mattermost: failed to register slash commands` 或 `mattermost: native slash commands enabled but no commands could be registered`。 + - 如果省略了 `callbackUrl`,且日志警告回调被解析为 `http://127.0.0.1:18789/...`,那么该 URL 很可能只有在 Mattermost 与 OpenClaw 运行于同一主机/网络命名空间时才可访问。请改为设置一个显式、外部可访问的 `commands.callbackUrl`。 + + + - 按钮显示为白框:智能体可能发送了格式错误的按钮数据。检查每个按钮是否都同时包含 `text` 和 `callback_data` 字段。 + - 按钮已渲染,但点击无反应:请确认 Mattermost 服务器配置中的 `AllowedUntrustedInternalConnections` 包含 `127.0.0.1 localhost`,并且 `ServiceSettings` 中的 `EnablePostActionIntegration` 为 `true`。 + - 点击按钮返回 404:按钮的 `id` 很可能包含连字符或下划线。Mattermost 的动作路由器无法处理非字母数字 ID。请仅使用 `[a-zA-Z0-9]`。 + - Gateway 网关日志出现 `invalid _token`:HMAC 不匹配。请检查你是否对所有 context 字段(而不是子集)进行了签名,是否使用了已排序的键,以及是否使用了紧凑 JSON(无空格)。参见上方 HMAC 小节。 + - Gateway 网关日志出现 `missing _token in context`:按钮的 context 中没有 `_token` 字段。请确保在构建 integration 负载时包含该字段。 + - 确认信息显示原始 ID 而不是按钮名称:`context.action_id` 与按钮的 `id` 不匹配。请将二者设置为相同的净化值。 + - 智能体不了解按钮:请在 Mattermost 渠道配置中添加 `capabilities: ["inlineButtons"]`。 + + ## 相关内容 -- [Channels Overview](/zh-CN/channels) —— 所有支持的渠道 -- [Pairing](/zh-CN/channels/pairing) —— 私信认证与配对流程 -- [Groups](/zh-CN/channels/groups) —— 群聊行为与提及门控 -- [Channel Routing](/zh-CN/channels/channel-routing) —— 消息的会话路由 -- [Security](/zh-CN/gateway/security) —— 访问模型与加固 +- [Channel Routing](/zh-CN/channels/channel-routing) — 消息的会话路由 +- [Channels Overview](/zh-CN/channels) — 所有受支持的渠道 +- [Groups](/zh-CN/channels/groups) — 群聊行为和提及门控 +- [Pairing](/zh-CN/channels/pairing) — 私信身份验证和配对流程 +- [Security](/zh-CN/gateway/security) — 访问模型和加固措施 diff --git a/docs/zh-CN/cli/doctor.md b/docs/zh-CN/cli/doctor.md index a7f55d204..6cbea01ee 100644 --- a/docs/zh-CN/cli/doctor.md +++ b/docs/zh-CN/cli/doctor.md @@ -1,21 +1,21 @@ --- read_when: - - 你遇到了连接或凭证问题,并希望获得引导式修复方案 - - 你已完成更新,并想进行安装完整性检查 + - 你遇到了连接或认证问题,并希望获得引导式修复方案 + - 你已完成更新,并想做一次完整性检查 summary: '`openclaw doctor` 的 CLI 参考(健康检查 + 引导式修复)' title: Doctor x-i18n: - generated_at: "2026-04-25T01:02:45Z" + generated_at: "2026-04-26T08:13:21Z" model: gpt-5.4 provider: openai - source_hash: 18e185d17d91d1677d0b16152d022b633d012d22d484bd9961820b200d5c4ce5 + source_hash: 1e2c21765f8c287c8d2aa066004ac516566c76a455337c377cf282551619e92a source_path: cli/doctor.md workflow: 15 --- # `openclaw doctor` -用于 Gateway 网关和渠道的健康检查 + 快速修复。 +用于 Gateway 网关和各渠道的健康检查 + 快速修复。 相关内容: @@ -34,30 +34,31 @@ openclaw doctor --generate-gateway-token ## 选项 -- `--no-workspace-suggestions`:禁用工作区 memory/search 建议 -- `--yes`:无需提示,接受默认值 -- `--repair`:无需提示,应用推荐修复 +- `--no-workspace-suggestions`:禁用工作区记忆/搜索建议 +- `--yes`:接受默认值而不提示 +- `--repair`:不经提示应用推荐修复 - `--fix`:`--repair` 的别名 - `--force`:应用更激进的修复,包括在需要时覆盖自定义服务配置 - `--non-interactive`:无提示运行;仅执行安全迁移 -- `--generate-gateway-token`:生成并配置 gateway token +- `--generate-gateway-token`:生成并配置 Gateway 网关令牌 - `--deep`:扫描系统服务以查找额外的 Gateway 网关安装 说明: -- 交互式提示(如钥匙串 / OAuth 修复)仅在 stdin 是 TTY 且**未**设置 `--non-interactive` 时运行。无头运行(cron、Telegram、无终端)将跳过提示。 -- 性能:非交互式 `doctor` 运行会跳过预先加载插件,因此无头健康检查可保持快速。交互式会话仍会在某项检查需要插件参与时完整加载插件。 +- 交互式提示(例如钥匙串/OAuth 修复)仅会在 stdin 是 TTY 且**未**设置 `--non-interactive` 时运行。无头运行(cron、Telegram、无终端)会跳过提示。 +- 性能:非交互式 `doctor` 运行会跳过急切的插件加载,以保持无头健康检查快速执行。交互式会话仍会在检查需要插件参与时完整加载插件。 - `--fix`(`--repair` 的别名)会将备份写入 `~/.openclaw/openclaw.json.bak`,并删除未知配置键,同时列出每一项被移除的内容。 -- 状态完整性检查现在会检测会话目录中的孤立 transcript 文件,并可将其归档为 `.deleted.`,以安全回收空间。 -- Doctor 还会扫描 `~/.openclaw/cron/jobs.json`(或 `cron.store`)中的旧版 cron 作业结构,并可在调度器需要在运行时自动规范化之前就地重写它们。 -- Doctor 会修复缺失的内置插件运行时依赖,而不会写入已打包的全局安装目录。对于 root 拥有的 npm 安装或强化配置的 systemd 单元,请将 `OPENCLAW_PLUGIN_STAGE_DIR` 设置为可写目录,例如 `/var/lib/openclaw/plugin-runtime-deps`。 -- Doctor 会自动将旧版扁平 Talk 配置(`talk.voiceId`、`talk.modelId` 及相关项)迁移到 `talk.provider` + `talk.providers.`。 -- 当唯一差异只是对象键顺序时,重复执行 `doctor --fix` 将不再报告 / 应用 Talk 规范化。 -- Doctor 包含 memory-search 就绪性检查,并且在缺少 embedding 凭证时会建议运行 `openclaw configure --section model`。 -- 如果已启用沙箱模式但 Docker 不可用,doctor 会报告高信号警告,并提供修复建议(`install Docker` 或 `openclaw config set agents.defaults.sandbox.mode off`)。 -- 如果 `gateway.auth.token` / `gateway.auth.password` 由 SecretRef 管理,且在当前命令路径中不可用,doctor 会报告只读警告,并且不会写入明文后备凭证。 -- 如果在修复路径中渠道 SecretRef 检查失败,doctor 会继续执行,并报告警告,而不是提前退出。 -- Telegram `allowFrom` 用户名自动解析(`doctor --fix`)要求当前命令路径中存在可解析的 Telegram token。如果 token 检查不可用,doctor 会报告警告,并在本次运行中跳过自动解析。 +- 状态完整性检查现在会检测会话目录中孤立的转录文件,并可将其归档为 `.deleted.`,以安全回收空间。 +- Doctor 还会扫描 `~/.openclaw/cron/jobs.json`(或 `cron.store`)中旧版 cron 任务结构,并可在调度器需要在运行时自动规范化之前直接原地重写它们。 +- Doctor 会修复缺失的内置插件运行时依赖,而不会写入已打包的全局安装。对于 root 所有的 npm 安装或受加固的 systemd 单元,请将 `OPENCLAW_PLUGIN_STAGE_DIR` 设置为可写目录,例如 `/var/lib/openclaw/plugin-runtime-deps`。 +- 当其他监督程序负责 Gateway 网关生命周期时,请设置 `OPENCLAW_SERVICE_REPAIR_POLICY=external`。Doctor 仍会报告 Gateway 网关/服务健康状态并应用非服务类修复,但会跳过服务安装、启动、重启、引导和旧版服务清理。 +- Doctor 会自动将旧版扁平 Talk 配置(`talk.voiceId`、`talk.modelId` 等)迁移到 `talk.provider` + `talk.providers.`。 +- 重复执行 `doctor --fix` 时,如果唯一差异只是对象键顺序,将不再报告/应用 Talk 规范化。 +- Doctor 包含记忆搜索就绪性检查,并可在缺少嵌入凭证时推荐运行 `openclaw configure --section model`。 +- 如果启用了沙箱模式但 Docker 不可用,doctor 会报告高信号警告并给出修复建议(`install Docker` 或 `openclaw config set agents.defaults.sandbox.mode off`)。 +- 如果 `gateway.auth.token`/`gateway.auth.password` 由 SecretRef 管理且在当前命令路径中不可用,doctor 会报告只读警告,并且不会写入明文回退凭证。 +- 如果渠道 SecretRef 检查在修复路径中失败,doctor 会继续执行并报告警告,而不是提前退出。 +- Telegram `allowFrom` 用户名自动解析(`doctor --fix`)要求在当前命令路径中存在可解析的 Telegram 令牌。如果令牌检查不可用,doctor 会报告警告,并在本次运行中跳过自动解析。 ## macOS:`launchctl` 环境变量覆盖 diff --git a/docs/zh-CN/cli/update.md b/docs/zh-CN/cli/update.md index f6465e4c0..2d54cd7ac 100644 --- a/docs/zh-CN/cli/update.md +++ b/docs/zh-CN/cli/update.md @@ -1,14 +1,14 @@ --- read_when: - - 你想安全地更新一个源代码检出副本 + - 你想要安全地更新一个源代码检出副本 - 你需要了解 `--update` 简写行为 summary: '`openclaw update` 的 CLI 参考(相对安全的源更新 + Gateway 网关自动重启)' title: 更新 x-i18n: - generated_at: "2026-04-26T05:40:43Z" + generated_at: "2026-04-26T08:13:19Z" model: gpt-5.4 provider: openai - source_hash: 67da56f0281b6268063952fc8cab70842a0882a6c7d0add65cd2654c3bff41fa + source_hash: b06cab7f4eee12e0fa474b2ea0fb2848fb4899517f9446369888391d2eb3ea9e source_path: cli/update.md workflow: 15 --- @@ -17,8 +17,7 @@ x-i18n: 安全地更新 OpenClaw,并在 stable/beta/dev 渠道之间切换。 -如果你是通过 **npm/pnpm/bun** 安装的(全局安装,没有 git 元数据), -更新会通过 [更新](/zh-CN/install/updating) 中的软件包管理器流程进行。 +如果你通过 **npm/pnpm/bun** 安装(全局安装,没有 git 元数据),更新会通过 [更新](/zh-CN/install/updating) 中的包管理器流程进行。 ## 用法 @@ -39,19 +38,19 @@ openclaw --update ## 选项 -- `--no-restart`:成功更新后跳过重启 Gateway 网关服务。对于确实会重启 Gateway 网关的软件包管理器更新,命令只有在验证重启后的服务报告了预期的更新版本后才会成功。 +- `--no-restart`:成功更新后跳过重启 Gateway 网关服务。对于确实会重启 Gateway 网关的包管理器更新,命令只有在验证重启后的服务报告了预期的更新版本后才会成功。 - `--channel `:设置更新渠道(git + npm;会持久化到配置中)。 -- `--tag `:仅为此次更新覆盖软件包目标。对于软件包安装,`main` 会映射到 `github:openclaw/openclaw#main`。 -- `--dry-run`:预览计划执行的更新操作(渠道/标签/目标/重启流程),不会写入配置、安装、同步插件或重启。 -- `--json`:打印机器可读的 `UpdateRunResult` JSON;当在更新后插件同步期间检测到 npm 插件产物漂移时,其中包含 `postUpdate.plugins.integrityDrifts`。 -- `--timeout `:每个步骤的超时时间(默认是 `1200s`)。 +- `--tag `:仅对此次更新覆盖包目标。对于包安装,`main` 会映射到 `github:openclaw/openclaw#main`。 +- `--dry-run`:预览计划执行的更新操作(渠道/tag/目标/重启流程),不会写入配置、安装、同步插件或重启。 +- `--json`:打印机器可读的 `UpdateRunResult` JSON;当在更新后插件同步期间检测到 npm 插件构件漂移时,其中包括 `postUpdate.plugins.integrityDrifts`。 +- `--timeout `:每一步的超时时间(默认 1200 秒)。 - `--yes`:跳过确认提示(例如降级确认) 注意:降级需要确认,因为旧版本可能会破坏配置。 ## `update status` -显示当前激活的更新渠道 + git 标签/分支/SHA(对于源代码检出副本),以及更新可用性。 +显示当前活动的更新渠道 + git tag/branch/SHA(针对源代码检出副本),以及更新可用性。 ```bash openclaw update status @@ -61,69 +60,62 @@ openclaw update status --timeout 10 选项: -- `--json`:打印机器可读的 Status JSON。 -- `--timeout `:检查的超时时间(默认是 `3s`)。 +- `--json`:打印机器可读的状态 JSON。 +- `--timeout `:检查超时时间(默认 3 秒)。 ## `update wizard` -交互式流程,用于选择更新渠道并确认更新后是否重启 Gateway 网关 -(默认会重启)。如果你在没有 git 检出副本的情况下选择 `dev`,它会 -提供创建检出副本的选项。 +交互式流程,用于选择更新渠道并确认更新后是否重启 Gateway 网关(默认会重启)。如果你在没有 git 检出副本的情况下选择 `dev`,它会提供创建一个检出副本的选项。 选项: - `--timeout `:每个更新步骤的超时时间(默认 `1200`) -## 它会执行什么 +## 它会做什么 -当你显式切换渠道(`--channel ...`)时,OpenClaw 也会保持 -安装方式一致: +当你显式切换渠道(`--channel ...`)时,OpenClaw 还会保持安装方式一致: -- `dev` → 确保存在一个 git 检出副本(默认:`~/openclaw`,可通过 `OPENCLAW_GIT_DIR` 覆盖), - 更新它,并从该检出副本安装全局 CLI。 +- `dev` → 确保存在一个 git 检出副本(默认:`~/openclaw`,可通过 `OPENCLAW_GIT_DIR` 覆盖),更新它,并从该检出副本安装全局 CLI。 - `stable` → 使用 `latest` 从 npm 安装。 -- `beta` → 优先使用 npm 的 `beta` dist-tag,但当 beta 不存在或比当前 stable 版本更旧时,会回退到 `latest`。 +- `beta` → 优先使用 npm dist-tag `beta`,但当 beta 缺失或比当前 stable 版本更旧时,会回退到 `latest`。 -Gateway 网关核心自动更新器(在配置中启用时)会复用这一路径进行更新。 +Gateway 网关核心自动更新器(在配置中启用时)会复用同一条更新路径。 -对于软件包管理器安装,`openclaw update` 会在调用软件包管理器之前解析目标软件包 -版本。如果已安装版本与目标完全匹配,且不需要持久化任何更新渠道变更, -则命令会在软件包安装、插件同步、completion 刷新 -或 Gateway 网关重启工作开始前以已跳过状态退出。 +对于包管理器安装,`openclaw update` 会先解析目标包版本,然后再调用包管理器。即使已安装版本已经与目标一致,该命令仍会刷新全局包安装,然后执行插件同步、补全刷新和重启工作。这样可以确保已打包的 sidecar 和渠道所属的插件记录与已安装的 OpenClaw 构建保持一致。 ## Git 检出副本流程 渠道: -- `stable`:检出最新的非 beta 标签,然后执行 build + doctor。 -- `beta`:优先选择最新的 `-beta` 标签,但当 beta 不存在或更旧时回退到最新的 stable 标签。 -- `dev`:检出 `main`,然后执行 fetch + rebase。 +- `stable`:检出最新的非 beta tag,然后 build + doctor。 +- `beta`:优先选择最新的 `-beta` tag,但如果 beta 缺失或更旧,则回退到最新的 stable tag。 +- `dev`:检出 `main`,然后 fetch + rebase。 高级流程: -1. 需要一个干净的工作区(没有未提交的更改)。 -2. 切换到所选渠道(标签或分支)。 -3. 拉取上游(仅 `dev`)。 -4. 仅 `dev`:在临时工作区中执行预检 lint + TypeScript build;如果最新提交失败,则最多回退 10 个提交以找到最新的可干净构建版本。 -5. rebase 到所选提交(仅 `dev`)。 -6. 使用仓库的软件包管理器安装依赖。对于 pnpm 检出副本,更新器会按需引导安装 `pnpm`(优先通过 `corepack`,然后回退为临时执行 `npm install pnpm@10`),而不是在 pnpm workspace 中运行 `npm run build`。 -7. 执行 build + 构建 Control UI。 -8. 将运行 `openclaw doctor` 作为最终的“安全更新”检查。 -9. 将插件同步到当前激活的渠道(`dev` 使用内置插件;`stable`/`beta` 使用 npm),并更新通过 npm 安装的插件。 +1. 需要一个干净的工作树(没有未提交的更改)。 +2. 切换到所选渠道(tag 或 branch)。 +3. 获取上游更新(仅 `dev`)。 +4. 仅 `dev`:在临时工作树中执行预检 lint + TypeScript build;如果最新提交失败,则最多回退 10 个提交,以找到最新一个可干净构建的提交。 +5. 变基到所选提交之上(仅 `dev`)。 +6. 使用仓库的包管理器安装依赖。对于 pnpm 检出副本,更新器会按需引导 `pnpm`(优先通过 `corepack`,然后使用临时的 `npm install pnpm@10` 作为回退),而不是在 pnpm workspace 中运行 `npm run build`。 +7. build,并构建 Control UI。 +8. 运行 `openclaw doctor`,作为最终的“安全更新”检查。 +9. 将插件同步到当前活动渠道(`dev` 使用内置插件;`stable`/`beta` 使用 npm),并更新通过 npm 安装的插件。 -如果某个精确固定版本的 npm 插件更新解析到的产物,其完整性与已存储的安装记录 -不同,`openclaw update` 会中止该插件产物更新,而不是安装它。只有在确认 -你信任该新产物后,才应显式重新安装或更新该插件。 +如果一个精确固定版本的 npm 插件更新解析到的构件,其完整性与已存储的安装记录不同,`openclaw update` 会中止该插件构件更新,而不是安装它。只有在确认你信任这个新构件之后,才应显式重新安装或更新该插件。 -如果 pnpm 引导安装仍然失败,更新器现在会提前停止,并报告一个与软件包管理器相关的错误,而不是尝试在检出副本中执行 `npm run build`。 +更新后的插件同步失败会导致更新结果失败,并停止后续的重启工作。修复插件安装/更新错误后,再重新运行 `openclaw update`。 + +如果 pnpm 引导仍然失败,更新器现在会提前停止,并报告一个特定于包管理器的错误,而不是尝试在检出副本中运行 `npm run build`。 ## `--update` 简写 -`openclaw --update` 会被重写为 `openclaw update`(对 shell 和启动脚本很有用)。 +`openclaw --update` 会重写为 `openclaw update`(对 shell 和启动脚本很有用)。 ## 相关内容 -- `openclaw doctor`(在 git 检出副本上会提供先运行 update 的选项) +- `openclaw doctor`(在 git 检出副本上会先提供运行更新的选项) - [开发渠道](/zh-CN/install/development-channels) - [更新](/zh-CN/install/updating) - [CLI 参考](/zh-CN/cli) diff --git a/docs/zh-CN/gateway/doctor.md b/docs/zh-CN/gateway/doctor.md index e83076b18..0d8e8da86 100644 --- a/docs/zh-CN/gateway/doctor.md +++ b/docs/zh-CN/gateway/doctor.md @@ -1,20 +1,20 @@ --- read_when: - 添加或修改 Doctor 迁移 - - 引入破坏性配置变更 + - 引入破坏性配置更改 sidebarTitle: Doctor -summary: Doctor 命令:健康检查、配置迁移和修复步骤 +summary: Doctor 命令:运行状况检查、配置迁移和修复步骤 title: Doctor x-i18n: - generated_at: "2026-04-26T07:49:08Z" + generated_at: "2026-04-26T08:13:19Z" model: gpt-5.4 provider: openai - source_hash: 53248eb2777a16197480654302d6802b8b6d4f4b810b443d0aea44e5d40b1cd5 + source_hash: 592a9f886e0e6dcbfeb41a09c765ab289f3ed16ed360be37ff9fbefba920754f source_path: gateway/doctor.md workflow: 15 --- -`openclaw doctor` 是 OpenClaw 的修复 + 迁移工具。它会修复过时的配置/状态,检查健康状况,并提供可执行的修复步骤。 +`openclaw doctor` 是 OpenClaw 的修复 + 迁移工具。它会修复过时的配置/状态、检查运行状况,并提供可执行的修复步骤。 ## 快速开始 @@ -22,7 +22,7 @@ x-i18n: openclaw doctor ``` -### 无头和自动化模式 +### 无头模式和自动化模式 @@ -30,7 +30,7 @@ openclaw doctor openclaw doctor --yes ``` - 接受默认值而不提示(包括在适用时的重启/服务/沙箱修复步骤)。 + 接受默认值而不提示(包括适用时的重启/服务/沙箱修复步骤)。 @@ -38,7 +38,7 @@ openclaw doctor openclaw doctor --repair ``` - 无需提示即可应用推荐修复(在安全情况下执行修复 + 重启)。 + 不经提示直接应用推荐的修复(在安全时执行修复 + 重启)。 @@ -46,7 +46,7 @@ openclaw doctor openclaw doctor --repair --force ``` - 还会应用激进修复(覆盖自定义 supervisor 配置)。 + 同时应用激进修复(会覆盖自定义 supervisor 配置)。 @@ -54,7 +54,7 @@ openclaw doctor openclaw doctor --non-interactive ``` - 在无提示的情况下运行,并且只应用安全迁移(配置规范化 + 磁盘状态移动)。会跳过需要人工确认的重启/服务/沙箱操作。检测到旧版状态迁移时会自动运行。 + 在无提示的情况下运行,并且只应用安全迁移(配置规范化 + 磁盘状态迁移)。跳过需要人工确认的重启/服务/沙箱操作。检测到旧版状态时,会自动运行旧状态迁移。 @@ -62,7 +62,7 @@ openclaw doctor openclaw doctor --deep ``` - 扫描系统服务以查找额外的 Gateway 网关 安装(`launchd`/`systemd`/`schtasks`)。 + 扫描系统服务以查找额外的 Gateway 网关安装(launchd/systemd/schtasks)。 @@ -73,108 +73,108 @@ openclaw doctor cat ~/.openclaw/openclaw.json ``` -## 它会做什么(摘要) +## 它的作用(摘要) - - - 可选的 Git 安装预检更新(仅限交互模式)。 - - UI 协议新鲜度检查(当协议 schema 较新时重建 Control UI)。 - - 健康检查 + 重启提示。 - - Skills 状态摘要(可用/缺失/阻止)和插件状态。 + + - 对于 git 安装,可选的预检更新(仅交互模式)。 + - UI 协议新鲜度检查(当协议 schema 更新时重建 Control UI)。 + - 运行状况检查 + 重启提示。 + - Skills 状态摘要(可用/缺失/受阻)和插件状态。 - - 旧版值的配置规范化。 - - 将旧版扁平 `talk.*` 字段迁移到 `talk.provider` + `talk.providers.` 的 Talk 配置迁移。 - - 针对旧版 Chrome 扩展配置和 Chrome MCP 就绪情况的浏览器迁移检查。 + - 对旧版值执行配置规范化。 + - 将旧版扁平 `talk.*` 字段迁移为 `talk.provider` + `talk.providers.` 的 Talk 配置迁移。 + - 针对旧版 Chrome 扩展配置和 Chrome MCP 就绪状态的浏览器迁移检查。 - OpenCode 提供商覆盖警告(`models.providers.opencode` / `models.providers.opencode-go`)。 - Codex OAuth 遮蔽警告(`models.providers.openai-codex`)。 - - OpenAI Codex OAuth profile 的 OAuth TLS 前置条件检查。 + - 针对 OpenAI Codex OAuth 配置文件的 OAuth TLS 前置条件检查。 - 旧版磁盘状态迁移(会话/智能体目录/WhatsApp 认证)。 - - 旧版插件 manifest 合约键迁移(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders` → `contracts`)。 - - 旧版 cron 存储迁移(`jobId`、`schedule.cron`、顶层 delivery/payload 字段、payload `provider`、简单的 `notify: true` webhook 回退任务)。 - - 将旧版智能体运行时策略迁移到 `agents.defaults.agentRuntime` 和 `agents.list[].agentRuntime`。 + - 旧版插件清单 contract 键迁移(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders` → `contracts`)。 + - 旧版 cron 存储迁移(`jobId`、`schedule.cron`、顶层 delivery/payload 字段、payload `provider`、简单的 `notify: true` webhook 回退作业)。 + - 将旧版智能体 runtime-policy 迁移为 `agents.defaults.agentRuntime` 和 `agents.list[].agentRuntime`。 - - 会话锁文件检查和过时锁清理。 - - 修复受影响的 2026.4.24 构建所创建的重复 prompt-rewrite 分支造成的会话转录。 + - 会话锁文件检查与陈旧锁清理。 + - 修复受影响的 2026.4.24 构建创建的重复 prompt-rewrite 分支所导致的会话转录问题。 - 状态完整性和权限检查(会话、转录、状态目录)。 - 本地运行时的配置文件权限检查(`chmod 600`)。 - - 模型认证健康检查:检查 OAuth 过期情况,可刷新即将过期的 token,并报告 auth-profile 冷却/禁用状态。 + - 模型认证健康检查:检查 OAuth 过期情况、可以刷新即将过期的令牌,并报告 auth-profile 冷却/禁用状态。 - 额外工作区目录检测(`~/openclaw`)。 - + - 启用沙箱隔离时的沙箱镜像修复。 - - 旧版服务迁移和额外 Gateway 网关 检测。 - - Matrix 渠道旧版状态迁移(在 `--fix` / `--repair` 模式下)。 - - Gateway 网关 运行时检查(服务已安装但未运行;缓存的 `launchd` 标签)。 - - 渠道状态警告(从正在运行的 Gateway 网关 探测)。 - - supervisor 配置审计(`launchd`/`systemd`/`schtasks`),可选修复。 - - Gateway 网关 运行时最佳实践检查(Node 与 Bun、版本管理器路径)。 - - Gateway 网关 端口冲突诊断(默认 `18789`)。 + - 旧版服务迁移和额外 Gateway 网关检测。 + - Matrix 渠道旧状态迁移(在 `--fix` / `--repair` 模式下)。 + - Gateway 网关运行时检查(已安装服务但未运行;缓存的 launchd 标签)。 + - 渠道状态警告(从正在运行的 Gateway 网关探测)。 + - Supervisor 配置审计(launchd/systemd/schtasks)及可选修复。 + - Gateway 网关运行时最佳实践检查(Node 与 Bun、版本管理器路径)。 + - Gateway 网关端口冲突诊断(默认 `18789`)。 - + - 针对开放私信策略的安全警告。 - - 本地 token 模式下的 Gateway 网关 认证检查(当不存在 token 源时提供 token 生成功能;不会覆盖 token SecretRef 配置)。 - - 设备配对故障检测(待处理的首次配对请求、待处理的角色/作用域升级、过时的本地设备 token 缓存漂移,以及已配对记录认证漂移)。 + - 针对本地令牌模式的 Gateway 网关认证检查(当不存在令牌来源时提供令牌生成功能;不会覆盖 token SecretRef 配置)。 + - 设备配对问题检测(首次配对请求待处理、角色/作用域升级待处理、陈旧的本地设备令牌缓存漂移,以及已配对记录的认证漂移)。 - - Linux 上的 `systemd linger` 检查。 + - Linux 上的 systemd linger 检查。 - 工作区 bootstrap 文件大小检查(针对上下文文件的截断/接近上限警告)。 - - shell 补全状态检查和自动安装/升级。 - - Memory 搜索嵌入提供商就绪检查(本地模型、远程 API 密钥或 QMD 二进制文件)。 - - 源码安装检查(`pnpm` 工作区不匹配、缺失的 UI 资源、缺失的 `tsx` 二进制文件)。 + - Shell 补全状态检查以及自动安装/升级。 + - Memory 搜索 embedding 提供商就绪检查(本地模型、远程 API key 或 QMD 二进制文件)。 + - 源码安装检查(`pnpm` 工作区不匹配、缺失 UI 资源、缺失 `tsx` 二进制文件)。 - 写入更新后的配置 + 向导元数据。 ## Dreams UI 回填和重置 -Control UI Dreams 场景包含用于 grounded dreaming 工作流的 **Backfill**、**Reset** 和 **Clear Grounded** 操作。这些操作使用 Gateway 网关 doctor 风格的 RPC 方法,但它们**不是** `openclaw doctor` CLI 修复/迁移的一部分。 +Control UI 的 Dreams 场景为 grounded dreaming 工作流包含 **Backfill**、**Reset** 和 **Clear Grounded** 操作。这些操作使用 Gateway 网关的 doctor 风格 RPC 方法,但它们**不是** `openclaw doctor` CLI 修复/迁移的一部分。 它们的作用: -- **Backfill** 会扫描活动工作区中的历史 `memory/YYYY-MM-DD.md` 文件,运行 grounded REM 日记处理,并将可逆的回填条目写入 `DREAMS.md`。 -- **Reset** 仅从 `DREAMS.md` 中移除这些已标记的回填日记条目。 -- **Clear Grounded** 仅移除来自历史回放、且尚未积累实时 recall 或每日支持的 staged grounded-only 短期条目。 +- **Backfill** 会扫描当前工作区中历史的 `memory/YYYY-MM-DD.md` 文件,运行 grounded REM 日记流程,并将可逆的回填条目写入 `DREAMS.md`。 +- **Reset** 仅从 `DREAMS.md` 中移除那些带标记的回填日记条目。 +- **Clear Grounded** 仅移除来自历史重放、且尚未积累实时 recall 或每日支持的 staged grounded-only 短期条目。 -它们本身**不会**做的事: +它们**本身不会**执行的操作: - 不会编辑 `MEMORY.md` - 不会运行完整的 doctor 迁移 -- 除非你先显式运行 staged CLI 路径,否则不会自动将 grounded 候选项 staged 到实时短期提升存储中 +- 不会自动将 grounded 候选项放入实时短期提升存储,除非你先显式运行 staged CLI 路径 -如果你希望 grounded 历史回放影响正常的深度提升通道,请改用 CLI 流程: +如果你希望 grounded 历史重放影响正常的深度提升流程,请改用以下 CLI 流程: ```bash openclaw memory rem-backfill --path ./memory --stage-short-term ``` -这样会将 grounded durable 候选项 staged 到短期 dreaming 存储中,同时保留 `DREAMS.md` 作为审查界面。 +这会将 grounded 的持久候选项放入短期 dreaming 存储,同时保留 `DREAMS.md` 作为审核界面。 -## 详细行为和理由 +## 详细行为和原理说明 - - 如果这是一个 Git 检出,并且 doctor 正在交互式运行,它会在运行 doctor 之前提供更新(fetch/rebase/build)。 + + 如果这是一个 git checkout,并且 doctor 以交互方式运行,它会先提供更新选项(fetch/rebase/build),然后再运行 doctor。 - 如果配置包含旧版值形状(例如没有渠道特定覆盖的 `messages.ackReaction`),doctor 会将其规范化为当前 schema。 + 如果配置包含旧版值结构(例如没有渠道专属覆盖的 `messages.ackReaction`),doctor 会将其规范化为当前 schema。 - 这包括旧版 Talk 扁平字段。当前公开的 Talk 配置是 `talk.provider` + `talk.providers.`。Doctor 会将旧的 `talk.voiceId` / `talk.voiceAliases` / `talk.modelId` / `talk.outputFormat` / `talk.apiKey` 形状重写到提供商映射中。 + 这也包括旧版 Talk 扁平字段。当前公开的 Talk 配置是 `talk.provider` + `talk.providers.`。Doctor 会将旧的 `talk.voiceId` / `talk.voiceAliases` / `talk.modelId` / `talk.outputFormat` / `talk.apiKey` 结构重写到提供商映射中。 - 当配置包含已弃用键时,其他命令会拒绝运行,并要求你运行 `openclaw doctor`。 + 当配置中包含已弃用键时,其他命令会拒绝运行,并要求你运行 `openclaw doctor`。 Doctor 将会: - - 解释找到了哪些旧版键。 - - 显示它应用的迁移。 + - 说明找到了哪些旧版键。 + - 展示它应用的迁移。 - 使用更新后的 schema 重写 `~/.openclaw/openclaw.json`。 - 当 Gateway 网关 在启动时检测到旧版配置格式,也会自动运行 doctor 迁移,因此过时配置无需人工干预即可修复。Cron 任务存储迁移由 `openclaw doctor --fix` 处理。 + Gateway 网关在启动时检测到旧版配置格式,也会自动运行 doctor 迁移,因此过时配置无需人工干预即可修复。Cron 作业存储迁移由 `openclaw doctor --fix` 处理。 - 当前迁移: + 当前迁移包括: - `routing.allowFrom` → `channels.whatsapp.allowFrom` - `routing.groupChat.requireMention` → `channels.whatsapp/telegram/imessage.groups."*".requireMention` @@ -197,85 +197,85 @@ openclaw memory rem-backfill --path ./memory --stage-short-term - `plugins.entries.voice-call.config.streaming.sttProvider` → `plugins.entries.voice-call.config.streaming.provider` - `plugins.entries.voice-call.config.streaming.openaiApiKey|sttModel|silenceDurationMs|vadThreshold` → `plugins.entries.voice-call.config.streaming.providers.openai.*` - `bindings[].match.accountID` → `bindings[].match.accountId` - - 对于已命名 `accounts` 但仍保留单账号顶层渠道值的渠道,将这些账号作用域值移入该渠道选定的提升账号中(大多数渠道使用 `accounts.default`;Matrix 可以保留现有匹配的已命名/默认目标) + - 对于具有命名 `accounts`,但仍残留单账户顶层渠道值的渠道,将这些账户作用域值移动到为该渠道选定的提升账户中(大多数渠道使用 `accounts.default`;Matrix 可以保留现有匹配的命名/默认目标) - `identity` → `agents.list[].identity` - `agent.*` → `agents.defaults` + `tools.*`(tools/elevated/exec/sandbox/subagents) - `agent.model`/`allowedModels`/`modelAliases`/`modelFallbacks`/`imageModelFallbacks` → `agents.defaults.models` + `agents.defaults.model.primary/fallbacks` + `agents.defaults.imageModel.primary/fallbacks` - `browser.ssrfPolicy.allowPrivateNetwork` → `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` - `browser.profiles.*.driver: "extension"` → `"existing-session"` - - 删除 `browser.relayBindHost`(旧版扩展 relay 设置) + - 移除 `browser.relayBindHost`(旧版扩展 relay 设置) - Doctor 警告还包括多账号渠道的默认账号指导: + Doctor 警告还包括针对多账户渠道的默认账户指引: - - 如果已配置两个或更多 `channels..accounts` 条目,但未设置 `channels..defaultAccount` 或 `accounts.default`,doctor 会警告回退路由可能选择意外账号。 - - 如果 `channels..defaultAccount` 被设置为未知账号 ID,doctor 会发出警告并列出已配置的账号 ID。 + - 如果配置了两个或更多 `channels..accounts` 条目,但没有设置 `channels..defaultAccount` 或 `accounts.default`,doctor 会警告回退路由可能选中意外的账户。 + - 如果 `channels..defaultAccount` 设置为未知账户 ID,doctor 会发出警告并列出已配置的账户 ID。 - 如果你手动添加了 `models.providers.opencode`、`opencode-zen` 或 `opencode-go`,它会覆盖来自 `@mariozechner/pi-ai` 的内置 OpenCode 目录。这可能会迫使模型走错 API,或将成本清零。Doctor 会发出警告,以便你移除该覆盖并恢复按模型的 API 路由 + 成本。 + 如果你手动添加了 `models.providers.opencode`、`opencode-zen` 或 `opencode-go`,它会覆盖来自 `@mariozechner/pi-ai` 的内置 OpenCode 目录。这可能会把模型强制路由到错误的 API,或者将费用归零。Doctor 会发出警告,以便你移除该覆盖并恢复按模型路由 API + 费用。 - - 如果你的浏览器配置仍指向已移除的 Chrome 扩展路径,doctor 会将其规范化为当前的主机本地 Chrome MCP 附加模型: + + 如果你的浏览器配置仍指向已移除的 Chrome 扩展路径,doctor 会将其规范化为当前的 host-local Chrome MCP 附加模型: - `browser.profiles.*.driver: "extension"` 会变为 `"existing-session"` - - `browser.relayBindHost` 会被删除 + - `browser.relayBindHost` 会被移除 - Doctor 还会在你使用 `defaultProfile: "user"` 或已配置的 `existing-session` profile 时,审计主机本地 Chrome MCP 路径: + Doctor 还会在你使用 `defaultProfile: "user"` 或已配置的 `existing-session` 配置文件时,审计 host-local Chrome MCP 路径: - - 检查 Google Chrome 是否安装在同一主机上,以供默认自动连接 profile 使用 - - 检查检测到的 Chrome 版本,并在其低于 Chrome 144 时发出警告 + - 检查同一主机上是否安装了 Google Chrome,以支持默认自动连接配置文件 + - 检查检测到的 Chrome 版本,并在版本低于 Chrome 144 时发出警告 - 提醒你在浏览器 inspect 页面中启用远程调试(例如 `chrome://inspect/#remote-debugging`、`brave://inspect/#remote-debugging` 或 `edge://inspect/#remote-debugging`) - Doctor 不能替你启用 Chrome 侧设置。主机本地 Chrome MCP 仍然需要: + Doctor 无法替你启用 Chrome 端设置。Host-local Chrome MCP 仍然需要: - Gateway 网关/节点主机上安装 Chromium 内核浏览器 144+ - 浏览器在本地运行 - 在该浏览器中启用远程调试 - - 在浏览器中批准首次附加同意提示 + - 在浏览器中批准首次 attach 同意提示 - 这里的就绪情况仅指本地附加前置条件。Existing-session 会保留当前 Chrome MCP 路由限制;像 `responsebody`、PDF 导出、下载拦截和批量操作这样的高级路由仍然需要受管浏览器或原始 CDP profile。 + 此处的就绪状态仅指本地 attach 前置条件。`existing-session` 会保留当前 Chrome MCP 路由限制;像 `responsebody`、PDF 导出、下载拦截和批量操作这类高级路由,仍然需要受管浏览器或原始 CDP 配置文件。 - 此检查**不**适用于 Docker、沙箱、remote-browser 或其他无头流程。那些流程将继续使用原始 CDP。 + 此检查**不**适用于 Docker、沙箱、remote-browser 或其他无头流程。这些流程会继续使用原始 CDP。 - 配置了 OpenAI Codex OAuth profile 时,doctor 会探测 OpenAI 授权端点,以验证本地 Node/OpenSSL TLS 栈是否可以校验证书链。如果探测因证书错误而失败(例如 `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`、证书过期或自签名证书),doctor 会打印特定于平台的修复指导。在 macOS 上使用 Homebrew Node 时,修复通常是 `brew postinstall ca-certificates`。使用 `--deep` 时,即使 Gateway 网关 健康,该探测也会运行。 + 配置了 OpenAI Codex OAuth 配置文件时,doctor 会探测 OpenAI 授权端点,以验证本地 Node/OpenSSL TLS 栈是否能够校验证书链。如果探测因证书错误失败(例如 `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`、证书过期或自签名证书),doctor 会输出按平台划分的修复指引。在 macOS 上使用 Homebrew 安装的 Node 时,修复方式通常是 `brew postinstall ca-certificates`。使用 `--deep` 时,即使 Gateway 网关状态正常,也会运行该探测。 - 如果你之前在 `models.providers.openai-codex` 下添加了旧版 OpenAI 传输设置,它们可能会遮蔽较新版本自动使用的内置 Codex OAuth provider 路径。当 doctor 在 Codex OAuth 旁边看到这些旧传输设置时,会发出警告,以便你删除或重写过时的传输覆盖,并恢复内置路由/回退行为。自定义代理和仅 header 的覆盖仍然受支持,不会触发此警告。 + 如果你之前在 `models.providers.openai-codex` 下添加了旧版 OpenAI 传输设置,它们可能会遮蔽新版本自动使用的内置 Codex OAuth provider 路径。当 doctor 在 Codex OAuth 旁边看到这些旧传输设置时,会发出警告,以便你移除或重写过时的传输覆盖,从而恢复内置路由/回退行为。自定义代理和仅 header 的覆盖仍然受支持,不会触发此警告。 - 启用内置 Codex 插件时,doctor 还会检查 `openai-codex/*` 主模型引用是否仍通过默认 PI runner 解析。当你想通过 PI 使用 Codex OAuth/订阅认证时,这种组合是有效的,但它很容易与原生 Codex app-server harness 混淆。Doctor 会发出警告,并指向显式的 app-server 形状:`openai/*` 加 `agentRuntime.id: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex`。 + 启用内置 Codex 插件时,doctor 还会检查 `openai-codex/*` 主模型引用是否仍通过默认 PI 运行器解析。当你希望通过 PI 使用 Codex OAuth/订阅认证时,这种组合是有效的,但它很容易与原生 Codex app-server harness 混淆。Doctor 会发出警告,并指向明确的 app-server 形式:`openai/*` 加上 `agentRuntime.id: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex`。 - Doctor 不会自动修复这一点,因为这两种路由都有效: + Doctor 不会自动修复这一点,因为这两种路径都有效: - - `openai-codex/*` + PI 表示“通过常规 OpenClaw runner 使用 Codex OAuth/订阅认证。” + - `openai-codex/*` + PI 表示“通过常规 OpenClaw 运行器使用 Codex OAuth/订阅认证。” - `openai/*` + `runtime: "codex"` 表示“通过原生 Codex app-server 运行嵌入式轮次。” - - `/codex ...` 表示“从聊天中控制或绑定一个原生 Codex 会话。” + - `/codex ...` 表示“从聊天中控制或绑定原生 Codex 对话。” - `/acp ...` 或 `runtime: "acp"` 表示“使用外部 ACP/acpx 适配器。” - 如果出现该警告,请选择你原本打算使用的路由,并手动编辑配置。如果 PI Codex OAuth 是有意为之,请保持该警告原样。 + 如果出现此警告,请选择你实际想要的路径并手动编辑配置。如果 PI Codex OAuth 是有意为之,请保留该警告不变。 Doctor 可以将较旧的磁盘布局迁移到当前结构: - 会话存储 + 转录: - - 从 `~/.openclaw/sessions/` 到 `~/.openclaw/agents//sessions/` + - 从 `~/.openclaw/sessions/` 迁移到 `~/.openclaw/agents//sessions/` - 智能体目录: - - 从 `~/.openclaw/agent/` 到 `~/.openclaw/agents//agent/` + - 从 `~/.openclaw/agent/` 迁移到 `~/.openclaw/agents//agent/` - WhatsApp 认证状态(Baileys): - - 从旧版 `~/.openclaw/credentials/*.json`(不包括 `oauth.json`) - - 到 `~/.openclaw/credentials/whatsapp//...`(默认账号 ID:`default`) + - 从旧版 `~/.openclaw/credentials/*.json`(`oauth.json` 除外) + - 迁移到 `~/.openclaw/credentials/whatsapp//...`(默认账户 ID:`default`) - 这些迁移以尽力而为且幂等的方式执行;当 doctor 将任何旧版文件夹保留为备份时,会发出警告。Gateway 网关/CLI 也会在启动时自动迁移旧版会话 + 智能体目录,因此历史记录/认证/模型会落到每个智能体的路径下,而无需手动运行 doctor。WhatsApp 认证有意只通过 `openclaw doctor` 迁移。Talk provider/provider-map 规范化现在按结构相等性比较,因此仅键顺序不同的差异不再触发重复的无操作 `doctor --fix` 更改。 + 这些迁移尽力而为且幂等;如果遗留了任何旧版文件夹作为备份,doctor 会发出警告。Gateway 网关/CLI 在启动时也会自动迁移旧版会话 + 智能体目录,因此历史记录/认证/模型会落到每个智能体各自的路径中,而无需手动运行 doctor。WhatsApp 认证有意只通过 `openclaw doctor` 迁移。Talk provider/provider-map 规范化现在按结构相等性进行比较,因此仅键顺序不同的差异不再触发重复的无操作 `doctor --fix` 更改。 - - Doctor 会扫描所有已安装插件的 manifest,查找已弃用的顶层能力键(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders`)。找到后,它会提议将它们移动到 `contracts` 对象中,并原地重写 manifest 文件。该迁移是幂等的;如果 `contracts` 键中已包含相同值,则会删除旧版键,而不会重复数据。 + + Doctor 会扫描所有已安装插件清单中已弃用的顶层能力键(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders`)。发现后,它会提供将这些键移动到 `contracts` 对象并原地重写清单文件的选项。此迁移是幂等的;如果 `contracts` 键中已经有相同值,则会移除旧版键,而不会重复数据。 - Doctor 还会检查 cron 任务存储(默认是 `~/.openclaw/cron/jobs.json`,或覆盖时使用 `cron.store`),查找调度器仍为兼容性而接受的旧任务形状。 + Doctor 还会检查 cron 作业存储(默认是 `~/.openclaw/cron/jobs.json`,或覆盖后的 `cron.store`)中调度器仍为兼容性接受的旧版作业结构。 当前 cron 清理包括: @@ -284,185 +284,186 @@ openclaw memory rem-backfill --path ./memory --stage-short-term - 顶层 payload 字段(`message`、`model`、`thinking`、...)→ `payload` - 顶层 delivery 字段(`deliver`、`channel`、`to`、`provider`、...)→ `delivery` - payload `provider` delivery 别名 → 显式 `delivery.channel` - - 简单的旧版 `notify: true` webhook 回退任务 → 显式 `delivery.mode="webhook"` 且 `delivery.to=cron.webhook` + - 简单旧版 `notify: true` webhook 回退作业 → 显式 `delivery.mode="webhook"` 且 `delivery.to=cron.webhook` - Doctor 仅在能够不改变行为的情况下自动迁移 `notify: true` 任务。如果某个任务将旧版 notify 回退与现有的非 webhook delivery 模式组合在一起,doctor 会发出警告,并将该任务留待手动审查。 + Doctor 仅在确保不会改变行为时,才会自动迁移 `notify: true` 作业。如果某个作业将旧版 notify 回退与现有非 webhook delivery 模式组合使用,doctor 会发出警告,并将该作业留给人工审查。 - Doctor 会扫描每个智能体会话目录中的过时写锁文件 —— 这些文件是在会话异常退出时遗留下来的。对于找到的每个锁文件,它会报告:路径、PID、该 PID 是否仍然存活、锁年龄,以及它是否被视为过时(PID 已死亡或超过 30 分钟)。在 `--fix` / `--repair` 模式下,它会自动移除过时锁文件;否则会打印说明,并提示你使用 `--fix` 重新运行。 + Doctor 会扫描每个智能体会话目录中的陈旧写锁文件——即会话异常退出后遗留的文件。对于找到的每个锁文件,它会报告:路径、PID、PID 是否仍在运行、锁年龄,以及它是否被视为陈旧(PID 已死亡或超过 30 分钟)。在 `--fix` / `--repair` 模式下,它会自动移除陈旧锁文件;否则它会输出说明,并指示你使用 `--fix` 重新运行。 - Doctor 会扫描智能体会话 JSONL 文件,查找由 2026.4.24 prompt transcript 重写 bug 创建的重复分支形状:一个已放弃的用户轮次,包含 OpenClaw 内部运行时上下文,以及一个活动同级分支,包含相同的可见用户提示。在 `--fix` / `--repair` 模式下,doctor 会在原文件旁为每个受影响文件创建备份,并将转录重写为活动分支,从而让 Gateway 网关 历史和 Memory 读取器不再看到重复轮次。 + Doctor 会扫描智能体会话 JSONL 文件,查找由 2026.4.24 prompt transcript 重写 bug 创建的重复分支结构:一个包含 OpenClaw 内部运行时上下文的已放弃用户轮次,以及一个包含相同可见用户提示的活动同级分支。在 `--fix` / `--repair` 模式下,doctor 会在原文件旁边备份每个受影响文件,并将转录重写为活动分支,从而使 Gateway 网关历史和 Memory 读取器不再看到重复轮次。 - - 状态目录是运行层面的脑干。它一旦消失,你就会丢失会话、凭证、日志和配置(除非你在别处有备份)。 + + 状态目录是运行层面的中枢。如果它消失了,你会丢失会话、凭证、日志和配置(除非你在别处有备份)。 Doctor 会检查: - - **状态目录缺失**:警告灾难性的状态丢失,提示重新创建目录,并提醒你它无法恢复缺失的数据。 - - **状态目录权限**:验证可写性;如果检测到所有者/组不匹配,则提供修复权限的选项(并给出 `chown` 提示)。 - - **macOS 云同步状态目录**:当状态解析到 iCloud Drive(`~/Library/Mobile Documents/com~apple~CloudDocs/...`)或 `~/Library/CloudStorage/...` 下时发出警告,因为基于同步的路径可能导致更慢的 I/O 以及锁/同步竞争。 - - **Linux SD 或 eMMC 状态目录**:当状态解析到 `mmcblk*` 挂载源时发出警告,因为基于 SD 或 eMMC 的随机 I/O 在会话和凭证写入下可能更慢且磨损更快。 - - **会话目录缺失**:`sessions/` 和会话存储目录是持久化历史并避免 `ENOENT` 崩溃所必需的。 - - **转录不匹配**:当最近的会话条目缺失转录文件时发出警告。 - - **主会话“1 行 JSONL”**:当主转录只有一行时标记(历史未在累积)。 + - **状态目录缺失**:警告灾难性状态丢失,提示重新创建目录,并提醒你它无法恢复缺失数据。 + - **状态目录权限**:验证可写性;提供修复权限的选项(并在检测到所有者/组不匹配时给出 `chown` 提示)。 + - **macOS 云同步状态目录**:当状态路径解析到 iCloud Drive(`~/Library/Mobile Documents/com~apple~CloudDocs/...`)或 `~/Library/CloudStorage/...` 下时发出警告,因为由同步支持的路径可能导致更慢的 I/O 以及锁/同步竞争。 + - **Linux SD 或 eMMC 状态目录**:当状态路径解析到 `mmcblk*` 挂载源时发出警告,因为在会话和凭证写入场景下,由 SD 或 eMMC 支持的随机 I/O 可能更慢且磨损更快。 + - **会话目录缺失**:`sessions/` 和会话存储目录是持久化历史记录并避免 `ENOENT` 崩溃所必需的。 + - **转录不匹配**:当最近的会话条目缺少转录文件时发出警告。 + - **主会话 “1 行 JSONL”**:当主转录只有一行时发出标记(历史没有持续累积)。 - **多个状态目录**:当不同主目录中存在多个 `~/.openclaw` 文件夹,或 `OPENCLAW_STATE_DIR` 指向其他位置时发出警告(历史可能在不同安装之间分裂)。 - - **远程模式提醒**:如果 `gateway.mode=remote`,doctor 会提醒你在远程主机上运行它(状态就存储在那里)。 - - **配置文件权限**:如果 `~/.openclaw/openclaw.json` 对组/所有人可读,则发出警告,并提供收紧为 `600` 的选项。 + - **远程模式提醒**:如果 `gateway.mode=remote`,doctor 会提醒你在远程主机上运行它(状态存储在那里)。 + - **配置文件权限**:如果 `~/.openclaw/openclaw.json` 对组/全体用户可读,则发出警告,并提供收紧到 `600` 的选项。 - - Doctor 会检查认证存储中的 OAuth profile,在 token 即将过期/已过期时发出警告,并可在安全情况下刷新它们。如果 Anthropic OAuth/token profile 已过时,它会建议使用 Anthropic API 密钥或 Anthropic setup-token 路径。刷新提示仅在交互式(TTY)运行时显示;`--non-interactive` 会跳过刷新尝试。 + + Doctor 会检查认证存储中的 OAuth 配置文件,在令牌即将过期/已过期时发出警告,并可在安全时刷新它们。如果 Anthropic OAuth/令牌配置文件已过时,它会建议使用 Anthropic API key 或 Anthropic setup-token 路径。只有在交互运行(TTY)时才会出现刷新提示;`--non-interactive` 会跳过刷新尝试。 - 当 OAuth 刷新永久失败时(例如 `refresh_token_reused`、`invalid_grant`,或提供商要求你重新登录),doctor 会报告需要重新认证,并打印要运行的精确 `openclaw models auth login --provider ...` 命令。 + 当 OAuth 刷新永久失败时(例如 `refresh_token_reused`、`invalid_grant`,或提供商告诉你需要重新登录),doctor 会报告需要重新认证,并输出确切的 `openclaw models auth login --provider ...` 命令供你运行。 - Doctor 还会报告因以下原因而暂时不可用的 auth-profile: + Doctor 还会报告由于以下原因而暂时不可用的 auth 配置文件: - - 短期冷却(速率限制/超时/认证失败) - - 较长期禁用(计费/额度失败) + - 短暂冷却期(速率限制/超时/认证失败) + - 较长时间禁用(计费/余额失败) - - 如果设置了 `hooks.gmail.model`,doctor 会根据目录和 allowlist 验证模型引用,并在其无法解析或不被允许时发出警告。 + + 如果设置了 `hooks.gmail.model`,doctor 会根据目录和 allowlist 校验该模型引用,并在其无法解析或不被允许时发出警告。 启用沙箱隔离时,doctor 会检查 Docker 镜像,并在当前镜像缺失时提供构建或切换到旧版名称的选项。 - Doctor 仅验证当前配置中处于激活状态,或由其内置 manifest 默认启用的内置插件的运行时依赖,例如 `plugins.entries.discord.enabled: true`、旧版 `channels.discord.enabled: true`,或默认启用的内置 provider。如果缺少任何依赖,doctor 会报告相应包,并在 `openclaw doctor --fix` / `openclaw doctor --repair` 模式下安装它们。外部插件仍然使用 `openclaw plugins install` / `openclaw plugins update`;doctor 不会为任意插件路径安装依赖。 + Doctor 仅验证当前配置中处于活动状态,或因其内置清单默认值而启用的内置插件的运行时依赖,例如 `plugins.entries.discord.enabled: true`、旧版 `channels.discord.enabled: true`,或默认启用的内置 provider。如果缺失任何依赖,doctor 会报告这些包,并在 `openclaw doctor --fix` / `openclaw doctor --repair` 模式下安装它们。外部插件仍使用 `openclaw plugins install` / `openclaw plugins update`;doctor 不会为任意插件路径安装依赖。 - Gateway 网关 和本地 CLI 也可以在导入内置插件之前,按需修复处于激活状态的内置插件运行时依赖。这些安装被限定在插件运行时安装根目录中,安装时禁用脚本,不写入 package lock,并通过安装根锁进行保护,以免并发的 CLI 或 Gateway 网关 启动同时修改同一棵 `node_modules` 树。 + Gateway 网关和本地 CLI 也可以在导入活动内置插件之前,按需修复其运行时依赖。这些安装会限定在插件运行时安装根目录中、在禁用脚本的情况下运行、不会写入 package lock,并且受安装根锁保护,因此并发的 CLI 或 Gateway 网关启动不会同时修改同一个 `node_modules` 树。 - - Doctor 会检测旧版 Gateway 网关 服务(`launchd`/`systemd`/`schtasks`),并提供移除它们以及使用当前 Gateway 网关 端口安装 OpenClaw 服务的选项。它还可以扫描额外的类似 Gateway 网关 的服务并打印清理提示。带 profile 名称的 OpenClaw Gateway 网关 服务被视为一等公民,不会被标记为“额外”。 + + Doctor 会检测旧版 Gateway 网关服务(launchd/systemd/schtasks),并提供移除它们以及使用当前 Gateway 网关端口安装 OpenClaw 服务的选项。它还可以扫描额外的类 Gateway 网关服务并输出清理提示。带 profile 名称的 OpenClaw Gateway 网关服务被视为一等公民,不会被标记为“额外”。 - 当 Matrix 渠道账号存在待处理或可执行的旧版状态迁移时,doctor(在 `--fix` / `--repair` 模式下)会先创建迁移前快照,然后运行尽力而为的迁移步骤:旧版 Matrix 状态迁移和旧版加密状态准备。这两个步骤都不是致命的;错误会被记录,启动会继续进行。在只读模式下(不带 `--fix` 的 `openclaw doctor`),该检查会被完全跳过。 + 当 Matrix 渠道账户存在待处理或可执行的旧版状态迁移时,doctor(在 `--fix` / `--repair` 模式下)会先创建迁移前快照,然后运行尽力而为的迁移步骤:旧版 Matrix 状态迁移和旧版加密状态准备。这两个步骤都不是致命错误;错误会被记录,启动会继续进行。在只读模式下(不带 `--fix` 的 `openclaw doctor`),此检查会被完全跳过。 - Doctor 现在会将设备配对状态作为正常健康检查的一部分进行检查。 + Doctor 现在会将设备配对状态纳入常规健康检查的一部分。 它会报告的内容: - 待处理的首次配对请求 - - 已配对设备的待处理角色升级 - - 已配对设备的待处理作用域升级 - - 公钥不匹配修复:设备 ID 仍然匹配,但设备身份已不再匹配已批准记录 - - 缺少已批准角色的活动 token 的已配对记录 - - 作用域漂移到已批准配对基线之外的已配对 token - - 当前机器的本地缓存设备 token 条目,这些条目早于 Gateway 网关 侧 token 轮换,或携带过时的作用域元数据 + - 已配对设备待处理的角色升级 + - 已配对设备待处理的作用域升级 + - 公钥不匹配修复:设备 ID 仍然匹配,但设备身份已不再与已批准记录一致 + - 已配对记录缺少与已批准角色对应的活动令牌 + - 已配对令牌的作用域漂移到已批准配对基线之外 + - 当前机器上的本地缓存设备令牌条目早于 Gateway 网关侧令牌轮换,或携带过时的作用域元数据 - Doctor 不会自动批准配对请求,也不会自动轮换设备 token。它会改为打印精确的下一步操作: + Doctor 不会自动批准配对请求,也不会自动轮换设备令牌。它会直接输出下一步操作: - 使用 `openclaw devices list` 检查待处理请求 - - 使用 `openclaw devices approve ` 批准精确请求 - - 使用 `openclaw devices rotate --device --role ` 轮换新的 token - - 使用 `openclaw devices remove ` 删除并重新批准过时记录 + - 使用 `openclaw devices approve ` 批准指定请求 + - 使用 `openclaw devices rotate --device --role ` 轮换新的令牌 + - 使用 `openclaw devices remove ` 移除并重新批准过时记录 - 这补上了常见的“已经配对但仍然提示需要配对”的漏洞:doctor 现在可以区分首次配对、待处理角色/作用域升级,以及过时 token/设备身份漂移。 + 这解决了常见的“已经配对但仍然提示需要配对”的问题:doctor 现在可以区分首次配对、待处理的角色/作用域升级,以及过时的令牌/设备身份漂移。 - 当某个提供商在没有 allowlist 的情况下对私信开放,或策略配置方式具有危险性时,doctor 会发出警告。 + 当某个提供商对私信开放但没有 allowlist,或者某项策略配置方式存在风险时,doctor 会发出警告。 - - 如果作为 `systemd` 用户服务运行,doctor 会确保已启用 lingering,以便 Gateway 网关 在注销后保持运行。 + + 如果作为 systemd 用户服务运行,doctor 会确保已启用 lingering,这样 Gateway 网关在注销后仍能保持运行。 - Doctor 会打印默认智能体的工作区状态摘要: + Doctor 会输出默认智能体的工作区状态摘要: - - **Skills 状态**:统计可用、缺少前置要求以及被 allowlist 阻止的 Skills。 + - **Skills 状态**:统计可用、缺少要求和被 allowlist 阻止的 Skills 数量。 - **旧版工作区目录**:当 `~/openclaw` 或其他旧版工作区目录与当前工作区并存时发出警告。 - - **插件状态**:统计已启用/已禁用/出错的插件;列出所有出错插件的插件 ID;报告内置插件能力。 + - **插件状态**:统计已启用/已禁用/出错的插件数量;列出所有出错插件的插件 ID;报告 bundle 插件能力。 - **插件兼容性警告**:标记与当前运行时存在兼容性问题的插件。 - - **插件诊断**:显示插件注册表在加载时发出的任何警告或错误。 + - **插件诊断**:展示插件注册表在加载时发出的任何警告或错误。 - Doctor 会检查工作区 bootstrap 文件(例如 `AGENTS.md`、`CLAUDE.md` 或其他注入的上下文文件)是否接近或超过已配置的字符预算。它会报告每个文件的原始字符数与注入字符数、截断百分比、截断原因(`max/file` 或 `max/total`),以及总注入字符数占总预算的比例。当文件被截断或接近限制时,doctor 会打印用于调节 `agents.defaults.bootstrapMaxChars` 和 `agents.defaults.bootstrapTotalMaxChars` 的提示。 + Doctor 会检查工作区 bootstrap 文件(例如 `AGENTS.md`、`CLAUDE.md` 或其他注入的上下文文件)是否接近或超过配置的字符预算。它会按文件报告原始字符数与注入字符数、截断百分比、截断原因(`max/file` 或 `max/total`),以及总注入字符数占总预算的比例。当文件被截断或接近上限时,doctor 会输出有关调整 `agents.defaults.bootstrapMaxChars` 和 `agents.defaults.bootstrapTotalMaxChars` 的提示。 - Doctor 会检查当前 shell(zsh、bash、fish 或 PowerShell)是否已安装 tab 补全: + Doctor 会检查当前 shell(zsh、bash、fish 或 PowerShell)是否已安装 Tab 补全: - - 如果 shell profile 使用较慢的动态补全模式(`source <(openclaw completion ...)`),doctor 会将其升级为更快的缓存文件变体。 - - 如果 profile 中已配置补全,但缓存文件缺失,doctor 会自动重新生成缓存。 - - 如果完全未配置补全,doctor 会提示安装(仅限交互模式;`--non-interactive` 下会跳过)。 + - 如果 shell 配置文件使用了较慢的动态补全模式(`source <(openclaw completion ...)`),doctor 会将其升级为更快的缓存文件变体。 + - 如果配置文件中已配置补全,但缓存文件缺失,doctor 会自动重新生成缓存。 + - 如果根本未配置补全,doctor 会提示安装(仅交互模式;`--non-interactive` 会跳过)。 - 运行 `openclaw completion --write-state` 可手动重新生成缓存。 + 运行 `openclaw completion --write-state` 以手动重新生成缓存。 - - Doctor 会检查本地 Gateway 网关 token 认证的就绪情况。 + + Doctor 会检查本地 Gateway 网关令牌认证的就绪状态。 - - 如果 token 模式需要 token 且不存在 token 源,doctor 会提供生成 token 的选项。 - - 如果 `gateway.auth.token` 由 SecretRef 管理但不可用,doctor 会发出警告,并且不会用明文覆盖它。 - - 仅当未配置 token SecretRef 时,`openclaw doctor --generate-gateway-token` 才会强制生成。 + - 如果令牌模式需要令牌且不存在令牌来源,doctor 会提供生成令牌的选项。 + - 如果 `gateway.auth.token` 由 SecretRef 管理但不可用,doctor 会发出警告,且不会用明文覆盖它。 + - `openclaw doctor --generate-gateway-token` 仅会在未配置令牌 SecretRef 时强制生成令牌。 - - 某些修复流程需要检查已配置凭证,而不削弱运行时快速失败行为。 + + 某些修复流程需要检查已配置的凭证,但又不能削弱运行时快速失败行为。 - - `openclaw doctor --fix` 现在使用与 status 系列命令相同的只读 SecretRef 摘要模型来执行有针对性的配置修复。 - - 例如:Telegram `allowFrom` / `groupAllowFrom` 的 `@username` 修复会在可用时尝试使用已配置的 bot 凭证。 - - 如果 Telegram bot token 通过 SecretRef 配置,但在当前命令路径中不可用,doctor 会报告该凭证是“已配置但不可用”,并跳过自动解析,而不是崩溃或错误地将 token 报告为缺失。 + - `openclaw doctor --fix` 现在会像 Status 系列命令一样,使用相同的只读 SecretRef 摘要模型来执行有针对性的配置修复。 + - 例如:Telegram `allowFrom` / `groupAllowFrom` `@username` 修复会在可用时尝试使用已配置的 bot 凭证。 + - 如果 Telegram bot 令牌通过 SecretRef 配置,但在当前命令路径中不可用,doctor 会报告该凭证“已配置但不可用”,并跳过自动解析,而不是崩溃或误报令牌缺失。 - - Doctor 会运行健康检查,并在 Gateway 网关 看起来不健康时提供重启选项。 + + Doctor 会运行健康检查,并在 Gateway 网关看起来不健康时提供重启选项。 - - Doctor 会检查为默认智能体配置的 Memory 搜索嵌入提供商是否已就绪。行为取决于已配置的后端和提供商: + + Doctor 会检查为默认智能体配置的 Memory 搜索 embedding 提供商是否已就绪。行为取决于所配置的后端和提供商: - - **QMD 后端**:探测 `qmd` 二进制文件是否可用且可启动。如果不可用,则打印修复指导,包括 npm 包和手动二进制路径选项。 - - **显式本地提供商**:检查本地模型文件或已识别的远程/可下载模型 URL。如果缺失,则建议切换到远程提供商。 - - **显式远程提供商**(`openai`、`voyage` 等):验证环境变量或认证存储中是否存在 API 密钥。如果缺失,则打印可执行的修复提示。 - - **自动提供商**:先检查本地模型可用性,然后按自动选择顺序依次尝试每个远程提供商。 + - **QMD 后端**:探测 `qmd` 二进制文件是否可用且可启动。如果不可用,会输出修复指引,包括 npm 包和手动二进制路径选项。 + - **显式本地提供商**:检查本地模型文件或可识别的远程/可下载模型 URL 是否存在。如果缺失,会建议切换到远程提供商。 + - **显式远程提供商**(`openai`、`voyage` 等):验证 API key 是否存在于环境变量或认证存储中。如果缺失,会输出可执行的修复提示。 + - **自动提供商**:先检查本地模型可用性,然后按自动选择顺序尝试每个远程提供商。 - 当 Gateway 网关 探测结果可用时(检查时 Gateway 网关 处于健康状态),doctor 会将其结果与 CLI 可见配置进行交叉比对,并注明任何差异。 + 当 Gateway 网关探测结果可用时(检查时 Gateway 网关处于健康状态),doctor 会将其结果与 CLI 可见配置进行交叉比对,并指出任何不一致。 - 使用 `openclaw memory status --deep` 可在运行时验证嵌入就绪情况。 + 使用 `openclaw memory status --deep` 可在运行时验证 embedding 就绪状态。 - 如果 Gateway 网关 健康,doctor 会运行渠道状态探测,并报告带有建议修复措施的警告。 + 如果 Gateway 网关健康,doctor 会运行渠道状态探测,并报告警告及建议修复方式。 - Doctor 会检查已安装的 supervisor 配置(`launchd`/`systemd`/`schtasks`)中是否缺少或过时的默认值(例如 `systemd` 的 `network-online` 依赖项和重启延迟)。发现不匹配时,它会建议更新,并可将服务文件/任务重写为当前默认值。 + Doctor 会检查已安装的 supervisor 配置(launchd/systemd/schtasks)是否缺少或使用了过时默认值(例如 systemd 的 network-online 依赖和重启延迟)。当发现不匹配时,它会建议更新,并可以将服务文件/任务重写为当前默认值。 说明: - `openclaw doctor` 会在重写 supervisor 配置前提示确认。 - `openclaw doctor --yes` 会接受默认修复提示。 - - `openclaw doctor --repair` 会在无提示的情况下应用推荐修复。 + - `openclaw doctor --repair` 会不经提示应用推荐修复。 - `openclaw doctor --repair --force` 会覆盖自定义 supervisor 配置。 - - 如果 token 认证需要 token 且 `gateway.auth.token` 由 SecretRef 管理,doctor 的服务安装/修复会验证该 SecretRef,但不会将解析出的明文 token 值持久化到 supervisor 服务环境元数据中。 - - 如果 token 认证需要 token 且已配置的 token SecretRef 尚未解析,doctor 会阻止安装/修复路径,并提供可执行指导。 - - 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,但未设置 `gateway.auth.mode`,doctor 会阻止安装/修复,直到显式设置模式。 - - 对于 Linux user-systemd 单元,doctor 的 token 漂移检查现在同时包括 `Environment=` 和 `EnvironmentFile=` 源,以比较服务认证元数据。 - - 当配置最后一次是由较新版本写入时,doctor 服务修复会拒绝重写、停止或重启来自较旧 OpenClaw 二进制文件的 Gateway 网关 服务。参见 [Gateway 网关 故障排除](/zh-CN/gateway/troubleshooting#split-brain-installs-and-newer-config-guard)。 - - 你始终可以通过 `openclaw gateway install --force` 强制进行完整重写。 + - `OPENCLAW_SERVICE_REPAIR_POLICY=external` 会让 doctor 在 Gateway 网关服务生命周期方面保持只读。它仍会报告服务健康状态并运行非服务修复,但会跳过服务安装/启动/重启/bootstrap、supervisor 配置重写和旧版服务清理,因为该生命周期由外部 supervisor 管理。 + - 如果令牌认证需要令牌且 `gateway.auth.token` 由 SecretRef 管理,doctor 的服务安装/修复会验证 SecretRef,但不会将解析出的明文令牌值持久化到 supervisor 服务环境元数据中。 + - 如果令牌认证需要令牌,而配置的令牌 SecretRef 未解析,doctor 会阻止安装/修复路径,并提供可执行的指引。 + - 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,但未设置 `gateway.auth.mode`,doctor 会阻止安装/修复,直到显式设置 mode。 + - 对于 Linux user-systemd 单元,doctor 的令牌漂移检查现在会同时包含 `Environment=` 和 `EnvironmentFile=` 来源,用于比较服务认证元数据。 + - 当配置最后一次由较新版本写入时,doctor 的服务修复会拒绝对来自较旧 OpenClaw 二进制文件的 Gateway 网关服务执行重写、停止或重启。参见 [Gateway 网关故障排除](/zh-CN/gateway/troubleshooting#split-brain-installs-and-newer-config-guard)。 + - 你始终可以通过 `openclaw gateway install --force` 强制执行完整重写。 - - Doctor 会检查服务运行时(PID、最后退出状态),并在服务已安装但实际上未运行时发出警告。它还会检查 Gateway 网关 端口(默认 `18789`)上的端口冲突,并报告可能原因(Gateway 网关 已在运行、SSH 隧道)。 + + Doctor 会检查服务运行时(PID、最后退出状态),并在服务已安装但实际未运行时发出警告。它还会检查 Gateway 网关端口(默认 `18789`)上的端口冲突,并报告可能原因(Gateway 网关已在运行、SSH 隧道)。 - - 当 Gateway 网关 服务运行在 Bun 或受版本管理的 Node 路径(`nvm`、`fnm`、`volta`、`asdf` 等)上时,doctor 会发出警告。WhatsApp + Telegram 渠道需要 Node,而版本管理器路径可能会在升级后失效,因为服务不会加载你的 shell 初始化。Doctor 会在系统 Node 安装可用时提供迁移到系统 Node 安装的选项(Homebrew/apt/choco)。 + + 当 Gateway 网关服务运行在 Bun 或版本管理的 Node 路径(`nvm`、`fnm`、`volta`、`asdf` 等)上时,doctor 会发出警告。WhatsApp 和 Telegram 渠道需要 Node,而版本管理器路径在升级后可能失效,因为服务不会加载你的 shell 初始化。Doctor 会在系统 Node 安装可用时提供迁移选项(Homebrew/apt/choco)。 - Doctor 会持久化任何配置更改,并写入向导元数据以记录本次 doctor 运行。 + Doctor 会持久化所有配置更改,并写入向导元数据以记录本次 doctor 运行。 - 当工作区缺少 Memory 系统时,doctor 会给出建议;如果工作区尚未纳入 Git 管理,它还会打印备份提示。 + 当缺少工作区 Memory 系统时,doctor 会提出建议;如果工作区尚未纳入 git,它还会输出备份提示。 - 有关工作区结构和 Git 备份(推荐使用私有 GitHub 或 GitLab)的完整指南,请参见 [/concepts/agent-workspace](/zh-CN/concepts/agent-workspace)。 + 参见 [/concepts/agent-workspace](/zh-CN/concepts/agent-workspace) 获取有关工作区结构和 git 备份的完整指南(推荐使用私有 GitHub 或 GitLab)。 ## 相关内容 -- [Gateway 网关 运行手册](/zh-CN/gateway) -- [Gateway 网关 故障排除](/zh-CN/gateway/troubleshooting) +- [Gateway 网关运行手册](/zh-CN/gateway) +- [Gateway 网关故障排除](/zh-CN/gateway/troubleshooting) diff --git a/docs/zh-CN/gateway/trusted-proxy-auth.md b/docs/zh-CN/gateway/trusted-proxy-auth.md index c3d40a027..c645544cf 100644 --- a/docs/zh-CN/gateway/trusted-proxy-auth.md +++ b/docs/zh-CN/gateway/trusted-proxy-auth.md @@ -1,64 +1,77 @@ --- read_when: - - 在身份感知代理后运行 OpenClaw】【:】【“】【analysis to=final code omitted due to developer instruction conflict? - - 在 OpenClaw 前面设置 Pomerium、Caddy 或 nginx + OAuth - - 修复反向代理配置中的 WebSocket 1008 unauthorized 错误 - - 决定在哪里设置 HSTS 和其他 HTTP 加固头 + - 在身份感知代理后运行 OpenClaw + - 在 OpenClaw 前面使用 OAuth 设置 Pomerium、Caddy 或 nginx + - 修复反向代理设置中的 WebSocket 1008 未授权错误 + - 决定在哪里设置 HSTS 和其他 HTTP 强化标头 +sidebarTitle: Trusted proxy auth summary: 将 Gateway 网关身份验证委托给受信任的反向代理(Pomerium、Caddy、nginx + OAuth) -title: 受信任代理认证 +title: 受信任代理身份验证 x-i18n: - generated_at: "2026-04-23T20:50:24Z" + generated_at: "2026-04-26T08:13:22Z" model: gpt-5.4 provider: openai - source_hash: af406f218fb91c5ae2fed04921670bfc4cd3d06f51b08eec91cddde4521bf771 + source_hash: 64e0f4dee942aedec548135f0408e7773e7b498f8262af13a4d0eff262cae646 source_path: gateway/trusted-proxy-auth.md workflow: 15 --- -> ⚠️ **安全敏感功能。** 此模式会将身份验证完全委托给你的反向代理。配置错误可能会使你的 Gateway 网关暴露给未授权访问。启用前请仔细阅读本页。 + +**安全敏感功能。** 此模式会将身份验证完全委托给你的反向代理。配置错误可能会让未经授权的访问暴露你的 Gateway 网关。启用前请仔细阅读本页。 + ## 何时使用 -在以下情况下使用 `trusted-proxy` 认证模式: +在以下情况下使用 `trusted-proxy` 身份验证模式: -- 你将 OpenClaw 运行在**身份感知代理**后面(Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth) -- 你的代理处理所有身份验证,并通过头部传递用户身份 -- 你处于 Kubernetes 或容器环境中,并且代理是访问 Gateway 网关的唯一路径 -- 你遇到了 WebSocket `1008 unauthorized` 错误,因为浏览器无法在 WS 负载中传递令牌 +- 你在**身份感知代理**后运行 OpenClaw(Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth)。 +- 你的代理处理所有身份验证,并通过标头传递用户身份。 +- 你处于 Kubernetes 或容器环境中,并且代理是访问 Gateway 网关的唯一入口。 +- 你遇到了 WebSocket `1008 unauthorized` 错误,因为浏览器无法在 WS 负载中传递令牌。 -## 何时不要使用 +## 何时**不要**使用 -- 如果你的代理不验证用户身份(只是 TLS 终止器或负载均衡器) -- 如果存在任何绕过代理访问 Gateway 网关的路径(防火墙漏洞、内部网络访问) -- 如果你不确定你的代理是否会正确剥离 / 覆盖转发头 -- 如果你只需要个人单用户访问(可考虑使用 Tailscale Serve + loopback,配置更简单) +- 如果你的代理不验证用户身份(只是 TLS 终止器或负载均衡器)。 +- 如果存在任何绕过代理直接访问 Gateway 网关的路径(防火墙漏洞、内部网络访问)。 +- 如果你不确定你的代理是否会正确剥离/覆盖转发标头。 +- 如果你只需要个人单用户访问(可考虑使用 Tailscale Serve + loopback,以获得更简单的设置)。 ## 工作原理 -1. 你的反向代理对用户进行身份验证(OAuth、OIDC、SAML 等) -2. 代理添加一个包含已验证用户身份的头(例如 `x-forwarded-user: nick@example.com`) -3. OpenClaw 检查请求是否来自**受信任代理 IP**(在 `gateway.trustedProxies` 中配置) -4. OpenClaw 从已配置头中提取用户身份 -5. 如果所有检查都通过,则请求获得授权 + + + 你的反向代理会验证用户身份(OAuth、OIDC、SAML 等)。 + + + 代理会添加一个包含已验证用户身份的标头(例如 `x-forwarded-user: nick@example.com`)。 + + + OpenClaw 会检查请求是否来自**受信任的代理 IP**(在 `gateway.trustedProxies` 中配置)。 + + + OpenClaw 会从已配置的标头中提取用户身份。 + + + 如果一切检查通过,则请求会被授权。 + + ## Control UI 配对行为 -当 `gateway.auth.mode = "trusted-proxy"` 处于活动状态,且请求通过 -trusted-proxy 检查时,Control UI WebSocket 会话可以在没有设备 -配对身份的情况下连接。 +当 `gateway.auth.mode = "trusted-proxy"` 处于启用状态,且请求通过了受信任代理检查时,Control UI WebSocket 会话可以在没有设备配对身份的情况下连接。 -含义: +影响: - 在此模式下,配对不再是 Control UI 访问的主要门槛。 -- 你的反向代理认证策略和 `allowUsers` 会成为实际的访问控制。 -- 请仅将 Gateway 网关入口锁定到受信任代理 IP(`gateway.trustedProxies` + 防火墙)。 +- 你的反向代理身份验证策略和 `allowUsers` 将成为实际的访问控制。 +- 让 Gateway 网关入口仅对受信任代理 IP 开放(`gateway.trustedProxies` + 防火墙)。 ## 配置 ```json5 { gateway: { - // trusted-proxy 认证要求请求来自非 loopback 的受信任代理源 + // 受信任代理身份验证要求请求来自非 loopback 的受信任代理来源 bind: "lan", // 关键:这里只添加你的代理 IP @@ -67,13 +80,13 @@ trusted-proxy 检查时,Control UI WebSocket 会话可以在没有设备 auth: { mode: "trusted-proxy", trustedProxy: { - // 包含已验证用户身份的头(必填) + // 包含已验证用户身份的标头(必需) userHeader: "x-forwarded-user", - // 可选:必须存在的头(代理验证) + // 可选:必须存在的标头(代理验证) requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"], - // 可选:限制为特定用户(空 = 允许所有) + // 可选:限制为特定用户(空 = 允许所有用户) allowUsers: ["nick@example.com", "admin@company.org"], }, }, @@ -81,204 +94,217 @@ trusted-proxy 检查时,Control UI WebSocket 会话可以在没有设备 } ``` -重要运行时规则: + +**重要运行时规则** -- trusted-proxy 认证会拒绝来自 loopback 源的请求(`127.0.0.1`、`::1`、loopback CIDR)。 -- 同主机 loopback 反向代理**不能**满足 trusted-proxy 认证要求。 -- 对于同主机 loopback 代理配置,请改用 token / password 认证,或通过一个 OpenClaw 可验证的非 loopback 受信任代理地址进行路由。 +- 受信任代理身份验证会拒绝来自 loopback 源的请求(`127.0.0.1`、`::1`、loopback CIDR)。 +- 同主机 loopback 反向代理**不**满足受信任代理身份验证要求。 +- 对于同主机 loopback 代理设置,请改用令牌/密码身份验证,或通过 OpenClaw 可以验证的非 loopback 受信任代理地址进行路由。 - 非 loopback 的 Control UI 部署仍需要显式设置 `gateway.controlUi.allowedOrigins`。 -- **转发头证据会覆盖 loopback 本地性。** 如果请求到达于 loopback,但携带了指向非本地来源的 `X-Forwarded-For` / `X-Forwarded-Host` / `X-Forwarded-Proto` 头,那么这些证据会使 loopback 本地性声明失效。该请求会被视为远程请求,并应用于配对、trusted-proxy 认证和 Control UI 设备身份门控。这可以防止同主机 loopback 代理通过转发头身份来伪装 trusted-proxy 认证。 +- **转发标头证据会覆盖 loopback 本地性。** 如果请求到达于 loopback,但携带的 `X-Forwarded-For` / `X-Forwarded-Host` / `X-Forwarded-Proto` 标头指向非本地来源,那么这些证据会使 loopback 本地性声明失效。该请求会被视为远程请求,用于配对、受信任代理身份验证以及 Control UI 设备身份门控。这可防止同主机 loopback 代理将转发标头身份“洗白”进受信任代理身份验证。 + ### 配置参考 -| 字段 | 必填 | 说明 | -| ------------------------------------------- | -------- | --------------------------------------------------------------------------- | -| `gateway.trustedProxies` | 是 | 要信任的代理 IP 地址数组。来自其他 IP 的请求会被拒绝。 | -| `gateway.auth.mode` | 是 | 必须为 `"trusted-proxy"` | -| `gateway.auth.trustedProxy.userHeader` | 是 | 包含已验证用户身份的头名称 | -| `gateway.auth.trustedProxy.requiredHeaders` | 否 | 请求要被信任时必须存在的附加头 | -| `gateway.auth.trustedProxy.allowUsers` | 否 | 用户身份允许列表。为空表示允许所有已验证用户。 | + + 要信任的代理 IP 地址数组。来自其他 IP 的请求会被拒绝。 + + + 必须为 `"trusted-proxy"`。 + + + 包含已验证用户身份的标头名称。 + + + 请求要被信任时必须存在的附加标头。 + + + 用户身份允许列表。为空表示允许所有已验证用户。 + -## TLS 终止和 HSTS +## TLS 终止与 HSTS 使用一个 TLS 终止点,并在那里应用 HSTS。 -### 推荐模式:由代理执行 TLS 终止 + + + 当你的反向代理为 `https://control.example.com` 处理 HTTPS 时,请在该域名的代理处设置 `Strict-Transport-Security`。 -当你的反向代理为 `https://control.example.com` 处理 HTTPS 时,请在 -该域名对应的代理上设置 `Strict-Transport-Security`。 + - 非常适合面向互联网的部署。 + - 将证书和 HTTP 强化策略集中在同一处。 + - OpenClaw 可以在代理后继续使用 loopback HTTP。 -- 非常适合面向互联网的部署。 -- 可将证书和 HTTP 加固策略集中放在一个位置。 -- OpenClaw 可以在代理后面继续使用 loopback HTTP。 + 标头值示例: -示例头值: + ```text + Strict-Transport-Security: max-age=31536000; includeSubDomains + ``` -```text -Strict-Transport-Security: max-age=31536000; includeSubDomains -``` + + + 如果 OpenClaw 本身直接提供 HTTPS 服务(没有执行 TLS 终止的代理),请设置: -### Gateway 网关 TLS 终止 - -如果 OpenClaw 本身直接提供 HTTPS(没有执行 TLS 终止的代理),请设置: - -```json5 -{ - gateway: { - tls: { enabled: true }, - http: { - securityHeaders: { - strictTransportSecurity: "max-age=31536000; includeSubDomains", + ```json5 + { + gateway: { + tls: { enabled: true }, + http: { + securityHeaders: { + strictTransportSecurity: "max-age=31536000; includeSubDomains", + }, + }, }, - }, - }, -} -``` + } + ``` -`strictTransportSecurity` 接受一个字符串形式的头值,或者显式设为 `false` 以禁用。 + `strictTransportSecurity` 接受字符串类型的标头值,或使用 `false` 来显式禁用。 -### 发布建议 + + -- 在验证流量期间,先使用较短的 max age(例如 `max-age=300`)。 -- 仅在你已建立足够信心后,再增加到长期值(例如 `max-age=31536000`)。 -- 只有在每个子域都已支持 HTTPS 时,才添加 `includeSubDomains`。 -- 只有在你有意满足整个域名集合的 preload 要求时,才使用 preload。 -- 仅 loopback 的本地开发不会从 HSTS 中受益。 +### 发布指导 + +- 开始时先使用较短的 max age(例如 `max-age=300`)来验证流量。 +- 只有在确信无误后,再增加到长期值(例如 `max-age=31536000`)。 +- 仅当每个子域都已准备好支持 HTTPS 时,才添加 `includeSubDomains`。 +- 仅当你有意满足整个域名集合的 preload 要求时,才使用 preload。 +- 仅限 loopback 的本地开发不会从 HSTS 中获益。 ## 代理设置示例 -### Pomerium + + + Pomerium 通过 `x-pomerium-claim-email`(或其他声明标头)传递身份,并通过 `x-pomerium-jwt-assertion` 传递 JWT。 -Pomerium 会在 `x-pomerium-claim-email`(或其他 claim 头)中传递身份,并在 `x-pomerium-jwt-assertion` 中传递 JWT。 - -```json5 -{ - gateway: { - bind: "lan", - trustedProxies: ["10.0.0.1"], // Pomerium 的 IP - auth: { - mode: "trusted-proxy", - trustedProxy: { - userHeader: "x-pomerium-claim-email", - requiredHeaders: ["x-pomerium-jwt-assertion"], + ```json5 + { + gateway: { + bind: "lan", + trustedProxies: ["10.0.0.1"], // Pomerium 的 IP + auth: { + mode: "trusted-proxy", + trustedProxy: { + userHeader: "x-pomerium-claim-email", + requiredHeaders: ["x-pomerium-jwt-assertion"], + }, + }, }, - }, - }, -} -``` - -Pomerium 配置片段: - -```yaml -routes: - - from: https://openclaw.example.com - to: http://openclaw-gateway:18789 - policy: - - allow: - or: - - email: - is: nick@example.com - pass_identity_headers: true -``` - -### Caddy 与 OAuth - -带有 `caddy-security` 插件的 Caddy 可以对用户进行身份验证并传递身份头。 - -```json5 -{ - gateway: { - bind: "lan", - trustedProxies: ["10.0.0.1"], // Caddy / sidecar 代理 IP - auth: { - mode: "trusted-proxy", - trustedProxy: { - userHeader: "x-forwarded-user", - }, - }, - }, -} -``` - -Caddyfile 片段: - -``` -openclaw.example.com { - authenticate with oauth2_provider - authorize with policy1 - - reverse_proxy openclaw:18789 { - header_up X-Forwarded-User {http.auth.user.email} } -} -``` + ``` -### nginx + oauth2-proxy + Pomerium 配置片段: -oauth2-proxy 会验证用户身份,并在 `x-auth-request-email` 中传递身份。 + ```yaml + routes: + - from: https://openclaw.example.com + to: http://openclaw-gateway:18789 + policy: + - allow: + or: + - email: + is: nick@example.com + pass_identity_headers: true + ``` -```json5 -{ - gateway: { - bind: "lan", - trustedProxies: ["10.0.0.1"], // nginx / oauth2-proxy IP - auth: { - mode: "trusted-proxy", - trustedProxy: { - userHeader: "x-auth-request-email", + + + 带有 `caddy-security` 插件的 Caddy 可以验证用户身份并传递身份标头。 + + ```json5 + { + gateway: { + bind: "lan", + trustedProxies: ["10.0.0.1"], // Caddy/sidecar 代理 IP + auth: { + mode: "trusted-proxy", + trustedProxy: { + userHeader: "x-forwarded-user", + }, + }, }, - }, - }, -} -``` + } + ``` -nginx 配置片段: + Caddyfile 片段: -```nginx -location / { - auth_request /oauth2/auth; - auth_request_set $user $upstream_http_x_auth_request_email; + ``` + openclaw.example.com { + authenticate with oauth2_provider + authorize with policy1 - proxy_pass http://openclaw:18789; - proxy_set_header X-Auth-Request-Email $user; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; -} -``` + reverse_proxy openclaw:18789 { + header_up X-Forwarded-User {http.auth.user.email} + } + } + ``` -### Traefik 与 Forward Auth + + + oauth2-proxy 会验证用户身份,并通过 `x-auth-request-email` 传递身份。 -```json5 -{ - gateway: { - bind: "lan", - trustedProxies: ["172.17.0.1"], // Traefik 容器 IP - auth: { - mode: "trusted-proxy", - trustedProxy: { - userHeader: "x-forwarded-user", + ```json5 + { + gateway: { + bind: "lan", + trustedProxies: ["10.0.0.1"], // nginx/oauth2-proxy IP + auth: { + mode: "trusted-proxy", + trustedProxy: { + userHeader: "x-auth-request-email", + }, + }, }, - }, - }, -} -``` + } + ``` -## 混合 token 配置 + nginx 配置片段: -当 `gateway.auth.token`(或 `OPENCLAW_GATEWAY_TOKEN`)与 `trusted-proxy` 模式同时启用时,OpenClaw 会拒绝这种含糊不清的配置。混合 token 配置可能导致 loopback 请求在错误的认证路径上被静默认证。 + ```nginx + location / { + auth_request /oauth2/auth; + auth_request_set $user $upstream_http_x_auth_request_email; + + proxy_pass http://openclaw:18789; + proxy_set_header X-Auth-Request-Email $user; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + ``` + + + + ```json5 + { + gateway: { + bind: "lan", + trustedProxies: ["172.17.0.1"], // Traefik 容器 IP + auth: { + mode: "trusted-proxy", + trustedProxy: { + userHeader: "x-forwarded-user", + }, + }, + }, + } + ``` + + + +## 混合令牌配置 + +当 `gateway.auth.token`(或 `OPENCLAW_GATEWAY_TOKEN`)与 `trusted-proxy` 模式同时启用时,OpenClaw 会拒绝这种有歧义的配置。混合令牌配置可能导致 loopback 请求在错误的身份验证路径上被静默验证通过。 如果你在启动时看到 `mixed_trusted_proxy_token` 错误: -- 在使用 trusted-proxy 模式时移除共享 token,或 -- 如果你本来就打算使用基于 token 的认证,请将 `gateway.auth.mode` 切换为 `"token"`。 +- 在使用 trusted-proxy 模式时移除共享令牌,或者 +- 如果你打算使用基于令牌的身份验证,请将 `gateway.auth.mode` 切换为 `"token"`。 -loopback trusted-proxy 认证也会以失败即关闭的方式处理:同主机调用方必须通过受信任代理提供已配置的身份头,而不是被静默认证。 +loopback 的受信任代理身份验证也会以失败关闭方式处理:同主机调用方必须通过受信任代理提供已配置的身份标头,而不是被静默验证通过。 -## 操作员权限头 +## Operator scopes 标头 -trusted-proxy 认证是一种**携带身份**的 HTTP 模式,因此调用方可以 -选择性地使用 `x-openclaw-scopes` 声明操作员权限。 +受信任代理身份验证是一种**携带身份信息的** HTTP 模式,因此调用方可以选择通过 `x-openclaw-scopes` 声明 operator scope。 示例: @@ -288,116 +314,130 @@ trusted-proxy 认证是一种**携带身份**的 HTTP 模式,因此调用方 行为: -- 当该头存在时,OpenClaw 会遵循已声明的权限集。 -- 当该头存在但为空时,请求声明为**无**操作员权限。 -- 当该头缺失时,普通携带身份的 HTTP API 会回退为标准操作员默认权限集。 -- Gateway 网关认证的**插件 HTTP 路由**默认更窄:当 `x-openclaw-scopes` 缺失时,它们的运行时权限会回退为 `operator.write`。 -- 浏览器来源的 HTTP 请求即使已经通过 trusted-proxy 认证,仍必须通过 `gateway.controlUi.allowedOrigins`(或有意启用的 Host 头回退模式)。 +- 当该标头存在时,OpenClaw 会采用所声明的 scope 集合。 +- 当该标头存在但为空时,请求声明的是**无** operator scope。 +- 当该标头缺失时,普通的携带身份信息 HTTP API 会回退到标准的 operator 默认 scope 集合。 +- Gateway 网关身份验证的**插件 HTTP 路由**默认更窄:当 `x-openclaw-scopes` 缺失时,其运行时 scope 会回退到 `operator.write`。 +- 来自浏览器源的 HTTP 请求即使在受信任代理身份验证成功后,仍然必须通过 `gateway.controlUi.allowedOrigins`(或有意启用的 Host 标头回退模式)。 -实用规则: - -- 当你希望 trusted-proxy 请求比默认值更窄时,或者某个 Gateway 网关认证的插件路由需要比 write 更强的权限时,请显式发送 `x-openclaw-scopes`。 +实用规则:当你希望某个受信任代理请求比默认值更窄,或者某个 Gateway 网关身份验证插件路由需要比写入 scope 更强的权限时,请显式发送 `x-openclaw-scopes`。 ## 安全检查清单 -在启用 trusted-proxy 认证之前,请确认: +启用受信任代理身份验证前,请确认: -- [ ] **代理是唯一访问路径**:Gateway 网关端口已通过防火墙阻止除你的代理之外的所有访问 -- [ ] **trustedProxies 保持最小化**:只包含你的实际代理 IP,而不是整个子网 -- [ ] **无 loopback 代理源**:trusted-proxy 认证会对 loopback 源请求以失败即关闭的方式处理 -- [ ] **代理会剥离头**:你的代理会覆盖(而不是追加)来自客户端的 `x-forwarded-*` 头 -- [ ] **TLS 终止**:你的代理处理 TLS;用户通过 HTTPS 连接 -- [ ] **allowedOrigins 显式设置**:非 loopback 的 Control UI 使用显式 `gateway.controlUi.allowedOrigins` -- [ ] **已设置 `allowUsers`**(推荐):限制为已知用户,而不是允许任意已认证用户 -- [ ] **没有混合 token 配置**:不要同时设置 `gateway.auth.token` 和 `gateway.auth.mode: "trusted-proxy"` +- [ ] **代理是唯一入口**:Gateway 网关端口已通过防火墙限制,除你的代理外其他来源均无法访问。 +- [ ] **trustedProxies 最小化**:只包含你实际使用的代理 IP,而不是整个子网。 +- [ ] **没有 loopback 代理来源**:对于来自 loopback 源的请求,受信任代理身份验证会以失败关闭方式处理。 +- [ ] **代理会剥离标头**:你的代理会覆盖(而不是追加)来自客户端的 `x-forwarded-*` 标头。 +- [ ] **TLS 终止**:你的代理处理 TLS;用户通过 HTTPS 连接。 +- [ ] **allowedOrigins 已显式设置**:非 loopback 的 Control UI 使用显式的 `gateway.controlUi.allowedOrigins`。 +- [ ] **已设置 allowUsers**(推荐):限制为已知用户,而不是允许任何已验证用户。 +- [ ] **没有混合令牌配置**:不要同时设置 `gateway.auth.token` 和 `gateway.auth.mode: "trusted-proxy"`。 ## 安全审计 -`openclaw security audit` 会将 trusted-proxy 认证标记为**严重**级别发现。这是有意设计的——提醒你已将安全性委托给代理配置。 +`openclaw security audit` 会将受信任代理身份验证标记为**严重**级别发现。这是有意为之——它是在提醒你:你正在将安全性委托给你的代理配置。 审计会检查: -- 基础 `gateway.trusted_proxy_auth` 警告 / 严重提醒 +- 基础 `gateway.trusted_proxy_auth` 警告/严重提醒 - 缺少 `trustedProxies` 配置 - 缺少 `userHeader` 配置 -- 空的 `allowUsers`(允许任意已认证用户) -- 暴露的 Control UI 界面上存在通配符或缺失的浏览器来源策略 +- `allowUsers` 为空(允许任何已验证用户) +- 在暴露的 Control UI 表面上,浏览器来源策略为通配符或缺失 ## 故障排除 -### “trusted_proxy_untrusted_source” + + + 请求并非来自 `gateway.trustedProxies` 中的 IP。请检查: -请求并非来自 `gateway.trustedProxies` 中的某个 IP。请检查: + - 代理 IP 是否正确?(Docker 容器 IP 可能会变化。) + - 你的代理前面是否还有负载均衡器? + - 使用 `docker inspect` 或 `kubectl get pods -o wide` 查找实际 IP。 -- 代理 IP 是否正确?(Docker 容器 IP 可能会变化) -- 你的代理前面是否还有负载均衡器? -- 使用 `docker inspect` 或 `kubectl get pods -o wide` 查找实际 IP + + + OpenClaw 拒绝了来自 loopback 源的 trusted-proxy 请求。 -### “trusted_proxy_loopback_source” + 请检查: -OpenClaw 拒绝了一个来自 loopback 源的 trusted-proxy 请求。 + - 代理是否从 `127.0.0.1` / `::1` 发起连接? + - 你是否正在尝试将 trusted-proxy 身份验证用于同主机 loopback 反向代理? -请检查: + 修复方法: -- 代理是否从 `127.0.0.1` / `::1` 连接? -- 你是否正在尝试用同主机 loopback 反向代理来使用 trusted-proxy 认证? + - 对同主机 loopback 代理设置使用令牌/密码身份验证,或者 + - 通过非 loopback 的受信任代理地址进行路由,并将该 IP 保留在 `gateway.trustedProxies` 中。 -修复: + + + 用户标头为空或缺失。请检查: -- 对于同主机 loopback 代理配置,请使用 token / password 认证,或 -- 通过非 loopback 的受信任代理地址进行路由,并将该 IP 保留在 `gateway.trustedProxies` 中。 + - 你的代理是否已配置为传递身份标头? + - 标头名称是否正确?(大小写不敏感,但拼写很重要) + - 用户是否确实已在代理处完成身份验证? -### “trusted_proxy_user_missing” + + + 某个必需标头不存在。请检查: -用户头为空或缺失。请检查: + - 你的代理中针对这些特定标头的配置。 + - 标头是否在链路中的某处被剥离。 -- 你的代理是否配置为传递身份头? -- 头名称是否正确?(不区分大小写,但拼写必须正确) -- 用户是否确实已在代理处完成身份验证? + + + 用户已通过身份验证,但不在 `allowUsers` 中。请将其加入,或移除允许列表。 + + + trusted-proxy 身份验证已成功,但浏览器的 `Origin` 标头未通过 Control UI 来源检查。 -### “trusted*proxy_missing_header*\*” + 请检查: -某个必需头不存在。请检查: + - `gateway.controlUi.allowedOrigins` 是否包含精确的浏览器来源。 + - 你是否没有依赖通配符来源,除非你确实想要允许所有来源的行为。 + - 如果你有意使用 Host 标头回退模式,是否已明确设置 `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true`。 -- 你的代理中这些特定头的配置 -- 这些头是否在链路中的某处被剥离 + + + 请确保你的代理: -### “trusted_proxy_user_not_allowed” + - 支持 WebSocket 升级(`Upgrade: websocket`、`Connection: upgrade`)。 + - 在 WebSocket 升级请求中传递身份标头(而不只是 HTTP)。 + - 没有为 WebSocket 连接设置单独的身份验证路径。 -用户已通过身份验证,但不在 `allowUsers` 中。请将其添加进去,或移除允许列表。 + + -### “trusted_proxy_origin_not_allowed” +## 从令牌身份验证迁移 -trusted-proxy 认证已成功,但浏览器 `Origin` 头未通过 Control UI 来源检查。 +如果你正在从令牌身份验证迁移到 trusted-proxy: -请检查: - -- `gateway.controlUi.allowedOrigins` 是否包含精确的浏览器来源 -- 除非你明确希望允许所有来源,否则不要依赖通配符来源 -- 如果你有意使用 Host 头回退模式,是否已明确设置 `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` - -### WebSocket 仍然失败 - -请确保你的代理: - -- 支持 WebSocket 升级(`Upgrade: websocket`、`Connection: upgrade`) -- 在 WebSocket 升级请求中传递身份头(而不仅仅是普通 HTTP) -- 没有为 WebSocket 连接使用单独的认证路径 - -## 从 token 认证迁移 - -如果你要从 token 认证迁移到 trusted-proxy: - -1. 配置你的代理,对用户进行身份验证并传递头 -2. 独立测试代理配置(带头的 curl) -3. 使用 trusted-proxy 认证更新 OpenClaw 配置 -4. 重启 Gateway 网关 -5. 从 Control UI 测试 WebSocket 连接 -6. 运行 `openclaw security audit` 并审查发现项 + + + 配置你的代理来验证用户身份并传递标头。 + + + 独立测试代理设置(使用带标头的 curl)。 + + + 使用 trusted-proxy 身份验证更新 OpenClaw 配置。 + + + 重启 Gateway 网关。 + + + 从 Control UI 测试 WebSocket 连接。 + + + 运行 `openclaw security audit` 并查看发现项。 + + ## 相关内容 -- [Security](/zh-CN/gateway/security) —— 完整安全指南 -- [Configuration](/zh-CN/gateway/configuration) —— 配置参考 -- [Remote Access](/zh-CN/gateway/remote) —— 其他远程访问模式 -- [Tailscale](/zh-CN/gateway/tailscale) —— 仅 tailnet 访问时更简单的替代方案 +- [配置](/zh-CN/gateway/configuration) — 配置参考 +- [远程访问](/zh-CN/gateway/remote) — 其他远程访问模式 +- [安全](/zh-CN/gateway/security) — 完整安全指南 +- [Tailscale](/zh-CN/gateway/tailscale) — 仅限 tailnet 访问的更简单替代方案 diff --git a/docs/zh-CN/nodes/media-understanding.md b/docs/zh-CN/nodes/media-understanding.md index 4f3f18afb..c4d18d314 100644 --- a/docs/zh-CN/nodes/media-understanding.md +++ b/docs/zh-CN/nodes/media-understanding.md @@ -1,61 +1,75 @@ --- read_when: - 设计或重构媒体理解 - - 调优入站音频/视频/图像预处理 -summary: 入站图像/音频/视频理解(可选),带提供商 + CLI 回退机制 + - 调整入站音频/视频/图像预处理 +sidebarTitle: Media understanding +summary: 入站图像/音频/视频理解(可选),并提供 provider + CLI 回退方案 title: 媒体理解 x-i18n: - generated_at: "2026-04-26T04:25:28Z" + generated_at: "2026-04-26T08:13:18Z" model: gpt-5.4 provider: openai - source_hash: 513fe1557bb3fce3189f7009d85ad13f43713521243a95fd9427a4c89b57f238 + source_hash: 25ee170a7af523fd2ce4f5f7764638f510b135f94a7796325daf1c3e04147f90 source_path: nodes/media-understanding.md workflow: 15 --- -# 媒体理解 - 入站(2026-01-17) +OpenClaw 可以在回复流水线运行之前,**总结入站媒体**(图像/音频/视频)。它会在检测到本地工具或 provider 密钥可用时自动启用,也可以被禁用或自定义。如果理解功能关闭,模型仍会像往常一样接收原始文件/URL。 -OpenClaw 可以在回复流水线运行前**总结入站媒体**(图像/音频/视频)。它会在本地工具或提供商密钥可用时自动检测,并且可以被禁用或自定义。如果理解功能关闭,模型仍会像往常一样接收原始文件/URL。 - -特定厂商的媒体行为由厂商插件注册,而 OpenClaw -核心负责共享的 `tools.media` 配置、回退顺序以及回复流水线 -集成。 +特定厂商的媒体行为由厂商插件注册,而 OpenClaw 核心负责共享的 `tools.media` 配置、回退顺序以及回复流水线集成。 ## 目标 -- 可选:将入站媒体预先提炼为简短文本,以实现更快的路由 + 更好的命令解析。 -- 始终保留向模型传递原始媒体(总是如此)。 -- 支持**provider API** 和 **CLI 回退**。 -- 允许多个模型按顺序回退(错误/大小/超时)。 +- 可选:将入站媒体预先提炼为简短文本,以便更快路由并提升命令解析效果。 +- 始终保留向模型传递原始媒体的能力。 +- 支持 **provider API** 和 **CLI 回退方案**。 +- 允许使用多个模型并按顺序回退(错误/大小/超时)。 ## 高层行为 -1. 收集入站附件(`MediaPaths`、`MediaUrls`、`MediaTypes`)。 -2. 对于每个已启用的能力(图像/音频/视频),按策略选择附件(默认:**第一个**)。 -3. 选择第一个符合条件的模型条目(大小 + 能力 + 身份验证)。 -4. 如果某个模型失败或媒体过大,**回退到下一个条目**。 -5. 成功时: - - `Body` 变为 `[Image]`、`[Audio]` 或 `[Video]` 块。 - - 音频会设置 `{{Transcript}}`;命令解析在有说明文字时使用说明文字, - 否则使用转录文本。 - - 说明文字会作为 `User text:` 保留在块内。 + + + 收集入站附件(`MediaPaths`、`MediaUrls`、`MediaTypes`)。 + + + 对于每个已启用的能力(图像/音频/视频),根据策略选择附件(默认:**第一个**)。 + + + 选择第一个符合条件的模型条目(大小 + 能力 + 认证)。 + + + 如果模型失败或媒体过大,**回退到下一个条目**。 + + + 成功时: -如果理解失败或被禁用,**回复流程仍会继续**,并使用原始正文 + 附件。 + - `Body` 变为 `[Image]`、`[Audio]` 或 `[Video]` 块。 + - 音频会设置 `{{Transcript}}`;存在说明文字时,命令解析使用说明文字,否则使用转录文本。 + - 说明文字会以 `User text:` 的形式保留在块中。 + + + + +如果理解失败或被禁用,**回复流程会继续**,并使用原始正文 + 附件。 ## 配置概览 -`tools.media` 支持**共享模型**以及按能力分别覆盖的配置: +`tools.media` 支持**共享模型**以及按能力划分的覆盖配置: -- `tools.media.models`:共享模型列表(使用 `capabilities` 进行限制)。 -- `tools.media.image` / `tools.media.audio` / `tools.media.video`: - - 默认值(`prompt`、`maxChars`、`maxBytes`、`timeoutSeconds`、`language`) - - 提供商覆盖项(`baseUrl`、`headers`、`providerOptions`) - - 通过 `tools.media.audio.providerOptions.deepgram` 配置 Deepgram 音频选项 - - 音频转录回显控制(`echoTranscript`,默认 `false`;`echoFormat`) - - 可选的**按能力分别定义的 `models` 列表**(优先于共享模型) - - `attachments` 策略(`mode`、`maxAttachments`、`prefer`) - - `scope`(可选,按渠道/聊天类型/会话键进行限制) -- `tools.media.concurrency`:能力运行的最大并发数(默认 **2**)。 + + + - `tools.media.models`:共享模型列表(使用 `capabilities` 控制适用范围)。 + - `tools.media.image` / `tools.media.audio` / `tools.media.video`: + - 默认值(`prompt`、`maxChars`、`maxBytes`、`timeoutSeconds`、`language`) + - provider 覆盖项(`baseUrl`、`headers`、`providerOptions`) + - 通过 `tools.media.audio.providerOptions.deepgram` 配置 Deepgram 音频选项 + - 音频转录回显控制(`echoTranscript`,默认 `false`;`echoFormat`) + - 可选的按能力划分的 `models` 列表(优先于共享模型) + - `attachments` 策略(`mode`、`maxAttachments`、`prefer`) + - `scope`(可选,按渠道/chatType/session key 进行限制) + - `tools.media.concurrency`:最大并发能力运行数(默认 **2**)。 + + ```json5 { @@ -84,97 +98,110 @@ OpenClaw 可以在回复流水线运行前**总结入站媒体**(图像/音频 每个 `models[]` 条目都可以是 **provider** 或 **CLI**: -```json5 -{ - type: "provider", // 如果省略,默认值为此 - provider: "openai", - model: "gpt-5.5", - prompt: "Describe the image in <= 500 chars.", - maxChars: 500, - maxBytes: 10485760, - timeoutSeconds: 60, - capabilities: ["image"], // 可选,用于多模态条目 - profile: "vision-profile", - preferredProfile: "vision-fallback", -} -``` + + + ```json5 + { + type: "provider", // 如果省略则为默认值 + provider: "openai", + model: "gpt-5.5", + prompt: "Describe the image in <= 500 chars.", + maxChars: 500, + maxBytes: 10485760, + timeoutSeconds: 60, + capabilities: ["image"], // 可选,用于多模态条目 + profile: "vision-profile", + preferredProfile: "vision-fallback", + } + ``` + + + ```json5 + { + type: "cli", + command: "gemini", + args: [ + "-m", + "gemini-3-flash", + "--allowed-tools", + "read_file", + "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", + ], + maxChars: 500, + maxBytes: 52428800, + timeoutSeconds: 120, + capabilities: ["video", "image"], + } + ``` -```json5 -{ - type: "cli", - command: "gemini", - args: [ - "-m", - "gemini-3-flash", - "--allowed-tools", - "read_file", - "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", - ], - maxChars: 500, - maxBytes: 52428800, - timeoutSeconds: 120, - capabilities: ["video", "image"], -} -``` + CLI 模板还可以使用: -CLI 模板还可以使用: + - `{{MediaDir}}`(包含媒体文件的目录) + - `{{OutputDir}}`(为本次运行创建的临时目录) + - `{{OutputBase}}`(临时输出文件基础路径,不含扩展名) -- `{{MediaDir}}`(包含媒体文件的目录) -- `{{OutputDir}}`(为本次运行创建的临时目录) -- `{{OutputBase}}`(临时文件基础路径,不含扩展名) + + -## 默认值和限制 +## 默认值与限制 推荐默认值: -- 图像/视频的 `maxChars`:**500**(简短,便于命令处理) -- 音频的 `maxChars`:**未设置**(除非你设置限制,否则为完整转录) +- `maxChars`:图像/视频为 **500**(简短、便于命令处理) +- `maxChars`:音频为**未设置**(除非你设置限制,否则返回完整转录) - `maxBytes`: - - 图像:**10MB** - - 音频:**20MB** - - 视频:**50MB** + - 图像:**10 MB** + - 音频:**20 MB** + - 视频:**50 MB** -规则: - -- 如果媒体超过 `maxBytes`,则跳过该模型,并**尝试下一个模型**。 -- 小于 **1024 字节**的音频文件会被视为空/损坏,并在提供商/CLI 转录之前跳过;入站回复上下文会收到一个确定性的占位转录文本,以便智能体知道该语音笔记过小。 -- 如果模型返回的内容超过 `maxChars`,输出会被截断。 -- `prompt` 默认为简单的“Describe the {media}.”,并附带 `maxChars` 指引(仅图像/视频)。 -- 如果当前激活的主图像模型已原生支持视觉能力,OpenClaw - 会跳过 `[Image]` 摘要块,而是将原始图像直接传入 - 模型。 -- 如果 Gateway 网关/WebChat 主模型仅支持文本,图像附件会 - 以卸载后的 `media://inbound/*` 引用形式保留,因此图像/PDF 工具或已配置的图像模型仍可检查它们,而不会丢失附件。 -- 显式的 `openclaw infer image describe --model ` 请求 - 则不同:它们会直接运行该支持图像的 provider/模型,包括 - 像 `ollama/qwen2.5vl:7b` 这样的 Ollama 引用。 -- 如果 `.enabled: true` 但未配置模型,OpenClaw 会在 - 其提供商支持该能力时尝试使用**当前激活的回复模型**。 + + + - 如果媒体超过 `maxBytes`,则跳过该模型并**尝试下一个模型**。 + - 小于 **1024 字节**的音频文件会被视为空或损坏,并在 provider/CLI 转录之前被跳过;入站回复上下文会收到一个确定性的占位转录文本,以便智能体知道该语音便笺过小。 + - 如果模型返回内容超过 `maxChars`,输出会被截断。 + - `prompt` 默认为简单的 “Describe the {media}.”,并附带 `maxChars` 提示(仅图像/视频)。 + - 如果当前主图像模型已经原生支持视觉能力,OpenClaw 会跳过 `[Image]` 摘要块,并改为直接将原始图像传给模型。 + - 如果 Gateway 网关 / WebChat 主模型仅支持文本,图像附件会保留为卸载的 `media://inbound/*` 引用,这样图像/PDF 工具或已配置的图像模型仍可检查它们,而不会丢失附件。 + - 显式的 `openclaw infer image describe --model ` 请求有所不同:它们会直接运行指定的具备图像能力的 provider/模型,包括诸如 `ollama/qwen2.5vl:7b` 之类的 Ollama 引用。 + - 如果 `.enabled: true`,但未配置任何模型,当其 provider 支持该能力时,OpenClaw 会尝试**当前活动的回复模型**。 + + ### 自动检测媒体理解(默认) -如果 `tools.media..enabled` **未**设置为 `false`,并且你尚未 -配置模型,OpenClaw 会按以下顺序自动检测,并在**第一个 -可用选项**处停止: +如果 `tools.media..enabled` **未**被设置为 `false`,并且你尚未配置模型,OpenClaw 会按以下顺序自动检测,并在**第一个可用选项**处停止: -1. **当前激活的回复模型**,前提是其提供商支持该能力。 -2. **`agents.defaults.imageModel`** 主/回退引用(仅图像)。 -3. **本地 CLI**(仅音频;如果已安装) - - `sherpa-onnx-offline`(需要 `SHERPA_ONNX_MODEL_DIR`,其中包含 encoder/decoder/joiner/tokens) - - `whisper-cli`(`whisper-cpp`;使用 `WHISPER_CPP_MODEL` 或内置 tiny 模型) - - `whisper`(Python CLI;会自动下载模型) -4. **Gemini CLI**(`gemini`),使用 `read_many_files` -5. **提供商身份验证** - - 已配置的 `models.providers.*` 条目中,支持该能力的条目会在内置回退顺序之前 - 被优先尝试。 - - 仅图像的配置提供商,只要具有支持图像的模型,即使它们不是内置厂商插件,也会自动为 - 媒体理解注册。 - - 当显式选择 Ollama 图像理解时可用,例如通过 `agents.defaults.imageModel` 或 - `openclaw infer image describe --model ollama/`。 - - 内置回退顺序: - - 音频:OpenAI → Groq → xAI → Deepgram → Google → SenseAudio → ElevenLabs → Mistral - - 图像:OpenAI → Anthropic → Google → MiniMax → MiniMax Portal → Z.AI - - 视频:Google → Qwen → Moonshot + + + 当其 provider 支持该能力时,使用当前活动的回复模型。 + + + `agents.defaults.imageModel` 的主/回退引用(仅图像)。 + + + 本地 CLI(如果已安装): + + - `sherpa-onnx-offline`(要求 `SHERPA_ONNX_MODEL_DIR` 中包含 encoder/decoder/joiner/tokens) + - `whisper-cli`(`whisper-cpp`;使用 `WHISPER_CPP_MODEL` 或内置的 tiny 模型) + - `whisper`(Python CLI;自动下载模型) + + + + 使用 `read_many_files` 的 `gemini`。 + + + - 已配置的 `models.providers.*` 条目中,支持该能力的项会优先于内置回退顺序进行尝试。 + - 仅图像配置的 provider,只要模型具备图像能力,即使它们不是内置厂商插件,也会自动注册到媒体理解中。 + - 当显式选中时,Ollama 图像理解可用,例如通过 `agents.defaults.imageModel` 或 `openclaw infer image describe --model ollama/`。 + + 内置回退顺序: + + - 音频:OpenAI → Groq → xAI → Deepgram → Google → SenseAudio → ElevenLabs → Mistral + - 图像:OpenAI → Anthropic → Google → MiniMax → MiniMax Portal → Z.AI + - 视频:Google → Qwen → Moonshot + + + 要禁用自动检测,请设置: @@ -190,26 +217,24 @@ CLI 模板还可以使用: } ``` -注意:二进制检测在 macOS/Linux/Windows 上是尽力而为的;请确保 CLI 在 `PATH` 中(我们会展开 `~`),或者使用带完整命令路径的显式 CLI 模型。 + +二进制检测会尽力兼容 macOS/Linux/Windows;请确保 CLI 位于 `PATH` 中(我们会展开 `~`),或者设置带完整命令路径的显式 CLI 模型。 + ### 代理环境支持(provider 模型) -当基于提供商的**音频**和**视频**媒体理解启用时,OpenClaw -会在提供商 HTTP 调用中遵循标准的出站代理环境变量: +当基于 provider 的**音频**和**视频**媒体理解启用时,OpenClaw 会在 provider HTTP 调用中遵循标准的出站代理环境变量: - `HTTPS_PROXY` - `HTTP_PROXY` - `https_proxy` - `http_proxy` -如果未设置任何代理环境变量,媒体理解将使用直接出站连接。 -如果代理值格式错误,OpenClaw 会记录警告并回退为直接 -获取。 +如果未设置任何代理环境变量,媒体理解将使用直连出站。如果代理值格式错误,OpenClaw 会记录一条警告并回退为直接抓取。 ## 能力(可选) -如果你设置了 `capabilities`,该条目只会对这些媒体类型运行。对于共享 -列表,OpenClaw 可以推断默认值: +如果你设置了 `capabilities`,该条目只会用于这些媒体类型。对于共享列表,OpenClaw 可以推断默认值: - `openai`、`anthropic`、`minimax`:**图像** - `minimax-portal`:**图像** @@ -222,225 +247,223 @@ CLI 模板还可以使用: - `groq`:**音频** - `xai`:**音频** - `deepgram`:**音频** -- 任何带有支持图像模型的 `models.providers..models[]` 目录: - **图像** +- 任何 `models.providers..models[]` 目录中带有具备图像能力模型的项:**图像** -对于 CLI 条目,**请显式设置 `capabilities`**,以避免意外匹配。 -如果你省略了 `capabilities`,该条目将适用于它所在的列表。 +对于 CLI 条目,**请显式设置 `capabilities`**,以避免出现意外匹配。如果你省略 `capabilities`,该条目将适用于它所在的列表。 -## 提供商支持矩阵(OpenClaw 集成) +## Provider 支持矩阵(OpenClaw 集成) -| Capability | Provider integration | Notes | -| ---------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 图像 | OpenAI、OpenAI Codex OAuth、Codex app-server、OpenRouter、Anthropic、Google、MiniMax、Moonshot、Qwen、Z.AI、配置提供商 | 厂商插件会注册图像支持;`openai-codex/*` 使用 OAuth provider 管道;`codex/*` 使用受限的 Codex app-server 轮次;MiniMax 和 MiniMax OAuth 都使用 `MiniMax-VL-01`;支持图像的配置提供商会自动注册。 | -| 音频 | OpenAI、Groq、xAI、Deepgram、Google、SenseAudio、ElevenLabs、Mistral | 提供商转录(Whisper/Groq/xAI/Deepgram/Gemini/SenseAudio/Scribe/Voxtral)。 | -| 视频 | Google、Qwen、Moonshot | 通过厂商插件提供视频理解;Qwen 视频理解使用 Standard DashScope 端点。 | +| Capability | Provider 集成 | 说明 | +| ---------- | ------------- | ---- | +| 图像 | OpenAI、OpenAI Codex OAuth、Codex app-server、OpenRouter、Anthropic、Google、MiniMax、Moonshot、Qwen、Z.AI、配置 provider | 厂商插件负责注册图像支持;`openai-codex/*` 使用 OAuth provider 管道;`codex/*` 使用受限的 Codex app-server 回合;MiniMax 和 MiniMax OAuth 都使用 `MiniMax-VL-01`;具备图像能力的配置 provider 会自动注册。 | +| 音频 | OpenAI、Groq、xAI、Deepgram、Google、SenseAudio、ElevenLabs、Mistral | provider 转录(Whisper/Groq/xAI/Deepgram/Gemini/SenseAudio/Scribe/Voxtral)。 | +| 视频 | Google、Qwen、Moonshot | 通过厂商插件提供 provider 视频理解;Qwen 视频理解使用标准 DashScope 端点。 | -MiniMax 说明: + +**MiniMax 说明** -- `minimax` 和 `minimax-portal` 图像理解来自插件自有的 - `MiniMax-VL-01` 媒体提供商。 -- 内置的 MiniMax 文本目录仍以仅文本能力开始;显式的 - `models.providers.minimax` 条目会具体化支持图像的 M2.7 聊天引用。 +- `minimax` 和 `minimax-portal` 图像理解来自插件自有的 `MiniMax-VL-01` 媒体 provider。 +- 内置的 MiniMax 文本目录仍然从纯文本开始;显式的 `models.providers.minimax` 条目会实例化具备图像能力的 M2.7 聊天引用。 + -## 模型选择指导 +## 模型选择指南 -- 当质量和安全性很重要时,优先为每种媒体能力选择可用的最新一代最强模型。 -- 对于处理不受信任输入的启用工具的智能体,避免使用较旧/较弱的媒体模型。 -- 每种能力至少保留一个回退选项以保证可用性(高质量模型 + 更快/更便宜的模型)。 -- 当 provider API 不可用时,CLI 回退(`whisper-cli`、`whisper`、`gemini`)非常有用。 -- `parakeet-mlx` 说明:使用 `--output-dir` 时,当输出格式为 `txt`(或未指定)时,OpenClaw 会读取 `/.txt`;非 `txt` 格式则回退到 stdout。 +- 当质量和安全性很重要时,优先为每种媒体能力选择最新一代、性能最强的模型。 +- 对于处理不可信输入的启用工具的智能体,避免使用较旧/较弱的媒体模型。 +- 每种能力至少保留一个回退项以保证可用性(高质量模型 + 更快/更便宜的模型)。 +- 当 provider API 不可用时,CLI 回退方案(`whisper-cli`、`whisper`、`gemini`)很有用。 +- `parakeet-mlx` 说明:使用 `--output-dir` 时,如果输出格式为 `txt`(或未指定),OpenClaw 会读取 `/.txt`;非 `txt` 格式则回退到 stdout。 ## 附件策略 -按能力分别设置的 `attachments` 用于控制处理哪些附件: +按能力划分的 `attachments` 控制要处理哪些附件: -- `mode`:`first`(默认)或 `all` -- `maxAttachments`:处理数量上限(默认 **1**) -- `prefer`:`first`、`last`、`path`、`url` + + 是处理第一个选中的附件,还是处理全部附件。 + + + 限制处理的数量上限。 + + + 在候选附件中的选择偏好。 + 当 `mode: "all"` 时,输出会标记为 `[Image 1/2]`、`[Audio 2/2]` 等。 -文件附件提取行为: - -- 提取出的文件文本会先包装为**不受信任的外部内容**,然后再追加到媒体提示词中。 -- 注入的块使用显式边界标记,例如 - `<<>>` / - `<<>>`,并包含一行 - `Source: External` 元数据。 -- 此附件提取路径有意省略较长的 - `SECURITY NOTICE:` 横幅,以避免媒体提示词过度膨胀;但边界 - 标记和元数据仍会保留。 -- 如果文件没有可提取的文本,OpenClaw 会注入 `[No extractable text]`。 -- 如果 PDF 在此路径中回退为渲染后的页面图像,媒体提示词会保留 - 占位符 `[PDF content rendered to images; images not forwarded to model]`, - 因为该附件提取步骤传递的是文本块,而不是渲染后的 PDF 图像。 + + + - 提取出的文件文本会先包装为**不受信任的外部内容**,然后再附加到媒体提示中。 + - 注入的区块会使用明确的边界标记,例如 `<<>>` / `<<>>`,并包含一行 `Source: External` 元数据。 + - 这个附件提取路径会有意省略较长的 `SECURITY NOTICE:` 横幅,以避免媒体提示过于臃肿;但边界标记和元数据仍会保留。 + - 如果文件没有可提取的文本,OpenClaw 会注入 `[No extractable text]`。 + - 如果 PDF 在此路径中回退为渲染后的页面图像,媒体提示会保留占位文本 `[PDF content rendered to images; images not forwarded to model]`,因为这个附件提取步骤传递的是文本块,而不是渲染后的 PDF 图像。 + + ## 配置示例 -### 1) 共享模型列表 + 覆盖项 - -```json5 -{ - tools: { - media: { - models: [ - { provider: "openai", model: "gpt-5.5", capabilities: ["image"] }, - { - provider: "google", - model: "gemini-3-flash-preview", - capabilities: ["image", "audio", "video"], - }, - { - type: "cli", - command: "gemini", - args: [ - "-m", - "gemini-3-flash", - "--allowed-tools", - "read_file", - "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", + + + ```json5 + { + tools: { + media: { + models: [ + { provider: "openai", model: "gpt-5.5", capabilities: ["image"] }, + { + provider: "google", + model: "gemini-3-flash-preview", + capabilities: ["image", "audio", "video"], + }, + { + type: "cli", + command: "gemini", + args: [ + "-m", + "gemini-3-flash", + "--allowed-tools", + "read_file", + "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", + ], + capabilities: ["image", "video"], + }, ], - capabilities: ["image", "video"], + audio: { + attachments: { mode: "all", maxAttachments: 2 }, + }, + video: { + maxChars: 500, + }, }, - ], - audio: { - attachments: { mode: "all", maxAttachments: 2 }, }, - video: { - maxChars: 500, - }, - }, - }, -} -``` - -### 2) 仅音频 + 视频(图像关闭) - -```json5 -{ - tools: { - media: { - audio: { - enabled: true, - models: [ - { provider: "openai", model: "gpt-4o-mini-transcribe" }, - { - type: "cli", - command: "whisper", - args: ["--model", "base", "{{MediaPath}}"], - }, - ], - }, - video: { - enabled: true, - maxChars: 500, - models: [ - { provider: "google", model: "gemini-3-flash-preview" }, - { - type: "cli", - command: "gemini", - args: [ - "-m", - "gemini-3-flash", - "--allowed-tools", - "read_file", - "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", + } + ``` + + + ```json5 + { + tools: { + media: { + audio: { + enabled: true, + models: [ + { provider: "openai", model: "gpt-4o-mini-transcribe" }, + { + type: "cli", + command: "whisper", + args: ["--model", "base", "{{MediaPath}}"], + }, ], }, - ], - }, - }, - }, -} -``` - -### 3) 可选图像理解 - -```json5 -{ - tools: { - media: { - image: { - enabled: true, - maxBytes: 10485760, - maxChars: 500, - models: [ - { provider: "openai", model: "gpt-5.5" }, - { provider: "anthropic", model: "claude-opus-4-6" }, - { - type: "cli", - command: "gemini", - args: [ - "-m", - "gemini-3-flash", - "--allowed-tools", - "read_file", - "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", + video: { + enabled: true, + maxChars: 500, + models: [ + { provider: "google", model: "gemini-3-flash-preview" }, + { + type: "cli", + command: "gemini", + args: [ + "-m", + "gemini-3-flash", + "--allowed-tools", + "read_file", + "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", + ], + }, ], }, - ], + }, }, - }, - }, -} -``` - -### 4) 多模态单条目(显式能力) - -```json5 -{ - tools: { - media: { - image: { - models: [ - { - provider: "google", - model: "gemini-3.1-pro-preview", - capabilities: ["image", "video", "audio"], + } + ``` + + + ```json5 + { + tools: { + media: { + image: { + enabled: true, + maxBytes: 10485760, + maxChars: 500, + models: [ + { provider: "openai", model: "gpt-5.5" }, + { provider: "anthropic", model: "claude-opus-4-6" }, + { + type: "cli", + command: "gemini", + args: [ + "-m", + "gemini-3-flash", + "--allowed-tools", + "read_file", + "Read the media at {{MediaPath}} and describe it in <= {{MaxChars}} characters.", + ], + }, + ], }, - ], + }, }, - audio: { - models: [ - { - provider: "google", - model: "gemini-3.1-pro-preview", - capabilities: ["image", "video", "audio"], + } + ``` + + + ```json5 + { + tools: { + media: { + image: { + models: [ + { + provider: "google", + model: "gemini-3.1-pro-preview", + capabilities: ["image", "video", "audio"], + }, + ], }, - ], - }, - video: { - models: [ - { - provider: "google", - model: "gemini-3.1-pro-preview", - capabilities: ["image", "video", "audio"], + audio: { + models: [ + { + provider: "google", + model: "gemini-3.1-pro-preview", + capabilities: ["image", "video", "audio"], + }, + ], }, - ], + video: { + models: [ + { + provider: "google", + model: "gemini-3.1-pro-preview", + capabilities: ["image", "video", "audio"], + }, + ], + }, + }, }, - }, - }, -} -``` + } + ``` + + ## Status 输出 -当媒体理解运行时,`/status` 会包含一行简短摘要: +当媒体理解运行时,`/status` 会包含一条简短摘要行: ``` 📎 Media: image ok (openai/gpt-5.4) · audio skipped (maxBytes) ``` -这会显示按能力划分的结果,以及适用时所选的提供商/模型。 +这会显示按能力划分的结果,以及在适用时所选的 provider/模型。 ## 说明 -- 理解是**尽力而为**的。错误不会阻止回复。 +- 理解功能是**尽力而为**的。错误不会阻塞回复。 - 即使理解功能被禁用,附件仍会传递给模型。 -- 使用 `scope` 来限制理解运行的位置(例如仅在私信中)。 +- 使用 `scope` 可以限制理解功能的运行范围(例如仅在私信中)。 -## 相关文档 +## 相关内容 - [配置](/zh-CN/gateway/configuration) - [图像与媒体支持](/zh-CN/nodes/images) diff --git a/docs/zh-CN/plugins/manifest.md b/docs/zh-CN/plugins/manifest.md index e90280653..1e3d0e38a 100644 --- a/docs/zh-CN/plugins/manifest.md +++ b/docs/zh-CN/plugins/manifest.md @@ -1,53 +1,53 @@ --- read_when: - 你正在构建一个 OpenClaw 插件 - - 你需要发布插件配置 schema,或调试插件校验错误 -summary: 插件清单 + JSON schema 要求(严格配置校验) + - 你需要发布一个插件配置 schema,或调试插件验证错误 +summary: 插件清单 + JSON schema 要求(严格配置验证) title: 插件清单 x-i18n: - generated_at: "2026-04-26T06:59:33Z" + generated_at: "2026-04-26T08:13:19Z" model: gpt-5.4 provider: openai - source_hash: 12eae5bd8e3ca47e7d2fb2202cd32abba8d79136d14dd5e38f0aac1c30c02e35 + source_hash: b86920ad774c5ef4ace7b546ef44e5b087a8ca694dea622ddb440258ffff4237 source_path: plugins/manifest.md workflow: 15 --- 此页面仅适用于**原生 OpenClaw 插件清单**。 -有关兼容的 bundle 布局,请参见 [插件 bundles](/zh-CN/plugins/bundles)。 +关于兼容的 bundle 布局,请参阅 [Plugin bundles](/zh-CN/plugins/bundles)。 兼容的 bundle 格式使用不同的清单文件: - Codex bundle:`.codex-plugin/plugin.json` -- Claude bundle:`.claude-plugin/plugin.json`,或不带清单的默认 Claude 组件布局 +- Claude bundle:`.claude-plugin/plugin.json` 或不带清单的默认 Claude 组件布局 - Cursor bundle:`.cursor-plugin/plugin.json` -OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的 `openclaw.plugin.json` schema 对它们进行校验。 +OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的 `openclaw.plugin.json` schema 对它们进行验证。 -对于兼容 bundle,当其布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据、声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值,以及受支持的 hook packs。 +对于兼容 bundle,当其布局符合 OpenClaw 运行时预期时,OpenClaw 目前会读取 bundle 元数据、已声明的 skill 根目录、Claude 命令根目录、Claude bundle 的 `settings.json` 默认值、Claude bundle 的 LSP 默认值,以及受支持的 hook 包。 -每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码**的情况下校验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。 +每个原生 OpenClaw 插件都**必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码的情况下**验证配置。缺失或无效的清单会被视为插件错误,并阻止配置验证。 -请参阅完整的插件系统指南:[插件](/zh-CN/tools/plugin)。 -关于原生能力模型和当前外部兼容性指导,请参见: +请参阅完整的插件系统指南:[Plugins](/zh-CN/tools/plugin)。 +关于原生能力模型和当前外部兼容性指南,请参阅: [能力模型](/zh-CN/plugins/architecture#public-capability-model)。 ## 此文件的作用 -`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下面的所有内容都必须足够轻量,以便无需启动插件运行时即可检查。 +`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。以下所有内容都必须足够轻量,能够在不启动插件运行时的情况下进行检查。 -**请将它用于:** +**用于:** -- 插件标识、配置校验,以及配置 UI 提示 +- 插件标识、配置验证,以及配置 UI 提示 - 认证、新手引导和设置元数据(别名、自动启用、provider 环境变量、认证选项) -- 控制平面界面的激活提示 -- 简写模型家族归属 +- control-plane 表面的激活提示 +- 简写的模型家族归属 - 静态能力归属快照(`contracts`) -- 供共享 `openclaw qa` 主机检查的 QA 运行器元数据 -- 合并到目录和校验界面中的渠道专用配置元数据 +- 共享 `openclaw qa` 宿主可检查的 QA 运行器元数据 +- 合并到目录和验证表面的渠道专用配置元数据 -**不要将它用于:**注册运行时行为、声明代码入口点,或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。 +**不要用于:** 注册运行时行为、声明代码入口点,或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。 ## 最小示例 @@ -131,64 +131,64 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的 | ------------------------------------ | -------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | 是 | `string` | 规范插件 id。这是在 `plugins.entries.` 中使用的 id。 | | `configSchema` | 是 | `object` | 此插件配置的内联 JSON Schema。 | -| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或将其设为任何非 `true` 的值,以保持插件默认禁用。 | -| `legacyPluginIds` | 否 | `string[]` | 会归一化为此规范插件 id 的旧版 id。 | +| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或设置为任何非 `true` 的值,以使该插件默认保持禁用。 | +| `legacyPluginIds` | 否 | `string[]` | 会规范化为此规范插件 id 的旧版 id。 | | `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些 provider id 时,应自动启用此插件。 | -| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的排他性插件类型。 | -| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于发现和配置校验。 | +| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明由 `plugins.slots.*` 使用的独占插件类型。 | +| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于发现和配置验证。 | | `providers` | 否 | `string[]` | 由此插件拥有的 provider id。 | -| `providerDiscoveryEntry` | 否 | `string` | 轻量级 provider 发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、限定于清单范围的 provider 目录元数据。 | +| `providerDiscoveryEntry` | 否 | `string` | 轻量级 provider 发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、作用域限定于清单的 provider 目录元数据。 | | `modelSupport` | 否 | `object` | 由清单拥有的简写模型家族元数据,用于在运行时之前自动加载插件。 | -| `modelCatalog` | 否 | `object` | 由此插件拥有的 provider 的声明式模型目录元数据。这是未来只读列表、新手引导、模型选择器、别名和抑制功能的控制平面契约,且无需加载插件运行时。 | -| `providerEndpoints` | 否 | `object[]` | 由清单拥有的端点 host/baseUrl 元数据,用于核心系统必须在 provider 运行时加载前分类的 provider 路由。 | +| `modelCatalog` | 否 | `object` | 由声明式方式定义的、适用于此插件所拥有 providers 的模型目录元数据。这是未来只读列表、onboarding、模型选择器、别名和抑制功能在不加载插件运行时情况下使用的 control-plane 合约。 | +| `providerEndpoints` | 否 | `object[]` | 由清单拥有的 endpoint 主机 / `baseUrl` 元数据,用于核心在 provider 运行时加载之前必须分类的 provider 路由。 | | `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 | -| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用,在运行时加载前进行冷模型发现期间,应探测其由插件拥有的合成认证 hook。 | +| `syntheticAuthRefs` | 否 | `string[]` | 在运行时加载之前、冷启动模型发现期间,应探测其插件自有 synthetic auth hook 的 provider 或 CLI 后端引用。 | | `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API key 值,表示非机密的本地、OAuth 或环境凭证状态。 | -| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称,在运行时加载前应生成具备插件感知能力的配置和 CLI 诊断信息。 | -| `providerAuthEnvVars` | 否 | `Record` | 已弃用的兼容性环境变量元数据,用于 provider 认证/Status 查询。对于新插件,优先使用 `setup.providers[].envVars`;在弃用窗口期间,OpenClaw 仍会读取此字段。 | -| `providerAuthAliases` | 否 | `Record` | 应复用另一个 provider id 进行认证查询的 provider id,例如共享基础 provider API key 和认证配置文件的编码 provider。 | -| `channelEnvVars` | 否 | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量级渠道环境变量元数据。将其用于通用启动/配置辅助工具需要识别的、由环境变量驱动的渠道设置或认证界面。 | -| `providerAuthChoices` | 否 | `object[]` | 面向新手引导选择器、首选 provider 解析和简单 CLI 标志接线的轻量级认证选项元数据。 | -| `activation` | 否 | `object` | 面向 provider、命令、渠道、路由和能力触发加载的轻量级激活规划器元数据。仅为元数据;实际行为仍由插件运行时拥有。 | -| `setup` | 否 | `object` | 轻量级设置/新手引导描述符,供发现和设置界面在不加载插件运行时的情况下检查。 | -| `qaRunners` | 否 | `object[]` | 在插件运行时加载前,由共享 `openclaw qa` 主机使用的轻量级 QA 运行器描述符。 | -| `contracts` | 否 | `object` | 外部认证 hooks、语音、实时转写、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属的静态内置能力快照。 | -| `mediaUnderstandingProviderMetadata` | 否 | `Record` | 为 `contracts.mediaUnderstandingProviders` 中声明的 provider id 提供的轻量级媒体理解默认值。 | -| `channelConfigs` | 否 | `Record` | 由清单拥有的渠道配置元数据,在运行时加载前合并到发现和校验界面中。 | +| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称,应在运行时加载之前生成带有插件感知能力的配置和 CLI 诊断信息。 | +| `providerAuthEnvVars` | 否 | `Record` | 用于 provider 认证 / Status 查找的已弃用兼容性环境变量元数据。对于新插件,优先使用 `setup.providers[].envVars`;OpenClaw 在弃用窗口期内仍会读取此字段。 | +| `providerAuthAliases` | 否 | `Record` | 应复用另一个 provider id 进行认证查找的 provider id,例如与基础 provider 共享 API key 和认证配置文件的编码 provider。 | +| `channelEnvVars` | 否 | `Record` | OpenClaw 可在不加载插件代码的情况下检查的轻量级渠道环境变量元数据。将其用于通用启动 / 配置辅助工具应可见的、由环境变量驱动的渠道设置或认证表面。 | +| `providerAuthChoices` | 否 | `object[]` | 用于 onboarding 选择器、首选 provider 解析和简单 CLI 标志接线的轻量级认证选项元数据。 | +| `activation` | 否 | `object` | 轻量级激活规划器元数据,用于由 provider、命令、渠道、路由和能力触发的加载。仅包含元数据;插件运行时仍拥有实际行为。 | +| `setup` | 否 | `object` | 轻量级设置 / onboarding 描述符,供发现和设置表面在不加载插件运行时的情况下检查。 | +| `qaRunners` | 否 | `object[]` | 由共享 `openclaw qa` 宿主在插件运行时加载前使用的轻量级 QA 运行器描述符。 | +| `contracts` | 否 | `object` | 静态内置能力快照,涵盖外部认证 hook、speech、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属。 | +| `mediaUnderstandingProviderMetadata` | 否 | `Record` | 为 `contracts.mediaUnderstandingProviders` 中声明的 provider id 提供的轻量级媒体理解默认元数据。 | +| `channelConfigs` | 否 | `Record` | 由清单拥有的渠道配置元数据,在运行时加载前合并到发现和验证表面中。 | | `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 | | `name` | 否 | `string` | 人类可读的插件名称。 | -| `description` | 否 | `string` | 显示在插件界面中的简短摘要。 | +| `description` | 否 | `string` | 显示在插件表面中的简短摘要。 | | `version` | 否 | `string` | 信息性插件版本。 | | `uiHints` | 否 | `Record` | 配置字段的 UI 标签、占位符和敏感性提示。 | ## `providerAuthChoices` 参考 -每个 `providerAuthChoices` 条目都描述一个新手引导或认证选项。 -OpenClaw 会在 provider 运行时加载前读取它。 +每个 `providerAuthChoices` 条目描述一个 onboarding 或认证选项。 +OpenClaw 会在 provider 运行时加载之前读取这些内容。 provider 设置列表会使用这些清单选项、从描述符派生的设置选项,以及安装目录元数据,而无需加载 provider 运行时。 | 字段 | 必填 | 类型 | 含义 | | --------------------- | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `provider` | 是 | `string` | 此选项所属的 provider id。 | -| `method` | 是 | `string` | 要分派到的认证方法 id。 | -| `choiceId` | 是 | `string` | 供新手引导和 CLI 流程使用的稳定认证选项 id。 | -| `choiceLabel` | 否 | `string` | 面向用户的标签。如省略,OpenClaw 会回退到 `choiceId`。 | -| `choiceHint` | 否 | `string` | 选择器中显示的简短帮助文本。 | -| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,数值越小排序越靠前。 | -| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏此选项,但仍允许手动通过 CLI 选择。 | +| `method` | 是 | `string` | 要分发到的认证方法 id。 | +| `choiceId` | 是 | `string` | onboarding 和 CLI 流程使用的稳定认证选项 id。 | +| `choiceLabel` | 否 | `string` | 面向用户的标签。如果省略,OpenClaw 会回退到 `choiceId`。 | +| `choiceHint` | 否 | `string` | 选择器的简短辅助文本。 | +| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,值越小排序越靠前。 | +| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏该选项,但仍允许手动通过 CLI 选择。 | | `deprecatedChoiceIds` | 否 | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 | -| `groupId` | 否 | `string` | 用于对相关选项分组的可选分组 id。 | +| `groupId` | 否 | `string` | 用于对相关选项进行分组的可选分组 id。 | | `groupLabel` | 否 | `string` | 该分组面向用户的标签。 | -| `groupHint` | 否 | `string` | 该分组的简短帮助文本。 | +| `groupHint` | 否 | `string` | 该分组的简短辅助文本。 | | `optionKey` | 否 | `string` | 用于简单单标志认证流程的内部选项键。 | | `cliFlag` | 否 | `string` | CLI 标志名称,例如 `--openrouter-api-key`。 | | `cliOption` | 否 | `string` | 完整的 CLI 选项形式,例如 `--openrouter-api-key `。 | -| `cliDescription` | 否 | `string` | 用于 CLI 帮助中的说明。 | -| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如省略,默认值为 `["text-inference"]`。 | +| `cliDescription` | 否 | `string` | CLI 帮助中使用的说明。 | +| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些 onboarding 表面中。如果省略,默认值为 `["text-inference"]`。 | ## `commandAliases` 参考 -当插件拥有一个运行时命令名称,而用户可能会误将其放入 `plugins.allow`,或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用此元数据在不导入插件运行时代码的情况下提供诊断信息。 +当插件拥有某个运行时命令名称,而用户可能会误将其放入 `plugins.allow`,或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用此元数据在不导入插件运行时代码的情况下提供诊断信息。 ```json { @@ -206,17 +206,18 @@ provider 设置列表会使用这些清单选项、从描述符派生的设置 | ------------ | -------- | ----------------- | ----------------------------------------------------------------------- | | `name` | 是 | `string` | 属于此插件的命令名称。 | | `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根 CLI 命令。 | -| `cliCommand` | 否 | `string` | 若存在,用于 CLI 操作时建议的相关根 CLI 命令。 | +| `cliCommand` | 否 | `string` | 若存在,可为 CLI 操作建议的相关根 CLI 命令。 | ## `activation` 参考 -当插件可以低成本地声明哪些控制平面事件应将其包含到激活/加载计划中时,请使用 `activation`。 +当插件可以以低成本声明哪些 control-plane 事件应将其纳入激活 / 加载计划时,请使用 `activation`。 -此块是规划器元数据,而不是生命周期 API。它不会注册运行时行为,不会替代 `register(...)`,也不保证插件代码已经执行。激活规划器使用这些字段在回退到现有清单归属元数据(如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和 hooks)之前缩小候选插件范围。 +此代码块是规划器元数据,而不是生命周期 API。它不会注册运行时行为,不会替代 `register(...)`,也不保证插件代码已经执行。激活规划器会使用这些字段缩小候选插件范围,然后再回退到现有的清单归属元数据,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和 hooks。 -优先使用已经描述归属关系的最窄元数据。当 `providers`、`channels`、`commandAliases`、设置描述符或 `contracts` 已能表达这种关系时,请使用这些字段。对于无法通过这些归属字段表示的额外规划器提示,再使用 `activation`。 +优先使用已经描述归属关系的最窄元数据。如果这些字段已经能够表达这种关系,请使用 `providers`、`channels`、`commandAliases`、设置描述符或 `contracts`。当这些归属字段无法表示所需关系时,再使用 `activation` 作为额外的规划器提示。 +对于 `claude-cli`、`codex-cli` 或 `google-gemini-cli` 之类的 CLI 运行时别名,请使用顶层 `cliBackends`;`activation.onAgentHarnesses` 仅适用于尚无归属字段的嵌入式 Agent harness id。 -此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时/插件入口点。当前使用方会在更广泛的插件加载前将其作为缩小范围的提示,因此缺少激活元数据通常只会带来性能成本;在旧版清单归属回退仍存在时,不应影响正确性。 +此代码块仅包含元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。当前使用方会在更广泛的插件加载之前将其作为缩小范围的提示,因此缺少激活元数据通常只会带来性能损耗;在旧版清单归属回退仍然存在的情况下,它不应影响正确性。 ```json { @@ -231,28 +232,28 @@ provider 设置列表会使用这些清单选项、从描述符派生的设置 ``` | 字段 | 必填 | 类型 | 含义 | -| ---------------- | -------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -| `onProviders` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的 provider id。 | -| `onCommands` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的命令 id。 | -| `onChannels` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的渠道 id。 | -| `onRoutes` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的路由类型。 | -| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划中使用的宽泛能力提示。若可能,优先使用更窄的字段。 | +| ------------------ | -------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `onProviders` | 否 | `string[]` | 在激活 / 加载计划中应包含此插件的 provider id。 | +| `onAgentHarnesses` | 否 | `string[]` | 在激活 / 加载计划中应包含此插件的嵌入式 Agent harness 运行时 id。对于 CLI 后端别名,请使用顶层 `cliBackends`。 | +| `onCommands` | 否 | `string[]` | 在激活 / 加载计划中应包含此插件的命令 id。 | +| `onChannels` | 否 | `string[]` | 在激活 / 加载计划中应包含此插件的渠道 id。 | +| `onRoutes` | 否 | `string[]` | 在激活 / 加载计划中应包含此插件的路由类型。 | +| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | control-plane 激活规划使用的宽泛能力提示。可能的话,优先使用更窄的字段。 | 当前在线使用方: - 由命令触发的 CLI 规划会回退到旧版 `commandAliases[].cliCommand` 或 `commandAliases[].name` -- 由渠道触发的设置/渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]` - 归属关系 -- 由 provider 触发的设置/运行时规划在缺少显式 provider - 激活元数据时,会回退到旧版 `providers[]` 和顶层 `cliBackends[]` - 归属关系 +- 智能体运行时启动规划对嵌入式 harness 使用 `activation.onAgentHarnesses`,对 CLI 运行时别名使用顶层 `cliBackends[]` +- 由渠道触发的设置 / 渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]` 归属 +- 由 provider 触发的设置 / 运行时规划在缺少显式 provider 激活元数据时,会回退到旧版 + `providers[]` 和顶层 `cliBackends[]` 归属 -规划器诊断可以区分显式激活提示和清单归属回退。例如,`activation-command-hint` 表示匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示规划器改用了 `commandAliases` 归属关系。这些原因标签用于宿主诊断和测试;插件作者应继续声明最能描述归属关系的元数据。 +规划器诊断可以区分显式激活提示和清单归属回退。例如,`activation-command-hint` 表示匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示规划器改为使用 `commandAliases` 归属。这些原因标签用于宿主诊断和测试;插件作者应继续声明最能描述归属关系的元数据。 ## `qaRunners` 参考 -当插件在共享 `openclaw qa` 根命令下贡献一个或多个传输运行器时,请使用 `qaRunners`。保持此元数据轻量且静态;实际 CLI 注册仍由插件运行时通过一个轻量级的 `runtime-api.ts` 接口负责,该接口导出 `qaRunnerCliRegistrations`。 +当插件在共享 `openclaw qa` 根命令下贡献一个或多个传输运行器时,请使用 `qaRunners`。请保持此元数据轻量且静态;实际的 CLI 注册仍由插件运行时通过导出 `qaRunnerCliRegistrations` 的轻量级 `runtime-api.ts` 表面来负责。 ```json { @@ -268,11 +269,11 @@ provider 设置列表会使用这些清单选项、从描述符派生的设置 | 字段 | 必填 | 类型 | 含义 | | ------------- | -------- | -------- | ------------------------------------------------------------------ | | `commandName` | 是 | `string` | 挂载在 `openclaw qa` 下的子命令,例如 `matrix`。 | -| `description` | 否 | `string` | 当共享宿主需要一个存根命令时使用的回退帮助文本。 | +| `description` | 否 | `string` | 当共享宿主需要一个占位命令时使用的回退帮助文本。 | ## `setup` 参考 -当设置和新手引导界面需要在运行时加载前获取由插件拥有的轻量级元数据时,请使用 `setup`。 +当设置和 onboarding 表面需要在运行时加载前读取由插件拥有的低成本元数据时,请使用 `setup`。 ```json { @@ -291,40 +292,40 @@ provider 设置列表会使用这些清单选项、从描述符派生的设置 } ``` -顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是用于控制平面/设置流程的、仅元数据的设置专用描述符界面。 +顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是面向 control-plane / 设置流程的、应保持仅元数据形式的 setup 专用描述符表面。 -存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现中首选的描述符优先查询界面。如果描述符仅用于缩小候选插件范围,而设置仍需要更丰富的设置期运行时 hooks,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。 +存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现的首选“descriptor-first”查找表面。如果描述符只能缩小候选插件范围,而设置仍需要更丰富的设置期运行时 hooks,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。 -OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和环境变量查询。`providerAuthEnvVars` 在弃用窗口期间仍通过兼容适配器受支持,但仍在使用它的非内置插件会收到清单诊断。新插件应将设置/Status 环境变量元数据放在 `setup.providers[].envVars` 上。 +OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和环境变量查找。`providerAuthEnvVars` 在弃用窗口期内仍通过兼容适配器受支持,但仍在使用它的非内置插件会收到清单诊断。新插件应将设置 / Status 环境变量元数据放在 `setup.providers[].envVars` 上。 -当没有可用的设置入口,或 `setup.requiresRuntime: false` 声明设置运行时并非必需时,OpenClaw 还可以根据 `setup.providers[].authMethods` 派生简单的设置选项。对于自定义标签、CLI 标志、新手引导范围和助手元数据,显式的 `providerAuthChoices` 条目仍是首选。 +当没有 setup 条目可用,或 `setup.requiresRuntime: false` 声明设置运行时不是必需时,OpenClaw 还可以从 `setup.providers[].authMethods` 派生简单的设置选项。对于自定义标签、CLI 标志、onboarding 范围和助手元数据,显式的 `providerAuthChoices` 条目仍然是首选。 -只有当这些描述符足以支撑设置界面时,才将 `requiresRuntime: false` 设为 `false`。OpenClaw 将显式 `false` 视为仅描述符契约,并且不会为设置查询执行 `setup-api` 或 `openclaw.setupEntry`。如果一个仅描述符插件仍提供了这些设置运行时入口之一,OpenClaw 会报告一条附加诊断,并继续忽略它。省略 `requiresRuntime` 会保留旧版回退行为,以免那些添加了描述符但未设置该标志的现有插件发生中断。 +仅当这些描述符对于设置表面已经足够时,才设置 `requiresRuntime: false`。OpenClaw 将显式的 `false` 视为仅描述符合约,并且不会为设置查找执行 `setup-api` 或 `openclaw.setupEntry`。如果仅描述符插件仍然提供了这些设置运行时入口之一,OpenClaw 会报告一条附加诊断,并继续忽略它。省略 `requiresRuntime` 会保留旧版回退行为,这样那些在未设置该标志的情况下添加了描述符的现有插件就不会出问题。 -由于设置查询可能会执行由插件拥有的 `setup-api` 代码,归一化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值在已发现插件之间必须保持唯一。归属关系不明确时会采用失败关闭,而不是根据发现顺序选择一个赢家。 +由于设置查找可能会执行由插件拥有的 `setup-api` 代码,规范化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值必须在已发现插件之间保持唯一。归属不明确时会采用失败即关闭的方式,而不是根据发现顺序挑选一个“胜出者”。 -当设置运行时确实执行时,如果 `setup-api` 注册了清单描述符未声明的 provider 或 CLI 后端,或者某个描述符没有匹配的运行时注册,设置注册表诊断会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。 +当设置运行时确实执行时,如果 `setup-api` 注册了清单描述符未声明的 provider 或 CLI 后端,或者某个描述符没有对应的运行时注册,设置注册表诊断就会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。 ### `setup.providers` 参考 | 字段 | 必填 | 类型 | 含义 | | ------------- | -------- | ---------- | ------------------------------------------------------------------------------------ | -| `id` | 是 | `string` | 在设置或新手引导期间公开的 provider id。保持归一化 id 在全局范围内唯一。 | -| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置/认证方法 id。 | -| `envVars` | 否 | `string[]` | 通用设置/Status 界面可在插件运行时加载前检查的环境变量。 | +| `id` | 是 | `string` | 在设置或 onboarding 期间公开的 provider id。保持规范化 id 在全局范围内唯一。 | +| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置 / 认证方法 id。 | +| `envVars` | 否 | `string[]` | 通用设置 / Status 表面可在插件运行时加载前检查的环境变量。 | ### `setup` 字段 | 字段 | 必填 | 类型 | 含义 | | ------------------ | -------- | ---------- | --------------------------------------------------------------------------------------------------- | -| `providers` | 否 | `object[]` | 在设置和新手引导期间公开的 provider 设置描述符。 | -| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查询的设置期后端 id。保持归一化 id 在全局范围内唯一。 | -| `configMigrations` | 否 | `string[]` | 由此插件设置界面拥有的配置迁移 id。 | -| `requiresRuntime` | 否 | `boolean` | 在描述符查询之后,设置是否仍需要执行 `setup-api`。 | +| `providers` | 否 | `object[]` | 在设置和 onboarding 期间公开的 provider 设置描述符。 | +| `cliBackends` | 否 | `string[]` | 用于 descriptor-first 设置查找的设置期后端 id。保持规范化 id 在全局范围内唯一。 | +| `configMigrations` | 否 | `string[]` | 由此插件的设置表面拥有的配置迁移 id。 | +| `requiresRuntime` | 否 | `boolean` | 在描述符查找之后,设置是否仍需要执行 `setup-api`。 | ## `uiHints` 参考 -`uiHints` 是一个从配置字段名映射到小型渲染提示的映射表。 +`uiHints` 是从配置字段名称到小型渲染提示的映射。 ```json { @@ -344,15 +345,15 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和 | 字段 | 类型 | 含义 | | ------------- | ---------- | --------------------------------------- | | `label` | `string` | 面向用户的字段标签。 | -| `help` | `string` | 简短帮助文本。 | -| `tags` | `string[]` | 可选的 UI 标签。 | -| `advanced` | `boolean` | 将该字段标记为高级选项。 | -| `sensitive` | `boolean` | 将该字段标记为机密或敏感。 | +| `help` | `string` | 简短辅助文本。 | +| `tags` | `string[]` | 可选 UI 标签。 | +| `advanced` | `boolean` | 将该字段标记为高级项。 | +| `sensitive` | `boolean` | 将该字段标记为机密或敏感项。 | | `placeholder` | `string` | 表单输入的占位文本。 | ## `contracts` 参考 -仅当需要 OpenClaw 在不导入插件运行时的情况下读取静态能力归属元数据时,才使用 `contracts`。 +仅将 `contracts` 用于 OpenClaw 能够在不导入插件运行时的情况下读取的静态能力归属元数据。 ```json { @@ -380,8 +381,8 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和 | `embeddedExtensionFactories` | `string[]` | Codex app-server 扩展工厂 id,目前为 `codex-app-server`。 | | `agentToolResultMiddleware` | `string[]` | 内置插件可为其注册工具结果中间件的运行时 id。 | | `externalAuthProviders` | `string[]` | 此插件拥有其外部认证配置文件 hook 的 provider id。 | -| `speechProviders` | `string[]` | 此插件拥有的语音 provider id。 | -| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转写 provider id。 | +| `speechProviders` | `string[]` | 此插件拥有的 speech provider id。 | +| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转录 provider id。 | | `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音 provider id。 | | `memoryEmbeddingProviders` | `string[]` | 此插件拥有的 Memory 嵌入 provider id。 | | `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解 provider id。 | @@ -389,17 +390,17 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和 | `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成 provider id。 | | `webFetchProviders` | `string[]` | 此插件拥有的网页抓取 provider id。 | | `webSearchProviders` | `string[]` | 此插件拥有的网页搜索 provider id。 | -| `tools` | `string[]` | 此插件为内置契约检查所拥有的智能体工具名称。 | +| `tools` | `string[]` | 此插件拥有的智能体工具名称,用于内置合约检查。 | -`contracts.embeddedExtensionFactories` 保留给仅用于内置 Codex app-server 的扩展工厂。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并通过 `api.registerAgentToolResultMiddleware(...)` 进行注册。外部插件不能注册工具结果中间件,因为该接口可以在模型看到输出前重写高信任度的工具输出。 +`contracts.embeddedExtensionFactories` 保留用于内置、仅限 Codex app-server 的扩展工厂。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并改为使用 `api.registerAgentToolResultMiddleware(...)` 进行注册。外部插件不能注册工具结果中间件,因为该接缝可以在模型看到之前重写高信任度工具输出。 -实现 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明该字段的插件仍会通过一个已弃用的兼容性回退路径运行,但该回退更慢,并将在迁移窗口结束后移除。 +实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明该字段的插件仍会通过已弃用的兼容性回退运行,但这种回退更慢,并将在迁移窗口结束后移除。 -内置 Memory 嵌入 provider 应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 之类的内置适配器。独立 CLI 路径使用此清单契约在完整 Gateway 网关运行时注册 provider 之前,仅加载其所属插件。 +内置 Memory 嵌入 providers 应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 之类的内置适配器。独立 CLI 路径会使用此清单合约,仅在完整 Gateway 网关运行时完成 provider 注册之前加载其所属插件。 ## `mediaUnderstandingProviderMetadata` 参考 -当媒体理解 provider 具有默认模型、自动认证回退优先级,或 generic core helpers 在运行时加载前需要的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。其中的键也必须在 `contracts.mediaUnderstandingProviders` 中声明。 +当媒体理解 provider 具有默认模型、自动认证回退优先级,或通用核心辅助工具在运行时加载前所需的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。其键也必须在 `contracts.mediaUnderstandingProviders` 中声明。 ```json { @@ -426,25 +427,25 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和 | 字段 | 类型 | 含义 | | ---------------------- | ----------------------------------- | ---------------------------------------------------------------------------- | -| `capabilities` | `("image" \| "audio" \| "video")[]` | 此 provider 公开的媒体能力。 | -| `defaultModels` | `Record` | 当配置未指定模型时使用的能力到模型默认值映射。 | -| `autoPriority` | `Record` | 基于凭证的自动 provider 回退中,数值越小排序越靠前。 | +| `capabilities` | `("image" \| "audio" \| "video")[]` | 该 provider 公开的媒体能力。 | +| `defaultModels` | `Record` | 当配置未指定模型时使用的“能力到模型”默认值。 | +| `autoPriority` | `Record` | 对于基于凭证的自动 provider 回退,数字越小排序越靠前。 | | `nativeDocumentInputs` | `"pdf"[]` | 该 provider 支持的原生文档输入。 | ## `channelConfigs` 参考 -当渠道插件需要在运行时加载前获取轻量级配置元数据时,请使用 `channelConfigs`。当没有可用的设置入口,或 `setup.requiresRuntime: false` 声明设置运行时并非必需时,只读渠道设置/Status 发现可以直接使用这些元数据来处理已配置的外部渠道。 +当渠道插件在运行时加载前需要低成本配置元数据时,请使用 `channelConfigs`。当没有可用的 setup 条目,或 `setup.requiresRuntime: false` 声明设置运行时不是必需时,只读的渠道设置 / Status 发现可以直接使用这些元数据来处理已配置的外部渠道。 -`channelConfigs` 是插件清单元数据,而不是新的顶层用户配置区段。用户仍然在 `channels.` 下配置渠道实例。OpenClaw 会读取清单元数据,以在插件运行时代码执行前判断哪个插件拥有该已配置渠道。 +`channelConfigs` 是插件清单元数据,而不是新的顶层用户配置部分。用户仍然在 `channels.` 下配置渠道实例。OpenClaw 读取清单元数据,以便在插件运行时代码执行之前决定哪个插件拥有该已配置渠道。 对于渠道插件,`configSchema` 和 `channelConfigs` 描述的是不同路径: -- `configSchema` 校验 `plugins.entries..config` -- `channelConfigs..schema` 校验 `channels.` +- `configSchema` 验证 `plugins.entries..config` +- `channelConfigs..schema` 验证 `channels.` -声明了 `channels[]` 的非内置插件也应声明匹配的 `channelConfigs` 条目。若缺少这些条目,OpenClaw 仍可加载插件,但冷路径配置 schema、设置以及 Control UI 界面在插件运行时执行前将无法知道该渠道拥有的选项结构。 +声明了 `channels[]` 的非内置插件,也应声明匹配的 `channelConfigs` 条目。没有这些条目时,OpenClaw 仍然可以加载该插件,但冷路径配置 schema、设置和 Control UI 表面在插件运行时执行之前无法获知渠道自有选项的形状。 -`channelConfigs..commands.nativeCommandsAutoEnabled` 和 `nativeSkillsAutoEnabled` 可以为运行时加载前执行的命令配置检查声明静态 `auto` 默认值。内置渠道也可以通过 `package.json#openclaw.channel.commands` 连同其其他由包拥有的渠道目录元数据一起发布相同的默认值。 +`channelConfigs..commands.nativeCommandsAutoEnabled` 和 `nativeSkillsAutoEnabled` 可以为在渠道运行时加载前执行的命令配置检查声明静态 `auto` 默认值。内置渠道也可以通过 `package.json#openclaw.channel.commands` 发布相同的默认值,并与其其他由包拥有的渠道目录元数据一起提供。 ```json { @@ -480,15 +481,15 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和 | 字段 | 类型 | 含义 | | ------------- | ------------------------ | ----------------------------------------------------------------------------------------- | | `schema` | `object` | `channels.` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 | -| `uiHints` | `Record` | 该渠道配置区段的可选 UI 标签/占位符/敏感性提示。 | -| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 | -| `description` | `string` | 用于检查和目录界面的简短渠道说明。 | +| `uiHints` | `Record` | 该渠道配置部分的可选 UI 标签 / 占位符 / 敏感性提示。 | +| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查表面中的渠道标签。 | +| `description` | `string` | 用于检查和目录表面的简短渠道描述。 | | `commands` | `object` | 用于运行时前配置检查的静态原生命令和原生 Skills 自动默认值。 | -| `preferOver` | `string[]` | 此渠道在选择界面中应优先于的旧版或较低优先级插件 id。 | +| `preferOver` | `string[]` | 在选择表面中,此渠道应优先于的旧版或较低优先级插件 id。 | ### 替换另一个渠道插件 -当你的插件是某个渠道 id 的首选拥有者,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见情况包括插件 id 已重命名、独立插件取代内置插件,或为保持配置兼容性而沿用相同渠道 id 的维护分支。 +当你的插件是某个渠道 id 的首选归属方,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见情况包括:插件 id 已重命名、某个独立插件取代了内置插件,或者某个维护中的分支为了保持配置兼容性而沿用相同的渠道 id。 ```json { @@ -509,13 +510,13 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和 } ``` -当配置了 `channels.chat` 时,OpenClaw 会同时考虑渠道 id 和首选插件 id。如果较低优先级的插件之所以被选中,仅仅是因为它是内置插件或默认启用,OpenClaw 会在生效的运行时配置中禁用它,以便由单个插件拥有该渠道及其工具。显式的用户选择仍然优先:如果用户明确启用了这两个插件,OpenClaw 会保留该选择,并报告重复渠道/工具诊断,而不是静默更改请求的插件集合。 +当配置了 `channels.chat` 时,OpenClaw 会同时考虑渠道 id 和首选插件 id。如果低优先级插件之所以被选中,仅仅是因为它是内置的或默认启用的,OpenClaw 就会在有效运行时配置中将其禁用,以便由一个插件拥有该渠道及其工具。显式用户选择仍然优先:如果用户显式启用了这两个插件,OpenClaw 会保留该选择,并报告重复渠道 / 工具诊断,而不是静默更改所请求的插件集。 -将 `preferOver` 的范围限定为确实能够提供同一渠道的插件 id。它不是通用优先级字段,也不会重命名用户配置键。 +请将 `preferOver` 的范围限定在确实能够提供同一渠道的插件 id 上。它不是一个通用优先级字段,也不会重命名用户配置键。 ## `modelSupport` 参考 -当 OpenClaw 应在插件运行时加载前,根据诸如 `gpt-5.5` 或 `claude-sonnet-4.6` 这样的简写模型 id 推断你的 provider 插件时,请使用 `modelSupport`。 +当 OpenClaw 应在插件运行时加载之前,根据 `gpt-5.5` 或 `claude-sonnet-4.6` 之类的简写模型 id 推断你的 provider 插件时,请使用 `modelSupport`。 ```json { @@ -526,23 +527,23 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和 } ``` -OpenClaw 应用以下优先级: +OpenClaw 按以下优先级处理: - 显式 `provider/model` 引用使用所属 `providers` 清单元数据 - `modelPatterns` 优先于 `modelPrefixes` - 如果一个非内置插件和一个内置插件都匹配,则非内置插件胜出 -- 剩余歧义会被忽略,直到用户或配置指定某个 provider +- 对于其余歧义,在用户或配置指定 provider 之前会被忽略 字段: | 字段 | 类型 | 含义 | | --------------- | ---------- | ------------------------------------------------------------------------------- | -| `modelPrefixes` | `string[]` | 对简写模型 id 使用 `startsWith` 进行匹配的前缀。 | -| `modelPatterns` | `string[]` | 在移除配置文件后缀后,对简写模型 id 进行匹配的正则表达式源码。 | +| `modelPrefixes` | `string[]` | 使用 `startsWith` 与简写模型 id 匹配的前缀。 | +| `modelPatterns` | `string[]` | 在移除配置文件后缀后,与简写模型 id 匹配的正则表达式源码。 | ## `modelCatalog` 参考 -当 OpenClaw 需要在加载插件运行时之前了解 provider 模型元数据时,请使用 `modelCatalog`。这是固定目录行、provider 别名、抑制规则和发现模式的清单拥有来源。运行时刷新仍属于 provider 运行时代码,但清单会告知核心系统何时需要运行时。 +当 OpenClaw 应在加载插件运行时之前了解 provider 模型元数据时,请使用 `modelCatalog`。这是固定目录行、provider 别名、抑制规则和发现模式的清单归属来源。运行时刷新仍属于 provider 运行时代码,但清单会告知核心何时需要运行时。 ```json { @@ -595,112 +596,113 @@ OpenClaw 应用以下优先级: | 字段 | 类型 | 含义 | | -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| `providers` | `Record` | 由此插件拥有的 provider id 的目录行。键也应出现在顶层 `providers` 中。 | -| `aliases` | `Record` | 为目录或抑制规划而应解析到某个所属 provider 的 provider 别名。 | -| `suppressions` | `object[]` | 由于特定 provider 原因而被此插件抑制的、来自其他来源的模型行。 | -| `discovery` | `Record` | provider 目录是否可从清单元数据读取、可刷新到缓存,或需要运行时。 | +| `providers` | `Record` | 此插件拥有的 provider id 的目录行。键也应出现在顶层 `providers` 中。 | +| `aliases` | `Record` | 应解析为某个已拥有 provider 的 provider 别名,用于目录或抑制规划。 | +| `suppressions` | `object[]` | 此插件因 provider 专用原因而抑制的、来自其他来源的模型行。 | +| `discovery` | `Record` | 该 provider 目录是可从清单元数据读取、可刷新到缓存,还是需要运行时。 | provider 字段: | 字段 | 类型 | 含义 | | --------- | ------------------------ | ----------------------------------------------------------------- | -| `baseUrl` | `string` | 此 provider 目录中模型的可选默认 base URL。 | +| `baseUrl` | `string` | 此 provider 目录中模型的可选默认 `baseUrl`。 | | `api` | `ModelApi` | 此 provider 目录中模型的可选默认 API 适配器。 | -| `headers` | `Record` | 适用于此 provider 目录的可选静态 headers。 | +| `headers` | `Record` | 适用于此 provider 目录的可选静态头。 | | `models` | `object[]` | 必需的模型行。没有 `id` 的行会被忽略。 | 模型字段: | 字段 | 类型 | 含义 | | --------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- | -| `id` | `string` | provider 本地模型 id,不带 `provider/` 前缀。 | +| `id` | `string` | provider 本地模型 id,不含 `provider/` 前缀。 | | `name` | `string` | 可选显示名称。 | | `api` | `ModelApi` | 可选的逐模型 API 覆盖。 | -| `baseUrl` | `string` | 可选的逐模型 base URL 覆盖。 | -| `headers` | `Record` | 可选的逐模型静态 headers。 | -| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 模型可接受的模态。 | -| `reasoning` | `boolean` | 模型是否公开 reasoning 行为。 | +| `baseUrl` | `string` | 可选的逐模型 `baseUrl` 覆盖。 | +| `headers` | `Record` | 可选的逐模型静态头。 | +| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 该模型接受的模态。 | +| `reasoning` | `boolean` | 该模型是否公开推理行为。 | | `contextWindow` | `number` | provider 原生上下文窗口。 | -| `contextTokens` | `number` | 当与 `contextWindow` 不同时的可选有效运行时上下文上限。 | +| `contextTokens` | `number` | 当与 `contextWindow` 不同时,可选的有效运行时上下文上限。 | | `maxTokens` | `number` | 已知时的最大输出 token 数。 | | `cost` | `object` | 可选的每百万 token 美元定价,包括可选的 `tieredPricing`。 | | `compat` | `object` | 与 OpenClaw 模型配置兼容性匹配的可选兼容性标志。 | | `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该行完全不应出现时才使用 suppress。 | -| `statusReason` | `string` | 与非可用状态一起显示的可选原因。 | -| `replaces` | `string[]` | 此模型取代的较旧 provider 本地模型 id。 | -| `replacedBy` | `string` | 用于已弃用行的替代 provider 本地模型 id。 | -| `tags` | `string[]` | 供选择器和过滤器使用的稳定标签。 | +| `statusReason` | `string` | 与不可用状态一同显示的可选原因。 | +| `replaces` | `string[]` | 此模型所取代的旧 provider 本地模型 id。 | +| `replacedBy` | `string` | 已弃用行的替代 provider 本地模型 id。 | +| `tags` | `string[]` | 供选择器和筛选器使用的稳定标签。 | -不要将仅运行时数据放入 `modelCatalog`。如果某个 provider 需要账户状态、API 请求或本地进程发现来获知完整模型集合,请在 `discovery` 中将该 provider 声明为 `refreshable` 或 `runtime`。 +不要将仅运行时数据放入 `modelCatalog`。如果某个 provider 需要账户状态、API 请求或本地进程发现才能得知完整模型集,请在 `discovery` 中将该 provider 声明为 `refreshable` 或 `runtime`。 ### OpenClaw Provider Index -OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,用于其插件可能尚未安装的 provider。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。Provider Index 是未来可安装 provider 和安装前模型选择界面在 provider 插件尚未安装时会使用的内部回退契约。 +OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,用于那些插件可能尚未安装的 providers。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。Provider Index 是未来可安装 provider 和安装前模型选择器表面在 provider 插件尚未安装时所使用的内部回退合约。 目录权威顺序: 1. 用户配置。 2. 已安装插件清单中的 `modelCatalog`。 -3. 来自显式刷新的模型目录缓存。 +3. 通过显式刷新获得的模型目录缓存。 4. OpenClaw Provider Index 预览行。 -Provider Index 不得包含机密、启用状态、运行时 hooks 或实时的账户专属模型数据。其预览目录使用与插件清单相同的 `modelCatalog` provider 行结构,但除非像 `api`、`baseUrl`、定价或兼容性标志等运行时适配器字段被有意与已安装插件清单保持一致,否则应仅限于稳定的显示元数据。具有实时 `/models` 发现能力的 provider 应通过显式模型目录缓存路径写入刷新后的行,而不是让常规列表或新手引导去调用 provider API。 +Provider Index 不得包含机密、启用状态、运行时 hooks,或实时的账户专属模型数据。其预览目录使用与插件清单相同的 `modelCatalog` provider 行形状,但除非有意与已安装插件清单保持一致,否则应限制为稳定显示元数据,而不要包含诸如 `api`、`baseUrl`、定价或兼容性标志之类的运行时适配器字段。对于带有实时 `/models` 发现的 providers,应通过显式模型目录缓存路径写入刷新后的行,而不是让常规列表或 onboarding 去调用 provider API。 -Provider Index 条目也可以携带适用于其插件已移出核心或尚未安装的 provider 的可安装插件元数据。此元数据沿用渠道目录模式:包名、npm 安装规格、预期完整性以及轻量级认证选项标签,足以展示一个可安装的设置选项。一旦插件安装完成,其清单即成为权威来源,Provider Index 中该 provider 的条目将被忽略。 +对于那些其插件已移出核心或尚未安装的 providers,Provider Index 条目也可以携带可安装插件元数据。此元数据遵循与渠道目录相同的模式:包名、npm 安装规范、预期完整性以及轻量级认证选项标签,足以展示一个可安装的设置选项。一旦插件安装完成,其清单即成为权威,Provider Index 中对应 provider 的条目将被忽略。 -旧版顶层能力键已弃用。使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载已不再将这些顶层字段视为能力归属。 +旧版顶层能力键已弃用。使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载不再将这些顶层字段视为能力归属。 -## 清单与 `package.json` 的区别 +## Manifest 与 `package.json` -这两个文件承担不同的职责: +这两个文件承担不同职责: | 文件 | 用途 | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -| `openclaw.plugin.json` | 插件代码运行前必须存在的发现、配置校验、认证选项元数据和 UI 提示 | -| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 区块 | +| `openclaw.plugin.json` | 发现、配置验证、认证选项元数据,以及在插件代码运行前必须存在的 UI 提示 | +| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 代码块 | -如果你不确定某条元数据应放在哪里,请使用这条规则: +如果你不确定某段元数据应放在哪里,请使用以下规则: -- 如果 OpenClaw 必须在加载插件代码前知道它,就把它放在 `openclaw.plugin.json` -- 如果它与打包、入口文件或 npm 安装行为有关,就把它放在 `package.json` +- 如果 OpenClaw 必须在加载插件代码之前知道它,就将其放在 `openclaw.plugin.json` 中 +- 如果它与打包、入口文件或 npm 安装行为有关,就将其放在 `package.json` 中 -### 会影响发现的 `package.json` 字段 +### 影响发现的 `package.json` 字段 -某些运行时前插件元数据有意放在 `package.json` 的 `openclaw` 区块下,而不是 `openclaw.plugin.json` 中。 +一些运行时前插件元数据有意放在 `package.json` 的 `openclaw` 代码块下,而不是 `openclaw.plugin.json` 中。 重要示例: | 字段 | 含义 | | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `openclaw.extensions` | 声明原生插件入口点。必须保持在插件包目录内。 | -| `openclaw.runtimeExtensions` | 为已安装包声明已构建的 JavaScript 运行时入口点。必须保持在插件包目录内。 | -| `openclaw.setupEntry` | 在新手引导、延迟渠道启动和只读渠道 Status/SecretRef 发现期间使用的轻量级仅设置入口点。必须保持在插件包目录内。 | -| `openclaw.runtimeSetupEntry` | 为已安装包声明已构建的 JavaScript 设置入口点。必须保持在插件包目录内。 | +| `openclaw.extensions` | 声明原生插件入口点。必须保留在插件包目录内。 | +| `openclaw.runtimeExtensions` | 为已安装包声明构建后的 JavaScript 运行时入口点。必须保留在插件包目录内。 | +| `openclaw.setupEntry` | 轻量级、仅设置用的入口点,用于 onboarding、延迟渠道启动以及只读的渠道 Status / SecretRef 发现。必须保留在插件包目录内。 | +| `openclaw.runtimeSetupEntry` | 为已安装包声明构建后的 JavaScript 设置入口点。必须保留在插件包目录内。 | | `openclaw.channel` | 轻量级渠道目录元数据,例如标签、文档路径、别名和选择文案。 | -| `openclaw.channel.commands` | 在渠道运行时加载前,供配置、审计和命令列表界面使用的静态原生命令和原生 Skills 自动默认元数据。 | +| `openclaw.channel.commands` | 在渠道运行时加载前,由配置、审计和命令列表表面使用的静态原生命令和原生 Skills 自动默认元数据。 | | `openclaw.channel.configuredState` | 轻量级已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经存在仅环境变量的设置?”。 | -| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经有任何内容登录?”。 | -| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 内置和外部发布插件的安装/更新提示。 | -| `openclaw.install.defaultChoice` | 当有多个安装来源可用时的首选安装路径。 | +| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经有任何登录状态?”。 | +| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 面向内置和外部发布插件的安装 / 更新提示。 | +| `openclaw.install.defaultChoice` | 当存在多个安装来源时的首选安装路径。 | | `openclaw.install.minHostVersion` | 最低支持的 OpenClaw 宿主版本,使用类似 `>=2026.3.22` 的 semver 下限。 | | `openclaw.install.expectedIntegrity` | 预期的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验获取到的工件。 | -| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一个范围受限的内置插件重新安装恢复路径。 | -| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置的渠道界面,再加载完整渠道插件。 | +| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一条范围很窄的内置插件重新安装恢复路径。 | +| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间于完整渠道插件之前加载仅设置用的渠道表面。 | -清单元数据决定了在运行时加载前,新手引导中会出现哪些 provider/渠道/设置选项。`package.json#openclaw.install` 则告诉新手引导,当用户选择这些选项之一时,应如何获取或启用该插件。不要将安装提示移入 `openclaw.plugin.json`。 +清单元数据决定在运行时加载前,onboarding 中会出现哪些 provider / 渠道 / 设置选项。`package.json#openclaw.install` 则告诉 onboarding:当用户选择这些选项之一时,应如何获取或启用该插件。不要将安装提示移入 `openclaw.plugin.json`。 -`openclaw.install.minHostVersion` 会在安装和清单注册表加载期间强制执行。无效值会被拒绝;对较旧宿主而言虽较新但有效的值,则会在旧宿主上跳过该插件。 +`openclaw.install.minHostVersion` 会在安装期间和清单注册表加载期间强制执行。无效值会被拒绝;较新的但有效的值会使该插件在旧宿主上被跳过。 精确的 npm 版本固定已经存在于 `npmSpec` 中,例如 -`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录条目应将精确规格与 `expectedIntegrity` 配对使用,以便在获取到的 npm 工件不再匹配固定发布版本时,更新流程采用失败关闭。出于兼容性考虑,交互式新手引导仍会提供受信任注册表的 npm 规格,包括裸包名和 dist-tags。目录诊断可以区分精确、浮动、带完整性固定、缺少完整性、包名不匹配以及无效默认选项来源等情况。它们还会在存在 `expectedIntegrity` 但没有可用于固定的有效 npm 来源时发出警告。当存在 `expectedIntegrity` 时,安装/更新流程会强制执行它;当省略该字段时,注册表解析结果会被记录,但不带完整性固定。 +`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录条目应将精确 spec 与 `expectedIntegrity` 配对使用,这样如果获取到的 npm 工件不再匹配已固定的发布版本,更新流程就会以失败即关闭的方式终止。为了兼容性,交互式 onboarding 仍会提供受信任注册表的 npm spec,包括裸包名和 dist-tag。目录诊断可以区分精确、浮动、带完整性固定、缺少完整性、包名不匹配以及无效默认选项来源。它们还会在存在 `expectedIntegrity` 但没有可用于固定的有效 npm 来源时发出警告。 +当存在 `expectedIntegrity` 时,安装 / 更新流程会强制执行它;当省略时,注册表解析会被记录下来,但不会附带完整性固定。 -当 Status、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`。该设置入口应公开渠道元数据,以及可安全用于设置的配置、Status 和 secrets 适配器;将网络客户端、网关监听器和传输运行时保留在主扩展入口点中。 +当 Status、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`。该设置入口应公开渠道元数据以及适用于设置的配置、Status 和密钥适配器;请将网络客户端、Gateway 网关监听器和传输运行时保留在主扩展入口点中。 -运行时入口点字段不会覆盖针对源码入口点字段的包边界检查。例如,`openclaw.runtimeExtensions` 不能让一个越界的 `openclaw.extensions` 路径变得可加载。 +运行时入口点字段不会覆盖源入口点字段的包边界检查。例如,`openclaw.runtimeExtensions` 不能让一个越界的 `openclaw.extensions` 路径变得可加载。 -`openclaw.install.allowInvalidConfigRecovery` 的范围是有意收窄的。它不会让任意损坏配置都变得可安装。当前它仅允许安装流程从特定的陈旧内置插件升级失败中恢复,例如缺失的内置插件路径,或该同一内置插件对应的陈旧 `channels.` 条目。无关的配置错误仍会阻止安装,并将操作人员引导到 `openclaw doctor --fix`。 +`openclaw.install.allowInvalidConfigRecovery` 的设计范围是有意收窄的。它不会让任意损坏的配置都能被安装。当前它仅允许安装流程从特定的陈旧内置插件升级失败中恢复,例如缺失的内置插件路径,或该同一内置插件的陈旧 `channels.` 条目。无关的配置错误仍会阻止安装,并将操作员引导至 `openclaw doctor --fix`。 -`openclaw.channel.persistedAuthState` 是用于一个微型检查器模块的包元数据: +`openclaw.channel.persistedAuthState` 是一个微型检查器模块的包元数据: ```json { @@ -716,9 +718,9 @@ Provider Index 条目也可以携带适用于其插件已移出核心或尚未 } ``` -当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前进行一次轻量级的是/否认证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 来路由它。 +当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前执行轻量级的“是 / 否”认证探测时,请使用它。目标导出应是一个仅读取持久化状态的小函数;不要通过完整渠道运行时 barrel 来路由它。 -`openclaw.channel.configuredState` 对轻量级仅环境变量已配置检查采用相同结构: +`openclaw.channel.configuredState` 对轻量级的仅环境变量已配置检查采用相同结构: ```json { @@ -734,54 +736,52 @@ Provider Index 条目也可以携带适用于其插件已移出核心或尚未 } ``` -当某个渠道可以仅根据环境变量或其他微小的非运行时输入来回答已配置状态时,请使用它。如果检查需要完整配置解析或真实渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` hook 中。 +当某个渠道可以根据环境变量或其他微型的非运行时输入来判断已配置状态时,请使用它。如果检查需要完整配置解析或真实的渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` hook 中。 ## 发现优先级(重复插件 id) -OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区、显式配置选定路径)。如果两个发现结果共享相同的 `id`,则只保留**优先级最高**的清单;较低优先级的重复项会被丢弃,而不是与其并行加载。 +OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区、配置中显式选择的路径)。如果两个发现结果共享同一个 `id`,则只保留**优先级最高**的清单;较低优先级的重复项会被丢弃,而不是与其并列加载。 -优先级从高到低: +优先级从高到低如下: 1. **配置选定** —— 在 `plugins.entries.` 中显式固定的路径 -2. **内置** —— 随 OpenClaw 一同发布的插件 +2. **内置** —— 随 OpenClaw 一同提供的插件 3. **全局安装** —— 安装到全局 OpenClaw 插件根目录中的插件 4. **工作区** —— 相对于当前工作区发现的插件 影响: -- 放在工作区中的某个内置插件的分支版本或陈旧副本,不会遮蔽内置构建版本。 -- 若要真正用本地插件覆盖内置插件,请通过 `plugins.entries.` 固定它,使其依靠优先级取胜,而不是依赖工作区发现。 -- 被丢弃的重复项会被记录日志,以便 Doctor 和启动诊断能够指向被舍弃的副本。 +- 位于工作区中的某个内置插件的分支或陈旧副本,不会遮蔽内置构建版本。 +- 若要真正用本地插件覆盖内置插件,请通过 `plugins.entries.` 固定它,使其按优先级获胜,而不是依赖工作区发现。 +- 被丢弃的重复项会被记录,以便 Doctor 和启动诊断能够指向被舍弃的副本。 ## JSON Schema 要求 - **每个插件都必须提供一个 JSON Schema**,即使它不接受任何配置。 -- 可以接受空 schema(例如 `{ "type": "object", "additionalProperties": false }`)。 -- Schema 会在配置读写时校验,而不是在运行时校验。 +- 空 schema 是可接受的(例如,`{ "type": "object", "additionalProperties": false }`)。 +- schema 在配置读取 / 写入时验证,而不是在运行时验证。 -## 校验行为 +## 验证行为 - 未知的 `channels.*` 键是**错误**,除非该渠道 id 由某个插件清单声明。 - `plugins.entries.`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*` - 必须引用**可发现**的插件 id。未知 id 属于**错误**。 -- 如果某个插件已安装,但其清单或 schema 损坏或缺失, - 校验将失败,Doctor 会报告该插件错误。 -- 如果插件配置存在,但插件处于**禁用**状态,配置会被保留,并且 - Doctor + 日志中会显示一条**警告**。 + 必须引用**可发现的**插件 id。未知 id 是**错误**。 +- 如果某个插件已安装,但其清单或 schema 缺失或损坏,验证会失败,Doctor 会报告该插件错误。 +- 如果插件配置存在,但插件被**禁用**,该配置会被保留,并且在 Doctor + 日志中显示**警告**。 -有关完整的 `plugins.*` schema,请参见[配置参考](/zh-CN/gateway/configuration)。 +完整的 `plugins.*` schema 请参阅 [配置参考](/zh-CN/gateway/configuration)。 -## 注意事项 +## 说明 -- 清单对于**原生 OpenClaw 插件**是**必需的**,包括本地文件系统加载。运行时仍会单独加载插件模块;清单仅用于发现 + 校验。 -- 原生清单使用 JSON5 解析,因此注释、尾随逗号和未加引号的键都被接受,只要最终值仍然是一个对象。 -- 清单加载器只会读取文档中记录的清单字段。避免使用自定义顶层键。 -- 当插件不需要时,可以省略 `channels`、`providers`、`cliBackends` 和 `skills`。 -- `providerDiscoveryEntry` 必须保持轻量,不应导入宽泛的运行时代码;应将其用于静态 provider 目录元数据或狭义发现描述符,而不是请求时执行。 -- 排他性插件类型通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory`,`kind: "context-engine"` 通过 `plugins.slots.contextEngine`(默认 `legacy`)。 -- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` 和 `channelEnvVars`)仅为声明式。Status、审计、cron 投递校验和其他只读界面在将某个环境变量视为已配置之前,仍会应用插件信任和生效激活策略。 -- 有关需要 provider 代码的运行时向导元数据,请参见[Provider 运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。 -- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器 allowlist 要求(例如 pnpm `allow-build-scripts` + `pnpm rebuild `)。 +- 对于**原生 OpenClaw 插件**,清单是**必需的**,包括本地文件系统加载。运行时仍会单独加载插件模块;清单仅用于发现 + 验证。 +- 原生清单使用 JSON5 解析,因此接受注释、尾随逗号和未加引号的键,只要最终值仍然是对象即可。 +- 清单加载器只会读取已记录的清单字段。避免使用自定义顶层键。 +- 当插件不需要它们时,`channels`、`providers`、`cliBackends` 和 `skills` 都可以省略。 +- `providerDiscoveryEntry` 必须保持轻量,不应导入宽泛的运行时代码;请将其用于静态 provider 目录元数据或狭窄的发现描述符,而不是请求时执行。 +- 独占插件类型通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory`,`kind: "context-engine"` 通过 `plugins.slots.contextEngine`(默认 `legacy`)。 +- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` 和 `channelEnvVars`)仅为声明式。Status、审计、cron 投递验证和其他只读表面在将某个环境变量视为已配置之前,仍会应用插件信任和有效激活策略。 +- 关于需要 provider 代码的运行时向导元数据,请参阅 [Provider runtime hooks](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。 +- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器允许列表要求(例如 pnpm `allow-build-scripts` + `pnpm rebuild `)。 ## 相关内容 diff --git a/docs/zh-CN/plugins/sdk-setup.md b/docs/zh-CN/plugins/sdk-setup.md index b9d50459e..371431d58 100644 --- a/docs/zh-CN/plugins/sdk-setup.md +++ b/docs/zh-CN/plugins/sdk-setup.md @@ -2,111 +2,120 @@ read_when: - 你正在为一个插件添加设置向导 - 你需要理解 `setup-entry.ts` 与 `index.ts` 的区别 - - 你正在定义插件配置模式或 `package.json` 中的 OpenClaw 元数据 -sidebarTitle: Setup and Config -summary: 设置向导、`setup-entry.ts`、配置模式,以及 `package.json` 元数据 + - 你正在定义插件配置 schema 或 `package.json` 中的 OpenClaw 元数据 +sidebarTitle: Setup and config +summary: 设置向导、`setup-entry.ts`、配置 schema,以及 `package.json` 元数据 title: 插件设置和配置 x-i18n: - generated_at: "2026-04-25T21:53:54Z" + generated_at: "2026-04-26T08:13:20Z" model: gpt-5.4 provider: openai - source_hash: 66c44a08db7c83ec981c92fadea54482e5d85af3cc3c4621916e3e0b1223d9a6 + source_hash: d5ac08bf43af0a15e4ed797eb3a732d15f24f67304efbac7d74e6f24ffe67af9 source_path: plugins/sdk-setup.md workflow: 15 --- -用于插件打包(`package.json` 元数据)、清单(`openclaw.plugin.json`)、设置入口和配置模式的参考。 +插件打包(`package.json` 元数据)、清单(`openclaw.plugin.json`)、设置入口和配置 schema 的参考文档。 - **在找操作演练?** 操作指南会在上下文中介绍打包: - [渠道插件](/zh-CN/plugins/sdk-channel-plugins#step-1-package-and-manifest) 和 - [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-1-package-and-manifest)。 +**想看操作演练?** 操作指南会在具体上下文中讲解打包流程:[渠道插件](/zh-CN/plugins/sdk-channel-plugins#step-1-package-and-manifest) 和 [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-1-package-and-manifest)。 ## 包元数据 -你的 `package.json` 需要有一个 `openclaw` 字段,用来告诉插件系统你的插件提供了什么: +你的 `package.json` 需要一个 `openclaw` 字段,用来告诉插件系统你的插件提供了什么: -**渠道插件:** - -```json -{ - "name": "@myorg/openclaw-my-channel", - "version": "1.0.0", - "type": "module", - "openclaw": { - "extensions": ["./index.ts"], - "setupEntry": "./setup-entry.ts", - "channel": { - "id": "my-channel", - "label": "My Channel", - "blurb": "Short description of the channel." + + + ```json + { + "name": "@myorg/openclaw-my-channel", + "version": "1.0.0", + "type": "module", + "openclaw": { + "extensions": ["./index.ts"], + "setupEntry": "./setup-entry.ts", + "channel": { + "id": "my-channel", + "label": "My Channel", + "blurb": "渠道的简短说明。" + } + } } - } -} -``` - -**提供商插件 / ClawHub 发布基线:** - -```json openclaw-clawhub-package.json -{ - "name": "@myorg/openclaw-my-plugin", - "version": "1.0.0", - "type": "module", - "openclaw": { - "extensions": ["./index.ts"], - "compat": { - "pluginApi": ">=2026.3.24-beta.2", - "minGatewayVersion": "2026.3.24-beta.2" - }, - "build": { - "openclawVersion": "2026.3.24-beta.2", - "pluginSdkVersion": "2026.3.24-beta.2" + ``` + + + ```json openclaw-clawhub-package.json + { + "name": "@myorg/openclaw-my-plugin", + "version": "1.0.0", + "type": "module", + "openclaw": { + "extensions": ["./index.ts"], + "compat": { + "pluginApi": ">=2026.3.24-beta.2", + "minGatewayVersion": "2026.3.24-beta.2" + }, + "build": { + "openclawVersion": "2026.3.24-beta.2", + "pluginSdkVersion": "2026.3.24-beta.2" + } + } } - } -} -``` + ``` + + -如果你要在 ClawHub 上对外发布插件,这些 `compat` 和 `build` -字段是必需的。规范的发布代码片段位于 -`docs/snippets/plugin-publish/`。 + +如果你要在 ClawHub 上对外发布插件,则必须提供这些 `compat` 和 `build` 字段。规范的发布片段位于 `docs/snippets/plugin-publish/`。 + ### `openclaw` 字段 -| 字段 | 类型 | 说明 | -| ------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------- | -| `extensions` | `string[]` | 入口点文件(相对于包根目录) | -| `setupEntry` | `string` | 仅用于设置的轻量入口(可选) | -| `channel` | `object` | 用于设置、选择器、快速开始和 Status 界面的渠道目录元数据 | -| `providers` | `string[]` | 此插件注册的提供商 id | -| `install` | `object` | 安装提示:`npmSpec`、`localPath`、`defaultChoice`、`minHostVersion`、`expectedIntegrity`、`allowInvalidConfigRecovery` | -| `startup` | `object` | 启动行为标志 | + + 入口点文件(相对于包根目录)。 + + + 仅用于设置的轻量入口(可选)。 + + + 用于设置、选择器、快速开始和状态界面的渠道目录元数据。 + + + 该插件注册的提供商 id。 + + + 安装提示:`npmSpec`、`localPath`、`defaultChoice`、`minHostVersion`、`expectedIntegrity`、`allowInvalidConfigRecovery`。 + + + 启动行为标记。 + ### `openclaw.channel` -`openclaw.channel` 是轻量级包元数据,用于在加载运行时之前支持渠道发现和设置界面。 +`openclaw.channel` 是轻量级包元数据,用于在运行时加载前支持渠道发现和设置界面。 -| 字段 | 类型 | 含义 | -| -------------------------------------- | ---------- | ------------------------------------------------- | -| `id` | `string` | 规范渠道 id。 | -| `label` | `string` | 主要渠道标签。 | -| `selectionLabel` | `string` | 当需要与 `label` 不同时,在选择器/设置中显示的标签。 | -| `detailLabel` | `string` | 用于更丰富渠道目录和 Status 界面的次级详情标签。 | -| `docsPath` | `string` | 用于设置和选择链接的文档路径。 | -| `docsLabel` | `string` | 当需要与渠道 id 不同时,用作文档链接的覆盖标签。 | -| `blurb` | `string` | 简短的新手引导/目录说明。 | -| `order` | `number` | 在渠道目录中的排序顺序。 | -| `aliases` | `string[]` | 用于渠道选择的额外查找别名。 | -| `preferOver` | `string[]` | 此渠道应优先于的低优先级插件/渠道 id。 | -| `systemImage` | `string` | 可选图标/system-image 名称,用于渠道 UI 目录。 | -| `selectionDocsPrefix` | `string` | 在选择界面中显示于文档链接前的前缀文本。 | -| `selectionDocsOmitLabel` | `boolean` | 在选择文案中直接显示文档路径,而不是带标签的文档链接。 | -| `selectionExtras` | `string[]` | 附加在选择文案中的额外短文本。 | -| `markdownCapable` | `boolean` | 将该渠道标记为支持 Markdown,用于出站格式决策。 | -| `exposure` | `object` | 用于设置、已配置列表和文档界面的渠道可见性控制。 | -| `quickstartAllowFrom` | `boolean` | 让此渠道加入标准快速开始 `allowFrom` 设置流程。 | -| `forceAccountBinding` | `boolean` | 即使只存在一个账户,也要求显式账户绑定。 | -| `preferSessionLookupForAnnounceTarget` | `boolean` | 解析此渠道的 announce 目标时,优先使用会话查找。 | +| 字段 | 类型 | 含义 | +| -------------------------------------- | ---------- | ------------------------------------------------------------------------------ | +| `id` | `string` | 规范渠道 id。 | +| `label` | `string` | 主要渠道标签。 | +| `selectionLabel` | `string` | 当需要区别于 `label` 时,在选择器/设置中显示的标签。 | +| `detailLabel` | `string` | 用于更丰富渠道目录和状态界面的次级详细标签。 | +| `docsPath` | `string` | 用于设置和选择链接的文档路径。 | +| `docsLabel` | `string` | 当文档链接标签需要区别于渠道 id 时使用的覆盖标签。 | +| `blurb` | `string` | 简短的新手引导/目录说明。 | +| `order` | `number` | 在渠道目录中的排序顺序。 | +| `aliases` | `string[]` | 渠道选择的额外查找别名。 | +| `preferOver` | `string[]` | 该渠道应优先于哪些较低优先级的插件/渠道 id。 | +| `systemImage` | `string` | 渠道 UI 目录中可选的图标/系统图像名称。 | +| `selectionDocsPrefix` | `string` | 在选择界面中显示于文档链接前的前缀文本。 | +| `selectionDocsOmitLabel` | `boolean` | 在选择文案中直接显示文档路径,而不是显示带标签的文档链接。 | +| `selectionExtras` | `string[]` | 附加到选择文案中的额外简短字符串。 | +| `markdownCapable` | `boolean` | 将该渠道标记为支持 Markdown,以便进行出站格式化决策。 | +| `exposure` | `object` | 控制渠道在设置、已配置列表和文档界面中的可见性。 | +| `quickstartAllowFrom` | `boolean` | 允许该渠道使用标准快速开始 `allowFrom` 设置流程。 | +| `forceAccountBinding` | `boolean` | 即使只存在一个账号,也要求显式账号绑定。 | +| `preferSessionLookupForAnnounceTarget` | `boolean` | 为该渠道解析通知目标时,优先使用会话查找。 | 示例: @@ -116,15 +125,15 @@ x-i18n: "channel": { "id": "my-channel", "label": "My Channel", - "selectionLabel": "My Channel (self-hosted)", + "selectionLabel": "My Channel(自托管)", "detailLabel": "My Channel Bot", "docsPath": "/channels/my-channel", "docsLabel": "my-channel", - "blurb": "Webhook-based self-hosted chat integration.", + "blurb": "基于 Webhook 的自托管聊天集成。", "order": 80, "aliases": ["mc"], "preferOver": ["my-channel-legacy"], - "selectionDocsPrefix": "Guide:", + "selectionDocsPrefix": "指南:", "selectionExtras": ["Markdown"], "markdownCapable": true, "exposure": { @@ -140,51 +149,58 @@ x-i18n: `exposure` 支持: -- `configured`:在已配置/Status 风格的列表界面中包含该渠道 +- `configured`:在已配置/状态类列表界面中包含该渠道 - `setup`:在交互式设置/配置选择器中包含该渠道 -- `docs`:在文档/导航界面中将该渠道标记为面向公众 +- `docs`:将该渠道标记为在文档/导航界面中对外可见 -`showConfigured` 和 `showInSetup` 仍然作为旧版别名受支持。优先使用 -`exposure`。 + +`showConfigured` 和 `showInSetup` 仍然作为旧版别名受支持。推荐优先使用 `exposure`。 + ### `openclaw.install` `openclaw.install` 是包元数据,不是清单元数据。 -| 字段 | 类型 | 含义 | -| ---------------------------- | -------------------- | ------------------------------------------------------------------------------ | -| `npmSpec` | `string` | 用于安装/更新流程的规范 npm 说明。 | -| `localPath` | `string` | 本地开发或内置安装路径。 | -| `defaultChoice` | `"npm"` \| `"local"` | 当两者都可用时,首选的安装来源。 | -| `minHostVersion` | `string` | 支持的最低 OpenClaw 版本,格式为 `>=x.y.z`。 | -| `expectedIntegrity` | `string` | 预期的 npm dist 完整性字符串,通常为 `sha512-...`,用于固定版本安装。 | -| `allowInvalidConfigRecovery` | `boolean` | 允许内置插件的重新安装流程从特定的陈旧配置故障中恢复。 | +| 字段 | 类型 | 含义 | +| ---------------------------- | -------------------- | -------------------------------------------------------------------------------- | +| `npmSpec` | `string` | 用于安装/更新流程的规范 npm spec。 | +| `localPath` | `string` | 本地开发或内置安装路径。 | +| `defaultChoice` | `"npm"` \| `"local"` | 当两者都可用时,优先使用的安装来源。 | +| `minHostVersion` | `string` | 最低支持的 OpenClaw 版本,格式为 `>=x.y.z`。 | +| `expectedIntegrity` | `string` | 预期的 npm dist 完整性字符串,通常为 `sha512-...`,用于固定版本安装。 | +| `allowInvalidConfigRecovery` | `boolean` | 允许内置插件的重新安装流程从特定的过期配置错误中恢复。 | -交互式新手引导也会使用 `openclaw.install` 来支持按需安装界面。如果你的插件在运行时加载之前公开提供商认证选项,或公开渠道设置/目录元数据,新手引导可以显示该选项,提示选择 npm 或本地安装,安装或启用插件,然后继续所选流程。npm 新手引导选项需要带有注册表 `npmSpec` 的受信任目录元数据;精确版本和 `expectedIntegrity` 是可选的固定项。如果存在 -`expectedIntegrity`,安装/更新流程会强制校验它。把“显示什么”的元数据放在 `openclaw.plugin.json` 中,把“如何安装它”的元数据放在 `package.json` 中。 + + + 交互式新手引导也会使用 `openclaw.install` 来支持按需安装界面。如果你的插件在运行时加载前就公开提供商认证选项,或提供渠道设置/目录元数据,新手引导就可以显示该选项,提示选择 npm 还是本地安装,安装或启用插件,然后继续所选流程。npm 新手引导选项需要可信的目录元数据以及注册表中的 `npmSpec`;精确版本和 `expectedIntegrity` 是可选的固定项。如果提供了 `expectedIntegrity`,安装/更新流程会强制校验它。请将“显示什么”的元数据放在 `openclaw.plugin.json` 中,将“如何安装”的元数据放在 `package.json` 中。 + + + 如果设置了 `minHostVersion`,安装和清单注册表加载都会强制执行它。较旧的宿主会跳过该插件;无效的版本字符串会被拒绝。 + + + 对于固定版本的 npm 安装,请在 `npmSpec` 中保留精确版本,并添加预期的制品完整性值: -如果设置了 `minHostVersion`,安装和清单注册表加载都会强制执行它。较旧的宿主会跳过该插件;无效的版本字符串会被拒绝。 - -对于固定的 npm 安装,请在 `npmSpec` 中保留精确版本,并添加预期的制品完整性: - -```json -{ - "openclaw": { - "install": { - "npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3", - "expectedIntegrity": "sha512-REPLACE_WITH_NPM_DIST_INTEGRITY", - "defaultChoice": "npm" + ```json + { + "openclaw": { + "install": { + "npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3", + "expectedIntegrity": "sha512-REPLACE_WITH_NPM_DIST_INTEGRITY", + "defaultChoice": "npm" + } + } } - } -} -``` + ``` -`allowInvalidConfigRecovery` 不是针对损坏配置的通用绕过方式。它只用于狭窄的内置插件恢复场景,这样重新安装/设置就能修复已知的升级遗留问题,比如缺失的内置插件路径,或同一插件对应的陈旧 `channels.` -条目。如果配置因无关原因损坏,安装仍会以失败关闭,并提示操作员运行 `openclaw doctor --fix`。 + + + `allowInvalidConfigRecovery` 并不是对损坏配置的通用绕过机制。它只适用于狭窄范围内的内置插件恢复场景,使重新安装/设置能够修复已知升级遗留问题,例如缺失的内置插件路径,或同一插件对应的过期 `channels.` 条目。如果配置因无关原因损坏,安装仍会以安全关闭方式失败,并提示操作员运行 `openclaw doctor --fix`。 + + ### 延迟完整加载 -渠道插件可以通过以下方式启用延迟加载: +渠道插件可以通过以下方式选择启用延迟加载: ```json { @@ -198,33 +214,30 @@ x-i18n: } ``` -启用后,即使对于已经配置的渠道,OpenClaw 在监听前的启动阶段也只会加载 `setupEntry`。完整入口会在 Gateway 网关开始监听之后加载。 +启用后,OpenClaw 在监听前的启动阶段只会加载 `setupEntry`,即使该渠道已经配置完成也是如此。完整入口会在 Gateway 网关开始监听后再加载。 - 只有当你的 `setupEntry` 在 Gateway 网关开始监听之前就注册了所需的一切(渠道注册、HTTP 路由、Gateway 网关方法)时,才启用延迟加载。如果完整入口拥有必需的启动能力,请保留默认行为。 +只有当你的 `setupEntry` 已注册 Gateway 网关在开始监听前所需的一切内容时,才应启用延迟加载(渠道注册、HTTP 路由、Gateway 网关方法)。如果完整入口拥有启动所需的关键能力,请保持默认行为。 -如果你的设置/完整入口会注册 Gateway 网关 RPC 方法,请将它们保留在插件专用前缀下。保留的核心管理命名空间(`config.*`、 -`exec.approvals.*`、`wizard.*`、`update.*`)仍归核心所有,并始终解析到 -`operator.admin`。 +如果你的设置/完整入口会注册 Gateway 网关 RPC 方法,请将它们保留在插件专属前缀下。保留的核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍归核心所有,并始终解析为 `operator.admin`。 ## 插件清单 -每个原生插件都必须在包根目录中提供一个 `openclaw.plugin.json`。 -OpenClaw 用它在不执行插件代码的情况下验证配置。 +每个原生插件都必须在包根目录中提供一个 `openclaw.plugin.json`。OpenClaw 会用它在不执行插件代码的情况下验证配置。 ```json { "id": "my-plugin", "name": "My Plugin", - "description": "Adds My Plugin capabilities to OpenClaw", + "description": "为 OpenClaw 添加 My Plugin 功能", "configSchema": { "type": "object", "additionalProperties": false, "properties": { "webhookSecret": { "type": "string", - "description": "Webhook verification secret" + "description": "Webhook 验证密钥" } } } @@ -246,7 +259,7 @@ OpenClaw 用它在不执行插件代码的情况下验证配置。 } ``` -即使没有配置的插件也必须提供一个模式。空模式也是有效的: +即使插件没有任何配置,也必须提供一个 schema。空 schema 也是有效的: ```json { @@ -258,7 +271,7 @@ OpenClaw 用它在不执行插件代码的情况下验证配置。 } ``` -完整模式参考请参见 [插件清单](/zh-CN/plugins/manifest)。 +完整 schema 参考请参见 [插件清单](/zh-CN/plugins/manifest)。 ## ClawHub 发布 @@ -269,12 +282,13 @@ clawhub package publish your-org/your-plugin --dry-run clawhub package publish your-org/your-plugin ``` -旧版仅用于 Skills 的发布别名适用于 Skills。插件包应始终使用 -`clawhub package publish`。 + +旧版仅 Skills 的发布别名是给 Skills 使用的。插件包始终应使用 `clawhub package publish`。 + ## 设置入口 -`setup-entry.ts` 文件是 `index.ts` 的轻量替代方案,当 OpenClaw 只需要设置界面时(新手引导、配置修复、已禁用渠道检查),会加载它。 +`setup-entry.ts` 文件是 `index.ts` 的轻量替代方案,当 OpenClaw 只需要设置界面时(新手引导、配置修复、已禁用渠道检查)就会加载它。 ```typescript // setup-entry.ts @@ -284,69 +298,61 @@ import { myChannelPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(myChannelPlugin); ``` -这样可以避免在设置流程中加载重量级运行时代码(加密库、CLI 注册、后台服务)。 +这样可以避免在设置流程中加载沉重的运行时代码(加密库、CLI 注册、后台服务)。 -对于将设置安全导出保存在 sidecar 模块中的内置工作区渠道,可以使用 -`openclaw/plugin-sdk/channel-entry-contract` 中的 -`defineBundledChannelSetupEntry(...)`,而不是 -`defineSetupPluginEntry(...)`。该内置契约同样支持可选的 -`runtime` 导出,这样设置阶段的运行时接线就能保持轻量且明确。 +对于将设置安全导出保存在 sidecar 模块中的内置工作区渠道,可以使用 `openclaw/plugin-sdk/channel-entry-contract` 中的 `defineBundledChannelSetupEntry(...)`,而不是 `defineSetupPluginEntry(...)`。该内置契约也支持可选的 `runtime` 导出,从而让设置时的运行时接线保持轻量且明确。 -**OpenClaw 何时使用 `setupEntry` 而不是完整入口:** + + + - 渠道已禁用,但仍需要设置/新手引导界面。 + - 渠道已启用,但尚未配置。 + - 已启用延迟加载(`deferConfiguredChannelFullLoadUntilAfterListen`)。 + + + - 渠道插件对象(通过 `defineSetupPluginEntry`)。 + - Gateway 网关开始监听前所需的任何 HTTP 路由。 + - 启动期间所需的任何 Gateway 网关方法。 -- 渠道已禁用,但需要设置/新手引导界面 -- 渠道已启用,但尚未配置 -- 已启用延迟加载(`deferConfiguredChannelFullLoadUntilAfterListen`) + 这些启动期 Gateway 网关方法仍应避免使用保留的核心管理命名空间,例如 `config.*` 或 `update.*`。 -**`setupEntry` 必须注册的内容:** + + + - CLI 注册。 + - 后台服务。 + - 沉重的运行时导入(加密、SDK)。 + - 仅在启动后才需要的 Gateway 网关方法。 + + -- 渠道插件对象(通过 `defineSetupPluginEntry`) -- Gateway 网关监听前所需的任何 HTTP 路由 -- 启动期间需要的任何 Gateway 网关方法 +### 缩窄的设置辅助导入 -这些启动期 Gateway 网关方法仍应避免使用保留的核心管理命名空间,例如 -`config.*` 或 `update.*`。 +对于仅设置的热路径,如果你只需要设置界面的一部分,优先使用这些缩窄的设置辅助接缝,而不是更宽泛的 `plugin-sdk/setup` 总入口: -**`setupEntry` 不应包含的内容:** +| 导入路径 | 适用场景 | 关键导出 | +| ---------------------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `plugin-sdk/setup-runtime` | 在 `setupEntry` / 延迟渠道启动中仍可用的设置时运行时辅助工具 | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | +| `plugin-sdk/setup-adapter-runtime` | 具备环境感知能力的账号设置适配器 | `createEnvPatchedAccountSetupAdapter` | +| `plugin-sdk/setup-tools` | 设置/安装 CLI、归档、文档辅助工具 | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | -- CLI 注册 -- 后台服务 -- 重量级运行时导入(加密库、SDK) -- 仅在启动后才需要的 Gateway 网关方法 +当你需要完整的共享设置工具箱时,请使用更宽泛的 `plugin-sdk/setup` 接缝,其中也包括诸如 `moveSingleAccountChannelSectionToDefaultAccount(...)` 这样的配置补丁辅助工具。 -### 窄范围设置辅助导入 +这些设置补丁适配器在导入时仍然是热路径安全的。它们对内置单账号提升契约界面的查找是惰性的,因此导入 `plugin-sdk/setup-runtime` 不会在适配器真正使用前就急切加载内置契约界面发现逻辑。 -对于仅限设置的热路径,如果你只需要设置界面的一部分,优先使用窄范围的设置辅助接缝,而不是更宽泛的 `plugin-sdk/setup` 总入口: +### 渠道自有的单账号提升 -| 导入路径 | 适用场景 | 关键导出 | -| ---------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `plugin-sdk/setup-runtime` | 在 `setupEntry` / 延迟渠道启动中仍可用的设置期运行时辅助工具 | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | -| `plugin-sdk/setup-adapter-runtime` | 具备环境感知能力的账户设置适配器 | `createEnvPatchedAccountSetupAdapter` | -| `plugin-sdk/setup-tools` | 设置/安装 CLI/归档/文档辅助工具 | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | +当某个渠道从单账号顶层配置升级到 `channels..accounts.*` 时,默认的共享行为是将被提升的账号范围值移动到 `accounts.default` 中。 -当你需要完整的共享设置工具箱时,请使用更宽泛的 `plugin-sdk/setup` 接缝,其中包括配置补丁辅助工具,例如 -`moveSingleAccountChannelSectionToDefaultAccount(...)`。 +内置渠道可以通过其设置契约界面来缩窄或覆盖这一提升行为: -这些设置补丁适配器在导入时仍然对热路径安全。它们对内置单账户提升契约界面的查找是惰性的,因此导入 -`plugin-sdk/setup-runtime` 不会在适配器真正使用前急切加载内置契约界面发现逻辑。 +- `singleAccountKeysToMove`:应移动到提升后账号中的额外顶层键 +- `namedAccountPromotionKeys`:当具名账号已存在时,只有这些键会移动到提升后的账号中;共享策略/投递键会保留在渠道根部 +- `resolveSingleAccountPromotionTarget(...)`:选择哪个现有账号接收被提升的值 -### 渠道自有的单账户提升 + +Matrix 是当前的内置示例。如果恰好已存在一个具名的 Matrix 账号,或者 `defaultAccount` 指向某个现有的非规范键(例如 `Ops`),提升过程会保留该账号,而不是新建 `accounts.default` 条目。 + -当一个渠道从单账户顶层配置升级为 -`channels..accounts.*` 时,默认的共享行为是将提升后的账户作用域值移动到 -`accounts.default`。 - -内置渠道可以通过其设置契约界面缩小或覆盖这种提升行为: - -- `singleAccountKeysToMove`:应移动到提升后账户中的额外顶层键 -- `namedAccountPromotionKeys`:当已存在命名账户时,只将这些键移动到提升后的账户;共享的策略/投递键保留在渠道根部 -- `resolveSingleAccountPromotionTarget(...)`:选择哪个现有账户接收提升后的值 - -Matrix 是当前的内置示例。如果恰好已经存在一个命名的 Matrix 账户,或者 -`defaultAccount` 指向现有的非规范键(例如 `Ops`),提升会保留该账户,而不是新建一个 -`accounts.default` 条目。 - -## 配置模式 +## 配置 schema 插件配置会根据你的清单中的 JSON Schema 进行验证。用户通过以下方式配置插件: @@ -364,9 +370,9 @@ Matrix 是当前的内置示例。如果恰好已经存在一个命名的 Matrix } ``` -你的插件会在注册期间通过 `api.pluginConfig` 接收此配置。 +你的插件在注册期间会通过 `api.pluginConfig` 接收这份配置。 -对于渠道特定配置,请改用渠道配置部分: +对于渠道专属配置,请改用渠道配置部分: ```json5 { @@ -379,10 +385,9 @@ Matrix 是当前的内置示例。如果恰好已经存在一个命名的 Matrix } ``` -### 构建渠道配置模式 +### 构建渠道配置 schema -使用 `buildChannelConfigSchema` 可将一个 Zod 模式转换为插件自有配置工件所使用的 -`ChannelConfigSchema` 包装器: +使用 `buildChannelConfigSchema` 将一个 Zod schema 转换为插件自有配置制品所使用的 `ChannelConfigSchema` 包装器: ```typescript import { z } from "zod"; @@ -398,13 +403,11 @@ const accountSchema = z.object({ const configSchema = buildChannelConfigSchema(accountSchema); ``` -对于第三方插件,冷路径契约仍然是插件清单:请将生成的 JSON Schema 镜像到 -`openclaw.plugin.json#channelConfigs` 中,这样配置模式、设置和 UI 界面就能在不加载运行时代码的情况下检查 `channels.`。 +对于第三方插件,冷路径契约仍然是插件清单:请将生成的 JSON Schema 镜像到 `openclaw.plugin.json#channelConfigs` 中,这样配置 schema、设置和 UI 界面就可以在不加载运行时代码的情况下检查 `channels.`。 ## 设置向导 -渠道插件可以为 `openclaw onboard` 提供交互式设置向导。向导是 -`ChannelPlugin` 上的一个 `ChannelSetupWizard` 对象: +渠道插件可以为 `openclaw onboard` 提供交互式设置向导。该向导是 `ChannelPlugin` 上的一个 `ChannelSetupWizard` 对象: ```typescript import type { ChannelSetupWizard } from "openclaw/plugin-sdk/channel-setup"; @@ -412,19 +415,19 @@ import type { ChannelSetupWizard } from "openclaw/plugin-sdk/channel-setup"; const setupWizard: ChannelSetupWizard = { channel: "my-channel", status: { - configuredLabel: "Connected", - unconfiguredLabel: "Not configured", + configuredLabel: "已连接", + unconfiguredLabel: "未配置", resolveConfigured: ({ cfg }) => Boolean((cfg.channels as any)?.["my-channel"]?.token), }, credentials: [ { inputKey: "token", providerHint: "my-channel", - credentialLabel: "Bot token", + credentialLabel: "Bot 令牌", preferredEnvVar: "MY_CHANNEL_BOT_TOKEN", - envPrompt: "Use MY_CHANNEL_BOT_TOKEN from environment?", - keepPrompt: "Keep current token?", - inputPrompt: "Enter your bot token:", + envPrompt: "使用环境变量中的 MY_CHANNEL_BOT_TOKEN 吗?", + keepPrompt: "保留当前令牌吗?", + inputPrompt: "输入你的 Bot 令牌:", inspect: ({ cfg, accountId }) => { const token = (cfg.channels as any)?.["my-channel"]?.token; return { @@ -437,91 +440,92 @@ const setupWizard: ChannelSetupWizard = { }; ``` -`ChannelSetupWizard` 类型支持 `credentials`、`textInputs`、 -`dmPolicy`、`allowFrom`、`groupAccess`、`prepare`、`finalize` 等等。 -完整示例请参见内置插件包(例如 Discord 插件的 `src/channel.setup.ts`)。 +`ChannelSetupWizard` 类型支持 `credentials`、`textInputs`、`dmPolicy`、`allowFrom`、`groupAccess`、`prepare`、`finalize` 等等。完整示例请参见内置插件包(例如 Discord 插件中的 `src/channel.setup.ts`)。 -对于只需要标准 -`note -> prompt -> parse -> merge -> patch` 流程的私信允许列表提示,优先使用 -`openclaw/plugin-sdk/setup` 中的共享设置辅助工具: -`createPromptParsedAllowFromForAccount(...)`、 -`createTopLevelChannelParsedAllowFromPrompt(...)` 和 -`createNestedChannelParsedAllowFromPrompt(...)`。 + + + 对于只需要标准 `note -> prompt -> parse -> merge -> patch` 流程的私信允许列表提示,优先使用 `openclaw/plugin-sdk/setup` 中的共享设置辅助工具:`createPromptParsedAllowFromForAccount(...)`、`createTopLevelChannelParsedAllowFromPrompt(...)` 和 `createNestedChannelParsedAllowFromPrompt(...)`。 + + + 对于仅在标签、分数和可选额外行上存在差异的渠道设置状态块,优先使用 `openclaw/plugin-sdk/setup` 中的 `createStandardChannelSetupStatus(...)`,而不是在每个插件中手写相同的 `status` 对象。 + + + 对于只应在特定上下文中显示的可选设置界面,请使用 `openclaw/plugin-sdk/channel-setup` 中的 `createOptionalChannelSetupSurface`: -对于仅在标签、分数和可选附加行上有所不同的渠道设置 Status 区块,优先使用 -`openclaw/plugin-sdk/setup` 中的 -`createStandardChannelSetupStatus(...)`,而不要在每个插件中手工重复同样的 -`status` 对象。 + ```typescript + import { createOptionalChannelSetupSurface } from "openclaw/plugin-sdk/channel-setup"; -对于仅应在特定上下文中出现的可选设置界面,请使用 -`openclaw/plugin-sdk/channel-setup` 中的 -`createOptionalChannelSetupSurface`: + const setupSurface = createOptionalChannelSetupSurface({ + channel: "my-channel", + label: "My Channel", + npmSpec: "@myorg/openclaw-my-channel", + docsPath: "/channels/my-channel", + }); + // 返回 { setupAdapter, setupWizard } + ``` -```typescript -import { createOptionalChannelSetupSurface } from "openclaw/plugin-sdk/channel-setup"; + `plugin-sdk/channel-setup` 还公开了更底层的 `createOptionalChannelSetupAdapter(...)` 和 `createOptionalChannelSetupWizard(...)` 构建器,适用于你只需要这个可选安装界面的一半能力时。 -const setupSurface = createOptionalChannelSetupSurface({ - channel: "my-channel", - label: "My Channel", - npmSpec: "@myorg/openclaw-my-channel", - docsPath: "/channels/my-channel", -}); -// Returns { setupAdapter, setupWizard } -``` + 生成的可选适配器/向导在真实配置写入时会以安全关闭方式失败。它们会在 `validateInput`、`applyAccountConfig` 和 `finalize` 之间复用同一条“需要安装”的消息,并在设置了 `docsPath` 时追加文档链接。 -`plugin-sdk/channel-setup` 还公开了更底层的 -`createOptionalChannelSetupAdapter(...)` 和 -`createOptionalChannelSetupWizard(...)` 构建器,当你只需要这个可选安装界面的一半时可以使用。 + + + 对于由二进制驱动的设置 UI,优先使用共享的委托式辅助工具,而不是在每个渠道中复制相同的二进制/状态胶水代码: -生成的可选适配器/向导在真实配置写入时会失败关闭。它们会在 -`validateInput`、`applyAccountConfig` 和 `finalize` 之间复用同一条“需要安装”的消息,并在设置了 `docsPath` 时附加一个文档链接。 + - `createDetectedBinaryStatus(...)`:适用于仅在标签、提示、分数和二进制检测上不同的状态块 + - `createCliPathTextInput(...)`:适用于基于路径的文本输入 + - `createDelegatedSetupWizardStatusResolvers(...)`、`createDelegatedPrepare(...)`、`createDelegatedFinalize(...)` 和 `createDelegatedResolveConfigured(...)`:适用于 `setupEntry` 需要惰性转发到更沉重的完整向导时 + - `createDelegatedTextInputShouldPrompt(...)`:适用于 `setupEntry` 只需要委托 `textInputs[*].shouldPrompt` 决策时 -对于基于二进制文件的设置 UI,优先使用共享的委托辅助工具,而不是在每个渠道中复制相同的二进制/Status 粘合逻辑: - -- `createDetectedBinaryStatus(...)`:用于仅在标签、提示、分数和二进制检测上变化的 Status 区块 -- `createCliPathTextInput(...)`:用于基于路径的文本输入 -- `createDelegatedSetupWizardStatusResolvers(...)`、 - `createDelegatedPrepare(...)`、`createDelegatedFinalize(...)` 和 - `createDelegatedResolveConfigured(...)`:当 `setupEntry` 需要惰性转发到更重的完整向导时使用 -- `createDelegatedTextInputShouldPrompt(...)`:当 `setupEntry` 只需要委托 `textInputs[*].shouldPrompt` 决策时使用 + + ## 发布和安装 **外部插件:** 发布到 [ClawHub](/zh-CN/tools/clawhub) 或 npm,然后安装: -```bash -openclaw plugins install @myorg/openclaw-my-plugin -``` + + + ```bash + openclaw plugins install @myorg/openclaw-my-plugin + ``` -OpenClaw 会先尝试 ClawHub,并在失败后自动回退到 npm。你也可以显式强制使用 ClawHub: + OpenClaw 会先尝试 ClawHub,失败后自动回退到 npm。 -```bash -openclaw plugins install clawhub:@myorg/openclaw-my-plugin # ClawHub only -``` + + + ```bash + openclaw plugins install clawhub:@myorg/openclaw-my-plugin + ``` + + + 没有对应的 `npm:` 覆盖写法。当你希望在 ClawHub 回退之后走 npm 路径时,请使用普通的 npm 包 spec: -没有对应的 `npm:` 覆盖方式。如果你希望在 ClawHub 回退后走 npm 路径,请使用普通的 npm 包说明: + ```bash + openclaw plugins install @myorg/openclaw-my-plugin + ``` -```bash -openclaw plugins install @myorg/openclaw-my-plugin -``` + + -**仓库内插件:** 放在内置插件工作区树下,构建期间会自动发现它们。 +**仓库内插件:** 放在内置插件工作区树下,构建期间会自动发现。 -**用户可执行安装:** +**用户可以安装:** ```bash openclaw plugins install ``` - 对于来自 npm 的安装,`openclaw plugins install` 会运行项目本地的 - `npm install --ignore-scripts`(不运行生命周期脚本),并忽略继承来的全局 npm 安装设置。请保持插件依赖树为纯 JS/TS,并避免依赖需要 `postinstall` 构建的包。 +对于来源于 npm 的安装,`openclaw plugins install` 会运行项目本地的 `npm install --ignore-scripts`(不执行生命周期脚本),并忽略继承的全局 npm 安装设置。请保持插件依赖树为纯 JS/TS,并避免依赖那些需要 `postinstall` 构建的包。 -内置且由 OpenClaw 拥有的插件是唯一的启动修复例外:当打包安装检测到某个插件已通过插件配置、旧版渠道配置,或其内置的默认启用清单而启用时,启动过程会在导入前安装该插件缺失的运行时依赖。第三方插件不应依赖启动安装;请继续使用显式的插件安装器。 + +只有 OpenClaw 自有的内置插件属于启动修复例外:当打包安装检测到某个插件已通过插件配置、旧版渠道配置,或其内置的默认启用清单被启用时,启动过程会在导入前先为该插件安装缺失的运行时依赖。第三方插件不应依赖启动时安装;请继续使用显式的插件安装器。 + ## 相关内容 -- [SDK 概览](/zh-CN/plugins/sdk-entrypoints) — `definePluginEntry` 和 `defineChannelPluginEntry` -- [插件清单](/zh-CN/plugins/manifest) — 完整清单模式参考 -- [构建插件](/zh-CN/plugins/building-plugins) — 分步入门指南 +- [构建插件](/zh-CN/plugins/building-plugins) — 分步的入门指南 +- [插件清单](/zh-CN/plugins/manifest) — 完整的清单 schema 参考 +- [SDK 入口点](/zh-CN/plugins/sdk-entrypoints) — `definePluginEntry` 和 `defineChannelPluginEntry` diff --git a/docs/zh-CN/tools/slash-commands.md b/docs/zh-CN/tools/slash-commands.md index a5ae5ff02..a6305ac91 100644 --- a/docs/zh-CN/tools/slash-commands.md +++ b/docs/zh-CN/tools/slash-commands.md @@ -2,38 +2,44 @@ read_when: - 使用或配置聊天命令 - 调试命令路由或权限 -summary: 斜杠命令:文本与原生、配置及支持的命令 +sidebarTitle: Slash commands +summary: 斜杠命令:文本与原生、配置和支持的命令 title: 斜杠命令 x-i18n: - generated_at: "2026-04-26T03:01:51Z" + generated_at: "2026-04-26T08:13:44Z" model: gpt-5.4 provider: openai - source_hash: cd97db0918e9ca0de77034d9a3e522d8b250ea66b210fc5d16ebfd60d6f73002 + source_hash: 75bf58d02738e30bfdc00ad1c264b2f066eebd2819f4ea0209f504f279755993 source_path: tools/slash-commands.md workflow: 15 --- -命令由 Gateway 网关处理。大多数命令必须作为以 `/` 开头的**独立**消息发送。 -仅主机可用的 bash 聊天命令使用 `! `(`/bash ` 是其别名)。 +命令由 Gateway 网关处理。大多数命令必须作为以 `/` 开头的**独立**消息发送。仅主机可用的 bash 聊天命令使用 `! `(`/bash ` 是它的别名)。 -当某个对话或线程绑定到 ACP 会话时,普通的后续文本 -会路由到该 ACP harness。Gateway 网关管理命令仍然保持本地处理: -`/acp ...` 总是会到达 OpenClaw ACP 命令处理器,而 `/status` 和 -`/unfocus` 在该界面启用命令处理时也始终保持本地处理。 +当某个对话或线程绑定到 ACP 会话时,普通的后续文本会路由到该 ACP harness。Gateway 网关管理命令仍然保持本地处理:`/acp ...` 总是会到达 OpenClaw ACP 命令处理器,而 `/status` 和 `/unfocus` 只要该界面启用了命令处理,就会保持本地处理。 这里有两个相关系统: -- **命令**:独立的 `/...` 消息。 -- **指令**:`/think`、`/fast`、`/verbose`、`/trace`、`/reasoning`、`/elevated`、`/exec`、`/model`、`/queue`。 - - 指令会在模型看到消息之前从消息中剥离。 - - 在普通聊天消息中(不是纯指令消息),它们会被视为“内联提示”,并且**不会**持久化会话设置。 - - 在纯指令消息中(消息只包含指令),它们会持久化到会话,并回复确认信息。 - - 指令仅对**已授权发送者**生效。如果设置了 `commands.allowFrom`,它就是唯一使用的 - 允许列表;否则授权来自渠道允许列表 / 配对以及 `commands.useAccessGroups`。 - 未授权发送者看到的指令会被当作普通文本处理。 + + + 独立的 `/...` 消息。 + + + `/think`、`/fast`、`/verbose`、`/trace`、`/reasoning`、`/elevated`、`/exec`、`/model`、`/queue`。 -还有一些**内联快捷命令**(仅限列入允许列表 / 已授权的发送者):`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 -它们会立即运行,在模型看到消息之前被剥离,剩余文本继续走正常流程。 + - 指令会在模型看到消息之前从消息中剥离。 + - 在普通聊天消息中(不是仅包含指令的消息),它们会被视为“行内提示”,并且**不会**持久化会话设置。 + - 在仅包含指令的消息中(消息只包含指令),它们会持久化到会话,并回复一个确认消息。 + - 指令只会对**已授权的发送者**生效。如果设置了 `commands.allowFrom`,它就是唯一使用的允许列表;否则,授权来源于渠道允许列表/配对加上 `commands.useAccessGroups`。未授权的发送者会看到这些指令被当作普通文本处理。 + + + + 仅限已列入允许列表/已授权的发送者:`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 + + 它们会立即运行,并在模型看到消息之前被剥离,剩余文本会继续按正常流程处理。 + + + ## 配置 @@ -62,30 +68,54 @@ x-i18n: } ``` -- `commands.text`(默认 `true`)启用在聊天消息中解析 `/...`。 - - 在不支持原生命令的界面上(WhatsApp / WebChat / Signal / iMessage / Google Chat / Microsoft Teams),即使你将其设置为 `false`,文本命令仍然可用。 -- `commands.native`(默认 `"auto"`)注册原生命令。 - - Auto:对 Discord / Telegram 开启;对 Slack 关闭(直到你添加斜杠命令);对不支持原生命令的提供商会被忽略。 - - 设置 `channels.discord.commands.native`、`channels.telegram.commands.native` 或 `channels.slack.commands.native` 可按提供商覆盖(布尔值或 `"auto"`)。 - - `false` 会在启动时清除之前在 Discord / Telegram 上注册的命令。Slack 命令在 Slack 应用中管理,不会自动移除。 -- `commands.nativeSkills`(默认 `"auto"`)在支持时以原生方式注册 **Skills** 命令。 - - Auto:对 Discord / Telegram 开启;对 Slack 关闭(Slack 要求为每个 Skill 单独创建一个斜杠命令)。 - - 设置 `channels.discord.commands.nativeSkills`、`channels.telegram.commands.nativeSkills` 或 `channels.slack.commands.nativeSkills` 可按提供商覆盖(布尔值或 `"auto"`)。 -- `commands.bash`(默认 `false`)启用 `! ` 来运行主机 shell 命令(`/bash ` 是别名;需要 `tools.elevated` 允许列表)。 -- `commands.bashForegroundMs`(默认 `2000`)控制 bash 在切换到后台模式前等待多长时间(`0` 表示立即转入后台)。 -- `commands.config`(默认 `false`)启用 `/config`(读取 / 写入 `openclaw.json`)。 -- `commands.mcp`(默认 `false`)启用 `/mcp`(读取 / 写入 OpenClaw 管理的 `mcp.servers` 下的 MCP 配置)。 -- `commands.plugins`(默认 `false`)启用 `/plugins`(插件发现 / 状态,以及安装与启用 / 禁用控制)。 -- `commands.debug`(默认 `false`)启用 `/debug`(仅运行时覆盖)。 -- `commands.restart`(默认 `true`)启用 `/restart` 以及 Gateway 网关重启工具操作。 -- `commands.ownerAllowFrom`(可选)为仅限所有者的命令 / 工具界面设置显式的所有者允许列表。这与 `commands.allowFrom` 分开。 -- 每个渠道的 `channels..commands.enforceOwnerForCommands`(可选,默认 `false`)会让仅限所有者的命令在该界面上要求**所有者身份**才能运行。当为 `true` 时,发送者必须与已解析的所有者候选匹配(例如 `commands.ownerAllowFrom` 中的条目或提供商原生所有者元数据),或者在内部消息渠道上拥有内部 `operator.admin` 作用域。渠道 `allowFrom` 中的通配符条目,或空的 / 未解析的所有者候选列表,**都不足以**满足要求——仅限所有者的命令会在该渠道上以失败关闭方式处理。如果你希望仅限所有者的命令只受 `ownerAllowFrom` 和标准命令允许列表控制,请保持关闭。 -- `commands.ownerDisplay` 控制所有者 ID 在系统提示中的显示方式:`raw` 或 `hash`。 -- `commands.ownerDisplaySecret` 可选设置在 `commands.ownerDisplay="hash"` 时使用的 HMAC 密钥。 -- `commands.allowFrom`(可选)为命令授权设置按提供商划分的允许列表。配置后,它会成为命令和指令的 - 唯一授权来源(渠道允许列表 / 配对以及 `commands.useAccessGroups` - 会被忽略)。使用 `"*"` 作为全局默认值;提供商专用键会覆盖它。 -- `commands.useAccessGroups`(默认 `true`)在未设置 `commands.allowFrom` 时,对命令强制执行允许列表 / 策略。 + + 启用在聊天消息中解析 `/...`。在没有原生命令的界面上(WhatsApp/WebChat/Signal/iMessage/Google Chat/Microsoft Teams),即使你将此项设置为 `false`,文本命令仍然可用。 + + + 注册原生命令。自动:对 Discord/Telegram 开启;对 Slack 关闭(直到你添加斜杠命令);对不支持原生能力的提供商会忽略。设置 `channels.discord.commands.native`、`channels.telegram.commands.native` 或 `channels.slack.commands.native` 可按提供商覆盖(布尔值或 `"auto"`)。`false` 会在启动时清除之前已在 Discord/Telegram 上注册的命令。Slack 命令由 Slack 应用管理,不会自动移除。 + + + 在支持时以原生方式注册 **skill** 命令。自动:对 Discord/Telegram 开启;对 Slack 关闭(Slack 需要为每个 skill 创建一个斜杠命令)。设置 `channels.discord.commands.nativeSkills`、`channels.telegram.commands.nativeSkills` 或 `channels.slack.commands.nativeSkills` 可按提供商覆盖(布尔值或 `"auto"`)。 + + + 启用 `! ` 来运行主机 shell 命令(`/bash ` 是别名;需要 `tools.elevated` 允许列表)。 + + + 控制 bash 在切换到后台模式之前等待多长时间(`0` 表示立即转入后台)。 + + + 启用 `/config`(读取/写入 `openclaw.json`)。 + + + 启用 `/mcp`(读取/写入 `mcp.servers` 下由 OpenClaw 管理的 MCP 配置)。 + + + 启用 `/plugins`(插件发现/状态,以及安装 + 启用/禁用控制)。 + + + 启用 `/debug`(仅运行时覆盖)。 + + + 启用 `/restart` 以及 Gateway 网关重启工具操作。 + + + 为仅限所有者的命令/工具界面设置显式的所有者允许列表。它独立于 `commands.allowFrom`。 + + + 按渠道设置:使该界面上的仅限所有者命令必须由**所有者身份**来运行。当为 `true` 时,发送者必须匹配一个已解析的所有者候选项(例如 `commands.ownerAllowFrom` 中的条目,或提供商原生的所有者元数据),或者在内部消息渠道上拥有内部 `operator.admin` 作用域。渠道 `allowFrom` 中的通配符条目,或者空的/未解析的所有者候选列表,**都不足以**满足条件——该渠道上的仅限所有者命令会以关闭方式失败。如果你希望仅限所有者命令只由 `ownerAllowFrom` 和标准命令允许列表来限制,请保持此项关闭。 + + + 控制所有者 id 在系统提示中的显示方式。 + + + 可选设置当 `commands.ownerDisplay="hash"` 时使用的 HMAC 密钥。 + + + 用于命令授权的按提供商划分的允许列表。配置后,它就是命令和指令唯一的授权来源(渠道允许列表/配对以及 `commands.useAccessGroups` 会被忽略)。使用 `"*"` 作为全局默认值;提供商特定键会覆盖它。 + + + 当未设置 `commands.allowFrom` 时,对命令强制执行允许列表/策略。 + ## 命令列表 @@ -93,61 +123,75 @@ x-i18n: - 核心内置命令来自 `src/auto-reply/commands-registry.shared.ts` - 生成的 dock 命令来自 `src/auto-reply/commands-registry.data.ts` -- 插件命令来自插件的 `registerCommand()` 调用 -- 你的 Gateway 网关上实际可用的命令仍取决于配置标志、渠道界面以及已安装 / 已启用的插件 +- 插件命令来自插件 `registerCommand()` 调用 +- 你的 Gateway 网关上实际可用的命令仍然取决于配置标志、渠道界面,以及已安装/已启用的插件 ### 核心内置命令 -当前可用的内置命令: - -- `/new [model]` 启动一个新会话;`/reset` 是重置别名。 -- `/reset soft [message]` 保留当前对话记录,丢弃复用的 CLI 后端会话 ID,并在原位重新运行启动 / 系统提示加载。 -- `/compact [instructions]` 压缩会话上下文。参见 [/concepts/compaction](/zh-CN/concepts/compaction)。 -- `/stop` 中止当前运行。 -- `/session idle ` 和 `/session max-age ` 管理线程绑定过期时间。 -- `/think ` 设置 thinking 级别。可选项来自当前模型的提供商配置;常见级别包括 `off`、`minimal`、`low`、`medium` 和 `high`,也包括仅在支持时可用的自定义级别,如 `xhigh`、`adaptive`、`max` 或二元 `on`。别名:`/thinking`、`/t`。 -- `/verbose on|off|full` 切换详细输出。别名:`/v`。 -- `/trace on|off` 为当前会话切换插件跟踪输出。 -- `/fast [status|on|off]` 显示或设置快速模式。 -- `/reasoning [on|off|stream]` 切换推理可见性。别名:`/reason`。 -- `/elevated [on|off|ask|full]` 切换 elevated 模式。别名:`/elev`。 -- `/exec host= security= ask= node=` 显示或设置 exec 默认值。 -- `/model [name|#|status]` 显示或设置模型。 -- `/models [provider] [page] [limit=|size=|all]` 列出提供商或某个提供商的模型。 -- `/queue ` 管理队列行为(`steer`、`interrupt`、`followup`、`collect`、`steer-backlog`),以及如 `debounce:2s cap:25 drop:summarize` 之类的选项。 -- `/help` 显示简短帮助摘要。 -- `/commands` 显示生成的命令目录。 -- `/tools [compact|verbose]` 显示当前智能体此刻可以使用的内容。 -- `/status` 显示执行 / 运行时状态,包括 `Execution` / `Runtime` 标签,以及可用时的提供商使用量 / 配额。 -- `/crestodian ` 从所有者私信中运行 Crestodian 设置与修复助手。 -- `/tasks` 列出当前会话的活动 / 最近后台任务。 -- `/context [list|detail|json]` 说明上下文是如何组装的。 -- `/export-session [path]` 将当前会话导出为 HTML。别名:`/export`。 -- `/export-trajectory [path]` 为当前会话导出 JSONL [trajectory bundle](/zh-CN/tools/trajectory)。别名:`/trajectory`。 -- `/whoami` 显示你的发送者 ID。别名:`/id`。 -- `/skill [input]` 按名称运行一个 Skill。 -- `/allowlist [list|add|remove] ...` 管理允许列表条目。仅文本。 -- `/approve ` 处理 exec 审批提示。 -- `/btw ` 提出一个旁支问题,而不改变未来的会话上下文。参见 [/tools/btw](/zh-CN/tools/btw)。 -- `/subagents list|kill|log|info|send|steer|spawn` 管理当前会话的子智能体运行。 -- `/acp spawn|cancel|steer|close|sessions|status|set-mode|set|cwd|permissions|timeout|model|reset-options|doctor|install|help` 管理 ACP 会话和运行时选项。 -- `/focus ` 将当前 Discord 线程或 Telegram 话题 / 对话绑定到一个会话目标。 -- `/unfocus` 移除当前绑定。 -- `/agents` 列出当前会话中线程绑定的智能体。 -- `/kill ` 中止一个或全部正在运行的子智能体。 -- `/steer ` 向正在运行的子智能体发送引导。别名:`/tell`。 -- `/config show|get|set|unset` 读取或写入 `openclaw.json`。仅限所有者。需要 `commands.config: true`。 -- `/mcp show|get|set|unset` 读取或写入 OpenClaw 管理的 `mcp.servers` 下的 MCP 服务器配置。仅限所有者。需要 `commands.mcp: true`。 -- `/plugins list|inspect|show|get|install|enable|disable` 检查或修改插件状态。`/plugin` 是别名。写操作仅限所有者。需要 `commands.plugins: true`。 -- `/debug show|set|unset|reset` 管理仅运行时的配置覆盖。仅限所有者。需要 `commands.debug: true`。 -- `/usage off|tokens|full|cost` 控制每次响应的使用量页脚,或打印本地成本摘要。 -- `/tts on|off|status|chat|latest|provider|limit|summary|audio|help` 控制 TTS。参见 [/tools/tts](/zh-CN/tools/tts)。 -- `/restart` 在启用时重启 OpenClaw。默认:启用;设置 `commands.restart: false` 可禁用。 -- `/activation mention|always` 设置群组激活模式。 -- `/send on|off|inherit` 设置发送策略。仅限所有者。 -- `/bash ` 运行主机 shell 命令。仅文本。别名:`! `。需要 `commands.bash: true` 以及 `tools.elevated` 允许列表。 -- `!poll [sessionId]` 检查后台 bash 作业。 -- `!stop [sessionId]` 停止后台 bash 作业。 + + + - `/new [model]` 启动一个新会话;`/reset` 是重置别名。 + - `/reset soft [message]` 保留当前转录内容,丢弃复用的 CLI 后端会话 id,并在原地重新运行启动/系统提示加载。 + - `/compact [instructions]` 压缩会话上下文。参见 [压缩](/zh-CN/concepts/compaction)。 + - `/stop` 中止当前运行。 + - `/session idle ` 和 `/session max-age ` 管理线程绑定过期时间。 + - `/export-session [path]` 将当前会话导出为 HTML。别名:`/export`。 + - `/export-trajectory [path]` 为当前会话导出一个 JSONL [trajectory bundle](/zh-CN/tools/trajectory)。别名:`/trajectory`。 + + + - `/think ` 设置思考级别。可选项来自当前模型的提供商配置文件;常见级别有 `off`、`minimal`、`low`、`medium` 和 `high`,也支持诸如 `xhigh`、`adaptive`、`max` 或仅在支持时提供的二元 `on` 等自定义级别。别名:`/thinking`、`/t`。 + - `/verbose on|off|full` 切换详细输出。别名:`/v`。 + - `/trace on|off` 为当前会话切换插件跟踪输出。 + - `/fast [status|on|off]` 显示或设置快速模式。 + - `/reasoning [on|off|stream]` 切换 reasoning 可见性。别名:`/reason`。 + - `/elevated [on|off|ask|full]` 切换 elevated 模式。别名:`/elev`。 + - `/exec host= security= ask= node=` 显示或设置 exec 默认值。 + - `/model [name|#|status]` 显示或设置模型。 + - `/models [provider] [page] [limit=|size=|all]` 列出提供商,或列出某个提供商的模型。 + - `/queue ` 管理队列行为(`steer`、`interrupt`、`followup`、`collect`、`steer-backlog`),以及类似 `debounce:2s cap:25 drop:summarize` 的选项。 + + + - `/help` 显示简短帮助摘要。 + - `/commands` 显示生成的命令目录。 + - `/tools [compact|verbose]` 显示当前智能体现在可使用的内容。 + - `/status` 显示执行/运行时状态,包括 `Execution`/`Runtime` 标签,以及可用时的提供商使用量/配额。 + - `/crestodian ` 从所有者私信中运行 Crestodian 设置和修复助手。 + - `/tasks` 列出当前会话中活动的/最近的后台任务。 + - `/context [list|detail|json]` 解释上下文是如何组装的。 + - `/whoami` 显示你的发送者 id。别名:`/id`。 + - `/usage off|tokens|full|cost` 控制每次响应的用量页脚,或打印本地成本摘要。 + + + - `/skill [input]` 按名称运行一个 skill。 + - `/allowlist [list|add|remove] ...` 管理允许列表条目。仅文本。 + - `/approve ` 处理 exec 审批提示。 + - `/btw ` 提出一个侧边问题,而不改变后续会话上下文。参见 [BTW](/zh-CN/tools/btw)。 + + + - `/subagents list|kill|log|info|send|steer|spawn` 管理当前会话的子智能体运行。 + - `/acp spawn|cancel|steer|close|sessions|status|set-mode|set|cwd|permissions|timeout|model|reset-options|doctor|install|help` 管理 ACP 会话和运行时选项。 + - `/focus ` 将当前 Discord 线程或 Telegram 话题/对话绑定到一个会话目标。 + - `/unfocus` 移除当前绑定。 + - `/agents` 列出当前会话中线程绑定的智能体。 + - `/kill ` 中止一个或所有正在运行的子智能体。 + - `/steer ` 向正在运行的子智能体发送引导。别名:`/tell`。 + + + - `/config show|get|set|unset` 读取或写入 `openclaw.json`。仅限所有者。需要 `commands.config: true`。 + - `/mcp show|get|set|unset` 读取或写入 `mcp.servers` 下由 OpenClaw 管理的 MCP 服务器配置。仅限所有者。需要 `commands.mcp: true`。 + - `/plugins list|inspect|show|get|install|enable|disable` 检查或修改插件状态。`/plugin` 是别名。写操作仅限所有者。需要 `commands.plugins: true`。 + - `/debug show|set|unset|reset` 管理仅运行时的配置覆盖。仅限所有者。需要 `commands.debug: true`。 + - `/restart` 在启用时重启 OpenClaw。默认:启用;设置 `commands.restart: false` 可禁用。 + - `/send on|off|inherit` 设置发送策略。仅限所有者。 + + + - `/tts on|off|status|chat|latest|provider|limit|summary|audio|help` 控制 TTS。参见 [TTS](/zh-CN/tools/tts)。 + - `/activation mention|always` 设置群组激活模式。 + - `/bash ` 运行主机 shell 命令。仅文本。别名:`! `。需要 `commands.bash: true` 加上 `tools.elevated` 允许列表。 + - `!poll [sessionId]` 检查后台 bash 作业。 + - `!stop [sessionId]` 停止后台 bash 作业。 + + ### 生成的 dock 命令 @@ -160,92 +204,98 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: ### 内置插件命令 -内置插件可以添加更多斜杠命令。此仓库中当前内置的命令: +内置插件可以添加更多斜杠命令。此仓库中当前内置的命令有: -- `/dreaming [on|off|status|help]` 切换 Memory Wiki dreaming。参见 [Dreaming](/zh-CN/concepts/dreaming)。 -- `/pair [qr|status|pending|approve|cleanup|notify]` 管理设备配对 / 设置流程。参见 [Pairing](/zh-CN/channels/pairing)。 +- `/dreaming [on|off|status|help]` 切换记忆 Dreaming。参见 [Dreaming](/zh-CN/concepts/dreaming)。 +- `/pair [qr|status|pending|approve|cleanup|notify]` 管理设备配对/设置流程。参见 [配对](/zh-CN/channels/pairing)。 - `/phone status|arm [duration]|disarm` 临时启用高风险手机节点命令。 - `/voice status|list [limit]|set ` 管理 Talk 语音配置。在 Discord 上,原生命令名称是 `/talkvoice`。 - `/card ...` 发送 LINE 富卡片预设。参见 [LINE](/zh-CN/channels/line)。 - `/codex status|models|threads|resume|compact|review|account|mcp|skills` 检查并控制内置的 Codex app-server harness。参见 [Codex harness](/zh-CN/plugins/codex-harness)。 -- 仅限 QQ Bot 的命令: +- 仅 QQBot 命令: - `/bot-ping` - `/bot-version` - `/bot-help` - `/bot-upgrade` - `/bot-logs` -### 动态 Skill 命令 +### 动态 skill 命令 -用户可调用的 Skills 也会暴露为斜杠命令: +可由用户调用的 Skills 也会暴露为斜杠命令: -- `/skill [input]` 始终可用,作为通用入口点。 -- 当 Skill / 插件注册它们时,Skills 也可能直接显示为诸如 `/prose` 之类的命令。 -- 原生 Skill 命令注册由 `commands.nativeSkills` 和 `channels..commands.nativeSkills` 控制。 +- `/skill [input]` 始终可作为通用入口点使用。 +- 当 skill/插件注册它们时,skills 也可能显示为像 `/prose` 这样的直接命令。 +- 原生 skill 命令注册由 `commands.nativeSkills` 和 `channels..commands.nativeSkills` 控制。 -注意: - -- 命令在命令与参数之间可选接受一个 `:`(例如 `/think: high`、`/send: on`、`/help:`)。 -- `/new ` 接受模型别名、`provider/model` 或提供商名称(模糊匹配);如果没有匹配,文本会被当作消息正文。 -- 如需完整的提供商使用量明细,请使用 `openclaw status --usage`。 -- `/allowlist add|remove` 需要 `commands.config=true`,并遵循渠道的 `configWrites`。 -- 在多账号渠道中,面向配置目标的 `/allowlist --account ` 和 `/config set channels..accounts....` 也遵循目标账号的 `configWrites`。 -- `/usage` 控制每次响应的使用量页脚;`/usage cost` 会根据 OpenClaw 会话日志打印本地成本摘要。 -- `/restart` 默认启用;设置 `commands.restart: false` 可禁用。 -- `/plugins install ` 接受与 `openclaw plugins install` 相同的插件规格:本地路径 / 压缩包、npm 包,或 `clawhub:`。 -- `/plugins enable|disable` 会更新插件配置,并可能提示重启。 -- 仅限 Discord 的原生命令:`/vc join|leave|status` 用于控制语音频道(不提供文本形式)。`join` 需要 guild 和已选择的语音 / Stage 频道。需要 `channels.discord.voice` 和原生命令。 -- Discord 线程绑定命令(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`)要求有效线程绑定已启用(`session.threadBindings.enabled` 和 / 或 `channels.discord.threadBindings.enabled`)。 -- ACP 命令参考与运行时行为:参见 [ACP Agents](/zh-CN/tools/acp-agents)。 -- `/verbose` 用于调试和额外可见性;在正常使用中请保持**关闭**。 -- `/trace` 比 `/verbose` 更窄:它只显示插件拥有的 trace / debug 行,并保持普通详细工具输出关闭。 -- `/fast on|off` 会持久化一个会话覆盖。使用 Sessions UI 中的 `inherit` 选项可清除它,并回退到配置默认值。 -- `/fast` 是提供商特定的:OpenAI / OpenAI Codex 会在原生 Responses 端点上将其映射为 `service_tier=priority`,而直接向公开 Anthropic 发出的请求,包括发送到 `api.anthropic.com` 的 OAuth 认证流量,则会将其映射为 `service_tier=auto` 或 `standard_only`。参见 [OpenAI](/zh-CN/providers/openai) 和 [Anthropic](/zh-CN/providers/anthropic)。 -- 相关时仍会显示工具失败摘要,但详细失败文本仅在 `/verbose` 为 `on` 或 `full` 时包含。 -- `/reasoning`、`/verbose` 和 `/trace` 在群组场景中有风险:它们可能泄露你原本无意暴露的内部推理、工具输出或插件诊断信息。建议保持关闭,尤其是在群聊中。 -- `/model` 会立即持久化新的会话模型。 -- 如果智能体处于空闲状态,下一次运行会立即使用它。 -- 如果某次运行已经处于活动状态,OpenClaw 会将实时切换标记为待处理,并仅在一个干净的重试点重启到新模型。 -- 如果工具活动或回复输出已经开始,待处理的切换可能会一直排队,直到稍后的重试机会或下一个用户轮次。 -- 在本地 TUI 中,`/crestodian [request]` 会从普通智能体 TUI 返回到 - Crestodian。这与消息渠道救援模式是分开的,并且不会 - 授予远程配置权限。 -- **快速路径:** 来自允许列表发送者的纯命令消息会被立即处理(绕过队列 + 模型)。 -- **群组提及门控:** 来自允许列表发送者的纯命令消息会绕过提及要求。 -- **内联快捷命令(仅限允许列表发送者):** 某些命令也可嵌入普通消息中使用,并会在模型看到剩余文本前被剥离。 - - 示例:`hey /status` 会触发状态回复,剩余文本继续走正常流程。 -- 当前包括:`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 -- 未授权的纯命令消息会被静默忽略,而内联 `/...` 标记会被当作普通文本。 -- **Skill 命令:** `user-invocable` Skills 会暴露为斜杠命令。名称会被清洗为 `a-z0-9_`(最多 32 个字符);冲突时会添加数字后缀(例如 `_2`)。 - - `/skill [input]` 按名称运行一个 Skill(当原生命令限制阻止按 Skill 单独建命令时很有用)。 - - 默认情况下,Skill 命令会作为普通请求转发给模型。 - - Skills 也可以选择声明 `command-dispatch: tool`,将命令直接路由给工具(确定性,无模型)。 - - 示例:`/prose`(OpenProse 插件)——参见 [OpenProse](/zh-CN/prose)。 -- **原生命令参数:** Discord 对动态选项使用自动补全(以及在你省略必需参数时使用按钮菜单)。Telegram 和 Slack 会在命令支持可选项且你省略参数时显示按钮菜单。动态选项会针对目标会话模型解析,因此诸如 `/think` 级别之类的模型特定选项会遵循该会话的 `/model` 覆盖。 + + + - 命令接受命令与参数之间可选的 `:`(例如 `/think: high`、`/send: on`、`/help:`)。 + - `/new ` 接受模型别名、`provider/model` 或提供商名称(模糊匹配);如果没有匹配项,文本会被视为消息正文。 + - 如需完整的提供商使用量明细,请使用 `openclaw status --usage`。 + - `/allowlist add|remove` 需要 `commands.config=true`,并遵循渠道 `configWrites`。 + - 在多账号渠道中,面向配置目标的 `/allowlist --account ` 和 `/config set channels..accounts....` 也会遵循目标账号的 `configWrites`。 + - `/usage` 控制每次响应的用量页脚;`/usage cost` 会根据 OpenClaw 会话日志打印本地成本摘要。 + - `/restart` 默认启用;设置 `commands.restart: false` 可禁用它。 + - `/plugins install ` 接受与 `openclaw plugins install` 相同的插件规范:本地路径/归档、npm 包或 `clawhub:`。 + - `/plugins enable|disable` 会更新插件配置,并可能提示你重启。 + + + - 仅 Discord 原生命令:`/vc join|leave|status` 控制语音频道(不提供文本形式)。`join` 需要 guild 和所选语音/舞台频道。需要 `channels.discord.voice` 和原生命令。 + - Discord 线程绑定命令(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`)要求实际线程绑定已启用(`session.threadBindings.enabled` 和/或 `channels.discord.threadBindings.enabled`)。 + - ACP 命令参考和运行时行为:参见 [ACP 智能体](/zh-CN/tools/acp-agents)。 + + + - `/verbose` 用于调试和提供更多可见性;正常使用时请保持**关闭**。 + - `/trace` 比 `/verbose` 更窄:它只显示插件拥有的 trace/debug 行,并保持普通 verbose 工具输出关闭。 + - `/fast on|off` 会持久化一个会话覆盖。使用 Sessions UI 的 `inherit` 选项可清除它并回退到配置默认值。 + - `/fast` 是提供商特定的:OpenAI/OpenAI Codex 会在原生 Responses 端点上将它映射为 `service_tier=priority`,而直接发送到 `api.anthropic.com` 的公共 Anthropic 请求(包括经 OAuth 认证的流量)则会将它映射为 `service_tier=auto` 或 `standard_only`。参见 [OpenAI](/zh-CN/providers/openai) 和 [Anthropic](/zh-CN/providers/anthropic)。 + - 当相关时,仍会显示工具失败摘要,但详细失败文本只会在 `/verbose` 为 `on` 或 `full` 时包含。 + - `/reasoning`、`/verbose` 和 `/trace` 在群组环境中有风险:它们可能暴露你无意公开的内部推理、工具输出或插件诊断信息。建议保持关闭,尤其是在群聊中。 + + + - `/model` 会立即持久化新的会话模型。 + - 如果智能体处于空闲状态,下一次运行会立即使用它。 + - 如果某次运行已经处于活动状态,OpenClaw 会将实时切换标记为待处理,并仅在一个干净的重试点重启到新模型。 + - 如果工具活动或回复输出已经开始,待处理切换可能会一直排队,直到后续的重试机会或下一次用户轮次。 + - 在本地 TUI 中,`/crestodian [request]` 会从普通智能体 TUI 返回到 Crestodian。这与消息渠道救援模式分离,并且不会授予远程配置权限。 + + + - **快速路径:** 来自允许列表发送者的纯命令消息会被立即处理(绕过队列 + 模型)。 + - **群组提及门控:** 来自允许列表发送者的纯命令消息会绕过提及要求。 + - **行内快捷命令(仅限允许列表发送者):** 某些命令即使嵌入在普通消息中也能生效,并会在模型看到其余内容之前被剥离。 + - 示例:`hey /status` 会触发状态回复,剩余文本会继续按正常流程处理。 + - 当前包括:`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 + - 未授权的纯命令消息会被静默忽略,而行内 `/...` 标记会被当作普通文本处理。 + + + - **skill 命令:** `user-invocable` skills 会暴露为斜杠命令。名称会被规范化为 `a-z0-9_`(最多 32 个字符);冲突时会加数字后缀(例如 `_2`)。 + - `/skill [input]` 按名称运行一个 skill(当原生命令限制阻止为每个 skill 创建命令时很有用)。 + - 默认情况下,skill 命令会作为普通请求转发给模型。 + - Skills 可以选择声明 `command-dispatch: tool`,将命令直接路由到工具(确定性,无模型参与)。 + - 示例:`/prose`(OpenProse 插件)——参见 [OpenProse](/zh-CN/prose)。 + - **原生命令参数:** Discord 对动态选项使用自动补全(当你省略必需参数时也会显示按钮菜单)。当命令支持选项而你省略参数时,Telegram 和 Slack 会显示按钮菜单。动态选项会根据目标会话模型解析,因此像 `/think` 级别这样的模型特定选项会遵循该会话的 `/model` 覆盖设置。 + + ## `/tools` -`/tools` 回答的是运行时问题,而不是配置问题:**这个智能体现在在 -此对话中可以使用什么**。 +`/tools` 回答的是一个运行时问题,而不是一个配置问题:**这个智能体现在在这个对话中可以使用什么**。 -- 默认 `/tools` 为紧凑模式,并针对快速扫描进行了优化。 +- 默认的 `/tools` 是紧凑模式,针对快速浏览进行了优化。 - `/tools verbose` 会添加简短说明。 -- 支持参数的原生命令界面也会暴露相同的 `compact|verbose` 模式切换。 -- 结果是会话作用域的,因此更改智能体、渠道、线程、发送者授权或模型都可能 - 改变输出。 -- `/tools` 包括在运行时实际可达的工具,包括核心工具、已连接的 - 插件工具和渠道拥有的工具。 +- 支持参数的原生命令界面会暴露相同的模式切换,即 `compact|verbose`。 +- 结果是会话范围的,因此更改智能体、渠道、线程、发送者授权或模型都可能改变输出。 +- `/tools` 包含运行时实际可达的工具,包括核心工具、已连接的插件工具和渠道拥有的工具。 -如需编辑配置文件和覆盖项,请使用 Control UI 的 Tools 面板或配置 / 目录界面, -而不要把 `/tools` 当作静态目录。 +对于配置文件和覆盖编辑,请使用 Control UI Tools 面板或配置/目录界面,而不要把 `/tools` 当成静态目录。 -## 使用量界面(各处显示什么) +## 使用量界面(哪些内容显示在哪里) -- **提供商使用量 / 配额**(例如:“Claude 还剩 80%”)会在 `/status` 中针对当前模型提供商显示,前提是已启用使用量跟踪。OpenClaw 会将提供商窗口标准化为“剩余 %”;对于 MiniMax,显示前会先对仅剩余百分比字段取反,而 `model_remains` 响应会优先选择聊天模型条目以及带模型标签的套餐标签。 -- `/status` 中的**令牌 / 缓存行**在实时会话快照较稀疏时,可以回退到最近一次对话记录使用量条目。现有的非零实时值仍然优先,而对话记录回退还可以在存储总量缺失或较小时,恢复当前活动运行时模型标签以及更大的面向提示的总量。 -- **Execution 与 Runtime:** `/status` 用 `Execution` 报告实际生效的沙箱路径,用 `Runtime` 报告实际运行会话的是谁:`OpenClaw Pi Default`、`OpenAI Codex`、某个 CLI 后端或某个 ACP 后端。 -- **每次响应的令牌 / 成本** 由 `/usage off|tokens|full` 控制(附加到普通回复)。 -- `/model status` 关注的是**模型 / 认证 / 端点**,而不是使用量。 +- **提供商使用量/配额**(例如:“Claude 剩余 80%”)会在启用使用量跟踪时显示在当前模型提供商的 `/status` 中。OpenClaw 会将提供商窗口统一标准化为“剩余百分比”;对于 MiniMax,只有剩余值的百分比字段会在显示前取反,而 `model_remains` 响应会优先选择 chat-model 条目并附带带模型标签的 plan 标签。 +- `/status` 中的 **Token/cache 行** 可以在实时会话快照信息稀疏时回退到最新的转录使用量条目。现有的非零实时值仍然优先,而转录回退也可以在存储总量缺失或更小时恢复当前活动运行时模型标签以及更偏向 prompt 的总量。 +- **Execution 与 runtime:** `/status` 会将有效沙箱路径报告为 `Execution`,并将实际运行该会话的对象报告为 `Runtime`:`OpenClaw Pi Default`、`OpenAI Codex`、某个 CLI 后端或某个 ACP 后端。 +- **每次响应的 token/成本** 由 `/usage off|tokens|full` 控制(附加到普通回复之后)。 +- `/model status` 关注的是**模型/认证/端点**,而不是使用量。 ## 模型选择(`/model`) @@ -262,16 +312,16 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: /model status ``` -注意: +说明: - `/model` 和 `/model list` 会显示一个紧凑的编号选择器(模型家族 + 可用提供商)。 -- 在 Discord 上,`/model` 和 `/models` 会打开一个交互式选择器,其中包含提供商和模型下拉菜单以及 Submit 步骤。 +- 在 Discord 上,`/model` 和 `/models` 会打开一个交互式选择器,包含提供商和模型下拉框以及一个 Submit 步骤。 - `/model <#>` 会从该选择器中进行选择(并在可能时优先使用当前提供商)。 -- `/model status` 会显示详细视图,包括已配置的提供商端点(`baseUrl`)和 API 模式(`api`),如果可用的话。 +- `/model status` 会显示详细视图,包括已配置的提供商端点(`baseUrl`)和 API 模式(`api`)(如果可用)。 -## 调试覆盖 +## Debug 覆盖 -`/debug` 允许你设置**仅运行时**配置覆盖(内存中,不写磁盘)。仅限所有者。默认禁用;使用 `commands.debug: true` 启用。 +`/debug` 允许你设置**仅运行时**的配置覆盖(存储在内存中,不写入磁盘)。仅限所有者。默认禁用;使用 `commands.debug: true` 启用。 示例: @@ -283,14 +333,13 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: /debug reset ``` -注意: + +覆盖会立即应用到新的配置读取,但**不会**写入 `openclaw.json`。使用 `/debug reset` 可清除所有覆盖并恢复到磁盘上的配置。 + -- 覆盖会立即应用于新的配置读取,但**不会**写入 `openclaw.json`。 -- 使用 `/debug reset` 清除所有覆盖,并返回磁盘上的配置。 +## 插件 trace 输出 -## 插件跟踪输出 - -`/trace` 允许你切换**会话作用域的插件 trace / debug 行**,而无需开启完整详细模式。 +`/trace` 允许你切换**会话范围的插件 trace/debug 行**,而无需开启完整的 verbose 模式。 示例: @@ -300,18 +349,18 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: /trace off ``` -注意: +说明: -- 不带参数的 `/trace` 会显示当前会话 trace 状态。 +- 不带参数的 `/trace` 会显示当前会话的 trace 状态。 - `/trace on` 会为当前会话启用插件 trace 行。 - `/trace off` 会再次禁用它们。 -- 插件 trace 行可能出现在 `/status` 中,也可能作为普通助手回复之后的后续诊断消息出现。 -- `/trace` 不能替代 `/debug`;`/debug` 仍用于管理仅运行时配置覆盖。 -- `/trace` 不能替代 `/verbose`;普通详细工具 / 状态输出仍属于 `/verbose`。 +- 插件 trace 行可能会显示在 `/status` 中,也可能作为普通助手回复之后的后续诊断消息出现。 +- `/trace` 不能替代 `/debug`;`/debug` 仍然用于管理仅运行时的配置覆盖。 +- `/trace` 不能替代 `/verbose`;普通的 verbose 工具/状态输出仍属于 `/verbose`。 ## 配置更新 -`/config` 会写入你的磁盘配置(`openclaw.json`)。仅限所有者。默认禁用;使用 `commands.config: true` 启用。 +`/config` 会写入你磁盘上的配置(`openclaw.json`)。仅限所有者。默认禁用;使用 `commands.config: true` 启用。 示例: @@ -323,14 +372,13 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: /config unset messages.responsePrefix ``` -注意: - -- 写入前会验证配置;无效变更会被拒绝。 -- `/config` 更新会在重启后保留。 + +配置会在写入前进行验证;无效更改会被拒绝。`/config` 更新会在重启后保留。 + ## MCP 更新 -`/mcp` 会写入 OpenClaw 管理的 `mcp.servers` 下的 MCP 服务器定义。仅限所有者。默认禁用;使用 `commands.mcp: true` 启用。 +`/mcp` 会将由 OpenClaw 管理的 MCP 服务器定义写入 `mcp.servers` 下。仅限所有者。默认禁用;使用 `commands.mcp: true` 启用。 示例: @@ -341,14 +389,13 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: /mcp unset context7 ``` -注意: - -- `/mcp` 将配置存储在 OpenClaw 配置中,而不是 Pi 拥有的项目设置中。 -- 运行时适配器决定哪些传输实际上可执行。 + +`/mcp` 将配置存储在 OpenClaw 配置中,而不是 Pi 拥有的项目设置中。运行时适配器决定哪些传输方式实际上可执行。 + ## 插件更新 -`/plugins` 允许操作员检查已发现的插件,并在配置中切换启用状态。只读流程可使用 `/plugin` 作为别名。默认禁用;使用 `commands.plugins: true` 启用。 +`/plugins` 允许操作员检查已发现的插件,并在配置中切换启用状态。只读流程可以使用 `/plugin` 作为别名。默认禁用;使用 `commands.plugins: true` 启用。 示例: @@ -360,47 +407,55 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: /plugins disable context7 ``` -注意: - -- `/plugins list` 和 `/plugins show` 会针对当前工作区以及磁盘配置执行真实插件发现。 -- `/plugins enable|disable` 只更新插件配置;不会安装或卸载插件。 -- 在启用 / 禁用变更后,重启 Gateway 网关以应用它们。 + +- `/plugins list` 和 `/plugins show` 会根据当前工作区和磁盘上的配置执行真实的插件发现。 +- `/plugins enable|disable` 只更新插件配置;它不会安装或卸载插件。 +- 启用/禁用更改后,重启 Gateway 网关以应用它们。 + ## 界面说明 -- **文本命令** 在普通聊天会话中运行(私信共享 `main`,群组有各自的会话)。 -- **原生命令** 使用隔离会话: - - Discord:`agent::discord:slash:` - - Slack:`agent::slack:slash:`(前缀可通过 `channels.slack.slashCommand.sessionPrefix` 配置) - - Telegram:`telegram:slash:`(通过 `CommandTargetSessionKey` 定向到聊天会话) -- **`/stop`** 针对活动聊天会话,因此它可以中止当前运行。 -- **Slack:** 仍支持 `channels.slack.slashCommand` 用于单个 `/openclaw` 风格命令。如果你启用了 `commands.native`,则必须为每个内置命令创建一个 Slack 斜杠命令(名称与 `/help` 相同)。Slack 的命令参数菜单会以临时 Block Kit 按钮形式发送。 - - Slack 原生命令例外:注册 `/agentstatus`(而不是 `/status`),因为 Slack 保留了 `/status`。文本 `/status` 在 Slack 消息中仍然可用。 + + + - **文本命令** 在普通聊天会话中运行(私信共享 `main`,群组有各自独立的会话)。 + - **原生命令** 使用隔离会话: + - Discord:`agent::discord:slash:` + - Slack:`agent::slack:slash:`(前缀可通过 `channels.slack.slashCommand.sessionPrefix` 配置) + - Telegram:`telegram:slash:`(通过 `CommandTargetSessionKey` 定位到聊天会话) + - **`/stop`** 以当前活动聊天会话为目标,因此它可以中止当前运行。 + + + `channels.slack.slashCommand` 仍然支持单个 `/openclaw` 风格的命令。如果你启用了 `commands.native`,则必须为每个内置命令在 Slack 中创建一个斜杠命令(名称与 `/help` 等相同)。Slack 的命令参数菜单会以临时 Block Kit 按钮的形式发送。 -## BTW 旁支问题 + Slack 原生命令例外:注册 `/agentstatus`(而不是 `/status`),因为 Slack 保留了 `/status`。文本 `/status` 在 Slack 消息中仍然可用。 -`/btw` 是一个关于当前会话的快速**旁支问题**。 + + + +## BTW 侧边问题 + +`/btw` 是一个关于当前会话的快速**侧边问题**。 与普通聊天不同: - 它使用当前会话作为背景上下文, -- 它以一个独立的**无工具**单次调用运行, -- 它不会改变未来的会话上下文, -- 它不会写入对话记录历史, -- 它会作为实时旁支结果交付,而不是普通助手消息。 +- 它会作为一个独立的**无工具**一次性调用运行, +- 它不会改变后续会话上下文, +- 它不会写入转录历史, +- 它会以实时侧边结果的形式传递,而不是作为普通助手消息。 -这使得 `/btw` 在你希望主任务继续进行的同时获得临时澄清时非常有用。 +这使得 `/btw` 在你希望获取临时澄清、同时主任务继续进行时非常有用。 示例: ```text -/btw 我们现在在做什么? +/btw what are we doing right now? ``` -完整行为和客户端 UX 细节请参见 [BTW Side Questions](/zh-CN/tools/btw)。 +完整行为和客户端 UX 细节请参见 [BTW 侧边问题](/zh-CN/tools/btw)。 -## 相关 +## 相关内容 +- [创建 Skills](/zh-CN/tools/creating-skills) - [Skills](/zh-CN/tools/skills) - [Skills 配置](/zh-CN/tools/skills-config) -- [创建 Skills](/zh-CN/tools/creating-skills)