chore(i18n): refresh zh-CN translations

This commit is contained in:
openclaw-docs-i18n[bot] 2026-04-27 06:56:57 +00:00
parent 4653f3761d
commit fbec7c5ae5
5 changed files with 330 additions and 343 deletions

View File

@ -1,28 +1,28 @@
---
read_when:
- 你想管理智能体钩子
- 你想检查钩子的可用性或启用工作区钩子
summary: '`openclaw hooks` 的 CLI 参考(智能体钩子)'
- 你想管理智能体钩子
- 你想检查钩子的可用性或启用工作区钩子
summary: '`openclaw hooks`(智能体钩子)的 CLI 参考'
title: 钩子
x-i18n:
generated_at: "2026-04-25T22:08:04Z"
generated_at: "2026-04-27T06:55:58Z"
model: gpt-5.4
provider: openai
source_hash: 874c3c7e7b603066209857e8b8b39bbe23eb8d1eda148025c74907c05bacd8f2
source_hash: 71c03d264f07bab80af8237d3ac5366a221d17e54234597a66ecbacff3bab62d
source_path: cli/hooks.md
workflow: 15
---
# `openclaw hooks`
管理智能体钩子(用于 `/new`、`/reset` 和 Gateway 网关启动等命令的事件驱动自动化)。
管理智能体钩子(针对 `/new`、`/reset` 和 Gateway 网关启动等命令的事件驱动自动化)。
在不带任何子命令的情况下运行 `openclaw hooks`,等同于 `openclaw hooks list`
在不带子命令的情况下运行 `openclaw hooks`,等同于 `openclaw hooks list`
相关内容:
- 钩子:[钩子](/zh-CN/automation/hooks)
- 插件钩子:[Plugin hooks](/zh-CN/plugins/hooks)
- 插件钩子:[插件钩子](/zh-CN/plugins/hooks)
## 列出所有钩子
@ -31,7 +31,7 @@ openclaw hooks list
```
列出从工作区、托管、额外和内置目录中发现的所有钩子。
在至少配置了一个内部钩子之前Gateway 网关启动时不会加载内部钩子处理程序
在至少配置了一个内部钩子之前Gateway 网关启动时不会加载内部钩子处理
**选项:**
@ -42,13 +42,13 @@ openclaw hooks list
**示例输出:**
```
Hooks (4/4 ready)
Hooks4/4 已就绪)
Ready:
🚀 boot-md ✓ - Run BOOT.md on gateway startup
📎 bootstrap-extra-files ✓ - Inject extra workspace bootstrap files during agent bootstrap
📝 command-logger ✓ - Log all command events to a centralized audit file
💾 session-memory ✓ - Save session context to memory when /new or /reset command is issued
已就绪:
🚀 boot-md ✓ - 在 Gateway 网关启动时运行 BOOT.md
📎 bootstrap-extra-files ✓ - 在智能体引导期间注入额外的工作区引导文件
📝 command-logger ✓ - 将所有命令事件记录到集中式审计文件
💾 session-memory ✓ - 在发出 /new 或 /reset 命令时将会话上下文保存到 memory
```
**示例(详细模式):**
@ -92,28 +92,28 @@ openclaw hooks info session-memory
**输出:**
```
💾 session-memory ✓ Ready
💾 session-memory ✓ 已就绪
Save session context to memory when /new or /reset command is issued
在发出 /new 或 /reset 命令时将会话上下文保存到 memory
Details:
详细信息:
Source: openclaw-bundled
Path: /path/to/openclaw/hooks/bundled/session-memory/HOOK.md
Handler: /path/to/openclaw/hooks/bundled/session-memory/handler.ts
Homepage: https://docs.openclaw.ai/automation/hooks#session-memory
Events: command:new, command:reset
Requirements:
要求:
Config: ✓ workspace.dir
```
## 检查钩子是否符合条件
## 检查钩子可用性
```bash
openclaw hooks check
```
显示钩子符合条件状态的摘要(有多少已就绪,多少未就绪)。
显示钩子可用性状态摘要(有多少已就绪,多少未就绪)。
**选项:**
@ -122,11 +122,11 @@ openclaw hooks check
**示例输出:**
```
Hooks Status
Hooks 状态
Total hooks: 4
Ready: 4
Not ready: 0
钩子总数:4
已就绪:4
未就绪:0
```
## 启用钩子
@ -135,9 +135,9 @@ Not ready: 0
openclaw hooks enable <name>
```
通过将特定钩子添加到你的配置中来启用它(默认是 `~/.openclaw/openclaw.json`)。
通过将特定钩子添加到你的配置中(默认是 `~/.openclaw/openclaw.json`来启用它
**注意:** 工作区钩子默认处于禁用状态,必须先在这里或在配置中启用。由插件管理的钩子会在 `openclaw hooks list` 中显示为 `plugin:<id>`,不能在这里启用或禁用。请改为启用或禁用对应插件。
**注意:** 工作区钩子默认禁用,需在这里或配置中启用。由插件管理的钩子会在 `openclaw hooks list` 中显示为 `plugin:<id>`,不能在这里启用或禁用。请改为启用或禁用对应插件。
**参数:**
@ -152,21 +152,20 @@ openclaw hooks enable session-memory
**输出:**
```
Enabled hook: 💾 session-memory
已启用钩子:💾 session-memory
```
**它会执行以下操作:**
- 检查钩子是否存在且符合条件
- 在你的配置中更新 `hooks.internal.entries.<name>.enabled = true`
- 更新你配置中的 `hooks.internal.entries.<name>.enabled = true`
- 将配置保存到磁盘
如果该钩子来自 `<workspace>/hooks/`,则必须完成这一步显式启用,
Gateway 网关才会加载它。
如果该钩子来自 `<workspace>/hooks/`则必须执行此选择启用步骤Gateway 网关才会加载它。
**启用后:**
- 重启 gateway使钩子重新加载在 macOS 上重启菜单栏应用,或在开发环境中重启你的 gateway 进程)。
- 重启 Gateway 网关以重新加载钩子(在 macOS 上重启菜单栏应用,或在开发环境中重启你的 Gateway 网关进程)。
## 禁用钩子
@ -189,12 +188,12 @@ openclaw hooks disable command-logger
**输出:**
```
Disabled hook: 📝 command-logger
已禁用钩子:📝 command-logger
```
**禁用后:**
- 重启 gateway使钩子重新加载
- 重启 Gateway 网关以重新加载钩子
## 说明
@ -204,24 +203,18 @@ openclaw hooks disable command-logger
## 安装钩子包
```bash
openclaw plugins install <package> # 优先 ClawHub然后是 npm
openclaw plugins install <package> --pin # 固定版本
openclaw plugins install <path> # 本地路径
openclaw plugins install <package> # ClawHub first, then npm
openclaw plugins install <package> --pin # pin version
openclaw plugins install <path> # local path
```
通过统一的插件安装器安装钩子包。
`openclaw hooks install` 仍然可用,作为兼容性别名,但它会打印弃用警告,
并转发到 `openclaw plugins install`
`openclaw hooks install` 仍然可用作兼容别名,但它会打印弃用警告,并转发到 `openclaw plugins install`
Npm 规格必须是**仅注册表**形式(包名 + 可选的**精确版本**或
**dist-tag**。Git/URL/file 规格和 semver 范围会被拒绝。出于安全考虑,
依赖安装会以项目本地方式运行,并使用 `--ignore-scripts`,即使你的
shell 配置了全局 npm 安装设置也是如此。
Npm 规格只支持**注册表来源**(包名 + 可选的**精确版本**或 **dist-tag**。Git/URL/file 规格和 semver 范围会被拒绝。为确保安全,依赖安装会在项目本地使用 `--ignore-scripts` 运行,即使你的 shell 配置了全局 npm 安装设置也是如此。
裸规格和 `@latest` 会保持在稳定通道上。如果 npm 将其中任一解析为预发布版本,
OpenClaw 会停止并要求你显式选择加入,例如使用 `@beta`/`@rc` 这样的
预发布标签,或精确的预发布版本。
裸规格和 `@latest` 会保持在稳定轨道上。如果 npm 将其中任一解析为预发布版本OpenClaw 会停止并要求你通过预发布标签(例如 `@beta`/`@rc`)或精确的预发布版本显式选择加入。
**它会执行以下操作:**
@ -232,7 +225,7 @@ OpenClaw 会停止并要求你显式选择加入,例如使用 `@beta`/`@rc`
**选项:**
- `-l, --link`:链接本地目录而不是复制(将其添加到 `hooks.internal.load.extraDirs`
- `--pin`:将 npm 安装记录为 `hooks.internal.installs` 中精确解析后的 `name@version`
- `--pin`:将 npm 安装以精确解析后的 `name@version` 记录到 `hooks.internal.installs`
**支持的归档格式:** `.zip`、`.tgz`、`.tar.gz`、`.tar`
@ -252,7 +245,7 @@ openclaw plugins install @openclaw/my-hook-pack
openclaw plugins install -l ./my-hook-pack
```
已链接的钩子包会被视为来自操作员配置目录的托管钩子,而不是工作区钩子。
已链接的钩子包会被视为来自运维者配置目录的托管钩子,而不是工作区钩子。
## 更新钩子包
@ -261,25 +254,22 @@ openclaw plugins update <id>
openclaw plugins update --all
```
通过统一的插件更新器更新跟踪的基于 npm 的钩子包。
通过统一的插件更新器更新跟踪的基于 npm 的钩子包。
`openclaw hooks update` 仍然可用,作为兼容性别名,但它会打印弃用警告,
并转发到 `openclaw plugins update`
`openclaw hooks update` 仍然可用作兼容别名,但它会打印弃用警告,并转发到 `openclaw plugins update`
**选项:**
- `--all`:更新所有跟踪的钩子包
- `--dry-run`:显示将会发生的更改,但不实际写入
- `--all`:更新所有跟踪的钩子包
- `--dry-run`:显示将会发生的更改,但不写入
当存在已存储的完整性哈希且获取到的制品哈希发生变化时,
OpenClaw 会打印警告,并在继续前请求确认。在 CI/非交互式运行中,
可使用全局 `--yes` 跳过提示。
当存在已存储的完整性哈希且获取到的制品哈希发生变化时OpenClaw 会打印警告,并在继续前请求确认。在 CI / 非交互式运行中,可使用全局 `--yes` 跳过提示。
## 内置钩子
### session-memory
当你发出 `/new``/reset` 时,将会话上下文保存到 memory
当你发出 `/new``/reset` 时,将会话上下文保存到 memory。
**启用:**
@ -305,7 +295,7 @@ openclaw hooks enable bootstrap-extra-files
### command-logger
将所有命令事件记录到集中式审计文件
将所有命令事件记录到集中式审计文件。
**启用:**
@ -332,7 +322,7 @@ grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
### boot-md
gateway 启动时运行 `BOOT.md`(在渠道启动之后)
Gateway 网关启动时(渠道启动后)运行 `BOOT.md`
**事件**`gateway:startup`

View File

@ -1,15 +1,15 @@
---
read_when:
- 你想要自动化的服务器部署,并进行安全加固
- 你需要通过 VPN 访问的防火墙隔离设置
- 你正在部署到远程 Debian/Ubuntu 服务器
summary: 使用 Ansible、Tailscale VPN 和防火墙隔离实现自动化加固的 OpenClaw 安装
- 你需要通过 VPN 访问的防火墙隔离设置
- 你部署到远程 Debian/Ubuntu 服务器
summary: 使用 Ansible、Tailscale VPN 和防火墙隔离实现自动化、强化安全的 OpenClaw 安装
title: Ansible
x-i18n:
generated_at: "2026-04-20T18:29:36Z"
generated_at: "2026-04-27T06:55:58Z"
model: gpt-5.4
provider: openai
source_hash: 2a23374c971a1f3163dd18c32e553ebaad55b2542c1f25f49bcc9ae464d679e8
source_hash: 2fa6c215bc2d4a9d032438bead4336bc10433eb8c40e206d72224c7009c7dabf
source_path: install/ansible.md
workflow: 15
---
@ -22,7 +22,7 @@ x-i18n:
[openclaw-ansible](https://github.com/openclaw/openclaw-ansible) 仓库是 Ansible 部署的权威来源。本页仅提供快速概览。
</Info>
## 前提条件
## 先决条件
| 要求 | 详情 |
| ----------- | --------------------------------------------------------- |
@ -34,11 +34,11 @@ x-i18n:
## 你将获得什么
- **防火墙优先的安全性** —— UFW + Docker 隔离(仅 SSH + Tailscale 可访问)
- **Tailscale VPN** —— 无需公开暴露服务即可安全远程访问
- **Docker** —— 隔离的沙箱容器,仅绑定 localhost
- **Tailscale VPN** —— 安全的远程访问,无需将服务公开暴露到互联网
- **Docker** —— 隔离的沙箱容器,仅绑定 localhost
- **纵深防御** —— 4 层安全架构
- **Systemd 集成** —— 开机自动启动并带有加固配置
- **一条命令即可完成设置** —— 几分钟内完成完整部署
- **Systemd 集成** —— 开机自动启动并带有安全加固
- **一条命令完成设置** —— 几分钟内完成完整部署
## 快速开始
@ -48,7 +48,7 @@ x-i18n:
curl -fsSL https://raw.githubusercontent.com/openclaw/openclaw-ansible/main/install.sh | bash
```
## 将安装内容
## 将安装哪些内容
Ansible playbook 会安装并配置:
@ -60,7 +60,7 @@ Ansible playbook 会安装并配置:
6. **Systemd 服务** —— 自动启动并带有安全加固
<Note>
Gateway 网关直接在主机上运行(不在 Docker 中)。智能体沙箱隔离是可选的;此 playbook 安装 Docker,因为它是默认的沙箱后端。详情及其他后端请参阅 [沙箱隔离](/zh-CN/gateway/sandboxing)。
Gateway 网关直接在主机上运行(不在 Docker 中)。智能体沙箱隔离是可选的;此 playbook 安装 Docker 是因为它是默认的沙箱后端。详情和其他后端请参见 [沙箱隔离](/zh-CN/gateway/sandboxing)。
</Note>
## 安装后设置
@ -87,7 +87,7 @@ Gateway 网关直接在主机上运行(不在 Docker 中)。智能体沙箱
```
</Step>
<Step title="连接到 Tailscale">
加入你的 VPN mesh 以进行安全远程访问。
加入你的 VPN mesh,以实现安全远程访问。
</Step>
</Steps>
@ -103,7 +103,7 @@ sudo journalctl -u openclaw -f
# 重启 Gateway 网关
sudo systemctl restart openclaw
# 提供商登录(以 openclaw 用户运行)
# 提供商登录(以 openclaw 用户身份运行)
sudo -i -u openclaw
openclaw channels login
```
@ -123,16 +123,16 @@ openclaw channels login
nmap -p- YOUR_SERVER_IP
```
该只有 22 端口SSH处于开放状态。所有其他服务Gateway 网关、Docker都已被锁定。
当只有端口 22SSH开放。所有其他服务Gateway 网关、Docker都已被锁定。
安装 Docker 是为了智能体沙箱(隔离的工具执行),而不是为了运行 Gateway 网关本身。有关沙箱配置,请参 [多智能体沙箱与工具](/zh-CN/tools/multi-agent-sandbox-tools)。
安装 Docker 是为了智能体沙箱(隔离的工具执行),而不是为了运行 Gateway 网关本身。有关沙箱配置,请参 [多智能体沙箱与工具](/zh-CN/tools/multi-agent-sandbox-tools)。
## 手动安装
如果你更希望手动控制自动化过程:
如果你更喜欢手动控制自动化过程:
<Steps>
<Step title="安装前提依赖">
<Step title="安装先决条件">
```bash
sudo apt update && sudo apt install -y ansible git
```
@ -156,7 +156,7 @@ nmap -p- YOUR_SERVER_IP
或者,直接运行,然后在之后手动执行设置脚本:
```bash
ansible-playbook playbook.yml --ask-become-pass
# 然后运行:/tmp/openclaw-setup.sh
# Then run: /tmp/openclaw-setup.sh
```
</Step>
@ -164,24 +164,24 @@ nmap -p- YOUR_SERVER_IP
## 更新
Ansible 安装器会将 OpenClaw 设置为手动更新。标准更新流程请参 [更新](/zh-CN/install/updating)。
Ansible 安装器会将 OpenClaw 设置为手动更新。标准更新流程请参 [更新](/zh-CN/install/updating)。
如需重新运行 Ansible playbook例如用于配置变更
要重新运行 Ansible playbook例如应用配置更改
```bash
cd openclaw-ansible
./run-playbook.sh
```
这是幂等的,可以安全地多次运行。
这是幂等的,并且可以安全地多次运行。
## 故障排除
<AccordionGroup>
<Accordion title="防火墙阻止了我的连接">
- 请先确保你可以通过 Tailscale VPN 访问
- 始终允许 SSH 访问(22 端口)
- Gateway 网关按设计仅通过 Tailscale 访问
- 确保你可以通过 Tailscale VPN 访问
- 始终允许 SSH 访问(端口 22
- Gateway 网关按设计仅通过 Tailscale 访问
</Accordion>
<Accordion title="服务无法启动">
```bash
@ -213,7 +213,7 @@ cd openclaw-ansible
</Accordion>
<Accordion title="提供商登录失败">
请确保你正在`openclaw` 用户身份运行:
确保你是`openclaw` 用户身份运行:
```bash
sudo -i -u openclaw
openclaw channels login
@ -223,7 +223,7 @@ cd openclaw-ansible
## 高级配置
有关详细的安全架构和故障排除信息,请参 openclaw-ansible 仓库:
有关详细的安全架构和故障排除信息,请参 openclaw-ansible 仓库:
- [安全架构](https://github.com/openclaw/openclaw-ansible/blob/main/docs/security.md)
- [技术细节](https://github.com/openclaw/openclaw-ansible/blob/main/docs/architecture.md)
@ -234,4 +234,4 @@ cd openclaw-ansible
- [openclaw-ansible](https://github.com/openclaw/openclaw-ansible) —— 完整部署指南
- [Docker](/zh-CN/install/docker) —— 容器化的 Gateway 网关设置
- [沙箱隔离](/zh-CN/gateway/sandboxing) —— 智能体沙箱配置
- [多智能体沙箱与工具](/zh-CN/tools/multi-agent-sandbox-tools) —— 按智能体隔离
- [多智能体沙箱与工具](/zh-CN/tools/multi-agent-sandbox-tools) —— 按智能体进行隔离

View File

@ -1,30 +1,30 @@
---
read_when:
- 了解 OpenClaw 中 Pi SDK 集成的设计
- 修改 Pi 的智能体会话生命周期、工具或 provider 接线
summary: OpenClaw 内嵌 Pi 智能体集成与会话生命周期的架构
- 理解 OpenClaw 中 Pi SDK 集成设计
- 修改 Pi 的智能体会话生命周期、工具能力或提供商接线逻辑
summary: OpenClaw 内置 Pi 智能体集成的架构和会话生命周期
title: Pi 集成架构
x-i18n:
generated_at: "2026-04-27T06:05:36Z"
generated_at: "2026-04-27T06:55:56Z"
model: gpt-5.4
provider: openai
source_hash: 42dff5d5a5d8a8c4af724c70a8864346f6ef9ff0b04dbc4fb3149685b2eb64cf
source_hash: 0b155cd5296875f2f187c68c6929c48aba27cef047f0caad74f560bcde5533e5
source_path: pi.md
workflow: 15
---
OpenClaw [pi-coding-agent](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent) 及其同级包(`pi-ai`、`pi-agent-core`、`pi-tui`集成,为其 AI 智能体能力提供支持
OpenClaw 通过集成 [pi-coding-agent](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent) 及其同级包(`pi-ai`、`pi-agent-core`、`pi-tui`来驱动其 AI 智能体能力
## 概览
OpenClaw 使用 pi SDK,将一个 AI 编码智能体嵌入到其消息 Gateway 网关架构中。OpenClaw 不会将 pi 作为子进程启动,也不会使用 RPC 模式,而是直接导入并通过 `createAgentSession()` 实例化 pi 的 `AgentSession`。这种嵌入式方提供了:
OpenClaw 使用 pi SDK 将一个 AI 编码智能体嵌入到其 Gateway 网关消息架构中。OpenClaw 并不是将 pi 作为子进程启动,也不是使用 RPC 模式,而是直接导入并通过 `createAgentSession()` 实例化 pi 的 `AgentSession`。这种嵌入式方提供了:
- 对会话生命周期和事件处理的完控制
- 对会话生命周期和事件处理的完控制
- 自定义工具注入(消息、沙箱、渠道特定操作)
- 按渠道/上下文进行系统提示自定义
- 按渠道/上下文定制系统提示词
- 支持分支/压缩的会话持久化
- 带故障转移的多账号 auth profile 轮换
- 与 provider 无关的模型切换
- 支持故障转移的多账户认证配置轮换
- 与提供商无关的模型切换
## 包依赖
@ -37,12 +37,12 @@ OpenClaw 使用 pi SDK将一个 AI 编码智能体嵌入到其消息 Gateway
}
```
| 包 | 用途 |
| ------------------- | ------------------------------------------------------------------------------------------------------ |
| `pi-ai` | 核心 LLM 抽象:`Model`、`streamSimple`、消息类型、provider API |
| `pi-agent-core` | Agent loop、工具执行、`AgentMessage` 类型 |
| `pi-coding-agent` | 高级 SDK`createAgentSession`、`SessionManager`、`AuthStorage`、`ModelRegistry`、内置工具 |
| `pi-tui` | 终端 UI 组件(用于 OpenClaw 的本地 TUI 模式) |
| 包 | 用途 |
| ----------------- | ------------------------------------------------------------------------------------------------------ |
| `pi-ai` | 核心 LLM 抽象:`Model`、`streamSimple`、消息类型、提供商 API |
| `pi-agent-core` | Agent loop、工具执行、`AgentMessage` 类型 |
| `pi-coding-agent` | 高层 SDK`createAgentSession`、`SessionManager`、`AuthStorage`、`ModelRegistry`、内置工具 |
| `pi-tui` | 终端 UI 组件(用于 OpenClaw 的本地 TUI 模式) |
## 文件结构
@ -52,67 +52,67 @@ src/agents/
├── pi-embedded-runner/
│ ├── run.ts # 主入口runEmbeddedPiAgent()
│ ├── run/
│ │ ├── attempt.ts # 会话设置的单次尝试逻辑
│ │ ├── attempt.ts # 会话设置的单次尝试逻辑
│ │ ├── params.ts # RunEmbeddedPiAgentParams 类型
│ │ ├── payloads.ts # 从运行结果构建响应载
│ │ ├── images.ts # Vision 模型图像注入
│ │ ├── payloads.ts # 从运行结果构建响应
│ │ ├── images.ts # 视觉模型图像注入
│ │ └── types.ts # EmbeddedRunAttemptResult
│ ├── abort.ts # 中止错误检测
│ ├── abort.ts # Abort 错误检测
│ ├── cache-ttl.ts # 用于上下文裁剪的缓存 TTL 跟踪
│ ├── compact.ts # 手动/自动压缩逻辑
│ ├── extensions.ts # 为嵌入式运行加载 pi 扩展
│ ├── extra-params.ts # provider 特定流式参数
│ ├── google.ts # Google/Gemini 回合顺序修复
│ ├── extra-params.ts # 提供商特定的流式参数
│ ├── google.ts # Google/Gemini 轮次顺序修复
│ ├── history.ts # 历史记录限制(私信 vs 群组)
│ ├── lanes.ts # 会话/全局命令通道
│ ├── logger.ts # 子系统日志记录器
│ ├── model.ts # 通过 ModelRegistry 解析模型
│ ├── runs.ts # 活动运行跟踪、中止、队列
│ ├── sandbox-info.ts # 用于系统提示的沙箱信息
│ ├── runs.ts # 活动运行跟踪、Abort、队列
│ ├── sandbox-info.ts # 用于系统提示的沙箱信息
│ ├── session-manager-cache.ts # SessionManager 实例缓存
│ ├── session-manager-init.ts # 会话文件初始化
│ ├── system-prompt.ts # 系统提示构建器
│ ├── tool-split.ts # 将工具拆分为 builtIn custom
│ ├── system-prompt.ts # 系统提示构建器
│ ├── tool-split.ts # 将工具拆分为 builtIn custom
│ ├── types.ts # EmbeddedPiAgentMeta、EmbeddedPiRunResult
│ └── utils.ts # ThinkLevel 映射、错误说明
│ └── utils.ts # ThinkLevel 映射、错误描述
├── pi-embedded-subscribe.ts # 会话事件订阅/分发
├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams
├── pi-embedded-subscribe.handlers.ts # 事件处理器工厂
├── pi-embedded-subscribe.handlers.lifecycle.ts
├── pi-embedded-subscribe.handlers.types.ts
├── pi-embedded-block-chunker.ts # 流式分块回复切
├── pi-embedded-messaging.ts # 消息工具发送跟踪
├── pi-embedded-helpers.ts # 错误分类、回合验证
├── pi-embedded-block-chunker.ts # 流式分块回复切
├── pi-embedded-messaging.ts # 消息工具发送跟踪
├── pi-embedded-helpers.ts # 错误分类、轮次校验
├── pi-embedded-helpers/ # 辅助模块
├── pi-embedded-utils.ts # 格式化工具
├── pi-tools.ts # createOpenClawCodingTools()
├── pi-tools.abort.ts # 工具的 AbortSignal
├── pi-tools.abort.ts # 工具的 AbortSignal
├── pi-tools.policy.ts # 工具允许列表/拒绝列表策略
├── pi-tools.read.ts # Read 工具自定义
├── pi-tools.schema.ts # 工具 schema 规范
├── pi-tools.read.ts # read 工具定制
├── pi-tools.schema.ts # 工具 schema 标准
├── pi-tools.types.ts # AnyAgentTool 类型别名
├── pi-tool-definition-adapter.ts # AgentTool -> ToolDefinition 适配器
├── pi-settings.ts # 设置覆盖
├── pi-hooks/ # 自定义 pi 钩子
│ ├── compaction-safeguard.ts # Safeguard 扩展
│ ├── compaction-safeguard.ts # 保护扩展
│ ├── compaction-safeguard-runtime.ts
│ ├── context-pruning.ts # 缓存 TTL 上下文裁剪扩展
│ └── context-pruning/
├── model-auth.ts # auth profile 解析
├── auth-profiles.ts # 配置存储、冷却、故障转移
├── model-auth.ts # 认证配置解析
├── auth-profiles.ts # 配置存储、冷却、故障转移
├── model-selection.ts # 默认模型解析
├── models-config.ts # models.json 生成
├── model-catalog.ts # 模型目录缓存
├── context-window-guard.ts # 上下文窗口验
├── context-window-guard.ts # 上下文窗口
├── failover-error.ts # FailoverError 类
├── defaults.ts # DEFAULT_PROVIDER、DEFAULT_MODEL
├── system-prompt.ts # buildAgentSystemPrompt()
├── system-prompt-params.ts # 系统提示参数解析
├── system-prompt-params.ts # 系统提示参数解析
├── system-prompt-report.ts # 调试报告生成
├── tool-summaries.ts # 工具描述摘要
├── tool-policy.ts # 工具策略解析
├── transcript-policy.ts # 转录验策略
├── skills.ts # Skills 快照/提示构建
├── transcript-policy.ts # 转录验策略
├── skills.ts # Skills 快照/提示构建
├── skills/ # Skills 子系统
├── sandbox.ts # 沙箱上下文解析
├── sandbox/ # 沙箱子系统
@ -134,7 +134,7 @@ src/agents/
└── ...
```
渠道特定的消息操作运行时现在位于插件自有扩展目录中,而不是 `src/agents/tools` 下,例如:
渠道特定的消息操作运行时代码现在位于各插件自有的扩展目录中,而不再位于 `src/agents/tools` 下,例如:
- Discord 插件操作运行时文件
- Slack 插件操作运行时文件
@ -143,7 +143,7 @@ src/agents/
## 核心集成流程
### 1. 运行嵌智能体
### 1. 运行嵌入式智能体
主入口是 `pi-embedded-runner/run.ts` 中的 `runEmbeddedPiAgent()`
@ -169,7 +169,7 @@ const result = await runEmbeddedPiAgent({
### 2. 创建会话
`runEmbeddedAttempt()`(由 `runEmbeddedPiAgent()` 调用)内部,使用 pi SDK
`runEmbeddedAttempt()`(由 `runEmbeddedPiAgent()` 调用)内部,使用 pi SDK
```typescript
import {
@ -225,39 +225,39 @@ const subscription = subscribeEmbeddedPiSession({
处理的事件包括:
- `message_start` / `message_end` / `message_update`(流式文本/thinking
- `message_start` / `message_end` / `message_update`(流式文本/思维
- `tool_execution_start` / `tool_execution_update` / `tool_execution_end`
- `turn_start` / `turn_end`
- `agent_start` / `agent_end`
- `compaction_start` / `compaction_end`
### 4. 提示输入
### 4. 发送提示
设置完成后,会向会话发送提示:
完成设置后,会向会话发送提示:
```typescript
await session.prompt(effectivePrompt, { images: imageResult.images });
```
SDK 会处理完整的 Agent loop发送给 LLM、执行工具调用、流式返回响应。
SDK 会处理完整的 Agent loop发送到 LLM、执行工具调用、流式传输响应。
图像注入是提示局部的OpenClaw 会从当前提示中加载图像引用,并仅通过该回合的 `images` 传入。它不会重新扫描更早的历史回合来重新注入图像载荷
图像注入是提示词局部的OpenClaw 会从当前提示词中加载图像引用,并仅通过 `images` 为当前这一轮传递。它不会重新扫描更早的历史轮次来重新注入图像负载
## 工具架构
### 工具流水线
1. **基础工具**pi 的 `codingTools`read、bash、edit、write
2. **自定义替换**OpenClaw 用 `exec`/`process` 替换 bash并为沙箱自定义 read/edit/write
3. **OpenClaw 工具**:消息、browser、canvas、sessions、cron、gateway
2. **自定义替换**OpenClaw 用 `exec`/`process` 替换 bash并为沙箱定制 read/edit/write
3. **OpenClaw 工具**:消息、浏览器、画布、会话、cron、Gateway 网关
4. **渠道工具**Discord/Telegram/Slack/WhatsApp 特定操作工具
5. **策略过滤**按配置档、provider、智能体、组、沙箱策略过滤工具
6. **Schema 规范化**:为 Gemini/OpenAI 的特殊情况清理 schema
7. **AbortSignal 包装**:为工具包装以支持 abort signal
5. **策略过滤**根据配置、提供商、智能体、群组、沙箱策略过滤工具
6. **Schema 标准化**:针对 Gemini/OpenAI 的特殊情况清理 schema
7. **AbortSignal 封装**:封装工具以遵循 Abort 信号
### 工具定义适配器
pi-agent-core 的 `AgentTool` 与 pi-coding-agent 的 `ToolDefinition``execute` 签名上不同。`pi-tool-definition-adapter.ts` 中的适配器会桥接两者
pi-agent-core 的 `AgentTool` 与 pi-coding-agent 的 `ToolDefinition``execute` 签名上不同。`pi-tool-definition-adapter.ts` 中的适配器负责桥接它们
```typescript
export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] {
@ -276,24 +276,24 @@ export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] {
### 工具拆分策略
`splitSdkTools()` 会通过 `customTools` 传入所有工具:
`splitSdkTools()` 通过 `customTools` 传递所有工具:
```typescript
export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) {
return {
builtInTools: [], // 为空。我们覆盖所有内容
builtInTools: [], // 为空。我们覆盖所有内容
customTools: toToolDefinitions(options.tools),
};
}
```
这可确保 OpenClaw 的策略过滤、沙箱集成和扩展工具集在不同 provider 间保持一致。
这可确保 OpenClaw 的策略过滤、沙箱集成和扩展工具集在各个提供商之间保持一致。
## 系统提示构建
## 系统提示构建
系统提示在 `buildAgentSystemPrompt()``system-prompt.ts`)中构建。它会组装一个完整提示,包含 Tooling、Tool Call Style、安全护栏、OpenClaw CLI 参考、Skills、文档、工作区、沙箱、消息、回复标签、语音、静默回复、心跳、运行时元数据,以及在启用时加入的 Memory 和 Reactions还可包含可选的上下文文件和额外系统提示内容。对于子智能体使用的最小提示模式会裁剪这些部分
系统提示`buildAgentSystemPrompt()``system-prompt.ts`)中构建。它会组装一个完整提示词,包含 Tooling、工具调用风格、安全护栏、OpenClaw CLI 参考、Skills、文档、工作区、沙箱、消息、回复标签、语气、静默回复、心跳、运行时元数据,以及在启用时包含的 Memory 和 Reactions还包括可选的上下文文件和额外系统提示词内容。对于子智能体使用的最小提示词模式会对这些部分进行裁剪
该提示会在会话创建后通过 `applySystemPromptOverrideToSession()` 应用:
系统提示词会在创建会话后通过 `applySystemPromptOverrideToSession()` 应用:
```typescript
const systemPromptOverride = createSystemPromptOverride(appendPrompt);
@ -304,17 +304,17 @@ applySystemPromptOverrideToSession(session, systemPromptOverride);
### 会话文件
会话是带树结构(通过 id/parentId 关联)的 JSONL 文件。pi 的 `SessionManager` 负责持久化:
会话是具有树状结构的 JSONL 文件(通过 id/parentId 链接)。pi 的 `SessionManager` 负责持久化:
```typescript
const sessionManager = SessionManager.open(params.sessionFile);
```
OpenClaw 会用 `guardSessionManager()` 对其进行包装,以保证工具结果安全。
OpenClaw 通过 `guardSessionManager()` 对其进行封装,以确保工具结果安全。
### 会话缓存
`session-manager-cache.ts` 会缓存 SessionManager 实例,以避免重复解析文件:
`session-manager-cache.ts` 会缓存 `SessionManager` 实例,以避免重复解析文件:
```typescript
await prewarmSessionFile(params.sessionFile);
@ -324,15 +324,15 @@ trackSessionManagerAccess(params.sessionFile);
### 历史记录限制
`limitHistoryTurns()` 会根据渠道类型(私信 vs 群组)裁剪对话历史
`limitHistoryTurns()` 会根据渠道类型(私信还是群组)裁剪会话历史记录
### 压缩
在上下文溢出时触发自动压缩。常见的溢出特征包括
自动压缩会在上下文溢出时触发。常见的溢出特征包括
`request_too_large`、`context length exceeded`、`input exceeds the
maximum number of tokens`、`input token count exceeds the maximum number of
input tokens`、`input is too long for the model`,以及 `ollama error: context
length exceeded`。`compactEmbeddedPiSessionDirect()` 处理手动压缩:
input tokens`、`input is too long for the model` `ollama error: context
length exceeded`。`compactEmbeddedPiSessionDirect()` 负责处理手动压缩:
```typescript
const compactResult = await compactEmbeddedPiSessionDirect({
@ -342,16 +342,16 @@ const compactResult = await compactEmbeddedPiSessionDirect({
## 认证与模型解析
### Auth Profiles
### 认证配置
OpenClaw 维护一个 auth profile 存储,为每个 provider 提供多个 API key
OpenClaw 维护一个认证配置存储,为每个提供商保存多个 API 密钥
```typescript
const authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
```
配置档会在失败时轮换,并跟踪冷却状态
配置会在失败时轮换,并带有冷却跟踪
```typescript
await markAuthProfileFailure({ store, profileId, reason, cfg, agentDir });
@ -392,11 +392,11 @@ if (fallbackConfigured && isFailoverErrorMessage(errorText)) {
## Pi 扩展
OpenClaw 会加载自定义 pi 扩展以实现特定行为:
OpenClaw 会加载自定义 pi 扩展以实现专门行为:
### 压缩保护
`src/agents/pi-hooks/compaction-safeguard.ts` 为压缩增加护栏,包括自适应 token 预算,以及工具失败和文件操作摘要:
`src/agents/pi-hooks/compaction-safeguard.ts` 会为压缩添加护栏,包括自适应 token 预算,以及工具失败和文件操作摘要:
```typescript
if (resolveCompactionMode(params.cfg) === "safeguard") {
@ -407,7 +407,7 @@ if (resolveCompactionMode(params.cfg) === "safeguard") {
### 上下文裁剪
`src/agents/pi-hooks/context-pruning.ts` 实现基于缓存 TTL 的上下文裁剪:
`src/agents/pi-hooks/context-pruning.ts` 实现基于缓存 TTL 的上下文裁剪:
```typescript
if (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") {
@ -433,18 +433,18 @@ const blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : n
### Thinking/Final 标签剥离
流式输出会经过处理,剥离 `<think>`/`<thinking>` 块并提取 `<final>` 内容:
流式输出会经过处理,剥离 `<think>`/`<thinking>` 块并提取 `<final>` 内容:
```typescript
const stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => {
// 剥离 <think>...</think> 内容
// 如果 enforceFinalTag,则只返回 <final>...</final> 内容
// 如果 enforceFinalTag 为 true返回 <final>...</final> 内容
};
```
### 回复指令
会解析并提取 `[[media:url]]`、`[[voice]]`、`[[reply:id]]` 回复指令:
会解析并提取诸如 `[[media:url]]`、`[[voice]]`、`[[reply:id]]` 之类的回复指令:
```typescript
const { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
@ -454,20 +454,20 @@ const { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDi
### 错误分类
`pi-embedded-helpers.ts` 会对错误进行分类,以便采取适当处理:
`pi-embedded-helpers.ts` 会对错误进行分类,以便执行适当处理:
```typescript
isContextOverflowError(errorText) // 上下文过大
isCompactionFailureError(errorText) // 压缩失败
isAuthAssistantError(lastAssistant) // 认证失败
isRateLimitAssistantError(...) // 遭遇速率限制
isFailoverAssistantError(...) // 应行故障转移
isRateLimitAssistantError(...) // 触发速率限制
isFailoverAssistantError(...) // 应行故障转移
classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "timeout" | ...
```
### Thinking 级别回退
如果某个 thinking 级别不受支持,会回退:
如果某个 thinking 级别不受支持,会回退:
```typescript
const fallbackThinking = pickFallbackThinkingLevel({
@ -482,7 +482,7 @@ if (fallbackThinking) {
## 沙箱集成
启用沙箱模式,工具和路径都会受到约束:
启用沙箱模式,工具和路径都会受到约束:
```typescript
const sandbox = await resolveSandboxContext({
@ -494,17 +494,17 @@ const sandbox = await resolveSandboxContext({
if (sandboxRoot) {
// 使用沙箱隔离的 read/edit/write 工具
// Exec 在容器中运行
// Browser 使用桥接 URL
// 浏览器使用 bridge URL
}
```
## Provider 特定处理
## 提供商特定处理
### Anthropic
- 拒绝魔法字符串清理
- 连续角色的回合验证
- 严格的上游 Pi 工具参数验
- 针对连续角色的轮次校验
- 严格的上游 Pi 工具参数
### Google/Gemini
@ -517,40 +517,40 @@ if (sandboxRoot) {
## TUI 集成
OpenClaw 还有一种本地 TUI 模式,会直接使用 pi-tui 组件:
OpenClaw 还提供本地 TUI 模式,可直接使用 pi-tui 组件:
```typescript
// src/tui/tui.ts
import { ... } from "@mariozechner/pi-tui";
```
这提供了与 pi 原生模式相似的交互式终端体验。
这提供了类似于 pi 原生模式的交互式终端体验。
## 与 Pi CLI 的关键差异
| 方面 | Pi CLI | OpenClaw 内嵌版 |
| --------------- | ----------------------- | ----------------------------------------------------------------------------------------------- |
| 调用方式 | `pi` 命令 / RPC | 通过 `createAgentSession()` 使用 SDK |
| 工具 | 默认编码工具 | 自定义 OpenClaw 工具套件 |
| 系统提示 | AGENTS.md + 提示 | 按渠道/上下文动态生成 |
| 会话存储 | `~/.pi/agent/sessions/` | `~/.openclaw/agents/<agentId>/sessions/`(或 `$OPENCLAW_STATE_DIR/agents/<agentId>/sessions/` |
| 认证 | 单一凭证 | 带轮换的多配置档 |
| 扩展 | 从磁盘加载 | 程序化 + 磁盘路径 |
| 事件处理 | TUI 渲染 | 基于回调(`onBlockReply` 等) |
| 方面 | Pi CLI | OpenClaw 嵌入式 |
| --------------- | ----------------------- | ---------------------------------------------------------------------------------------------- |
| 调用方式 | `pi` 命令 / RPC | 通过 `createAgentSession()` 使用 SDK |
| 工具 | 默认编码工具 | 自定义 OpenClaw 工具套件 |
| 系统提示词 | AGENTS.md + 提示词 | 按渠道/上下文动态生成 |
| 会话存储 | `~/.pi/agent/sessions/` | `~/.openclaw/agents/<agentId>/sessions/`(或 `$OPENCLAW_STATE_DIR/agents/<agentId>/sessions/` |
| 认证 | 单一凭证 | 支持轮换的多配置 |
| 扩展 | 从磁盘加载 | 以编程方式 + 磁盘路径加载 |
| 事件处理 | TUI 渲染 | 基于回调(`onBlockReply` 等) |
## 未来考虑
潜在的重构方向包括
潜在需要重构的领域
1. **工具签名对齐**当前需要在 pi-agent-core 和 pi-coding-agent 的签名之间适配
2. **会话管理器包装**`guardSessionManager` 增加了安全性,但也增加了复杂度
1. **工具签名对齐**目前仍在适配 pi-agent-core 与 pi-coding-agent 的签名差异
2. **Session manager 封装**`guardSessionManager` 增加了安全性,但也提高了复杂度
3. **扩展加载**:可以更直接地使用 pi 的 `ResourceLoader`
4. **流式处理器复杂度**`subscribeEmbeddedPiSession` 已变得较大
5. **Provider 特殊情况**:存在许多 provider 特定代码路径,这些将来可能由 pi 统一处理
4. **流式处理器复杂度**`subscribeEmbeddedPiSession` 已变得较大
5. **提供商特性差异**:存在许多提供商特定代码路径,未来可能由 pi 自身处理
## 测试
Pi 集成覆盖这些测试套件:
Pi 集成覆盖了以下测试套件:
- `src/agents/pi-*.test.ts`
- `src/agents/pi-auth-json.test.ts`
@ -568,7 +568,7 @@ Pi 集成覆盖这些测试套件:
- `src/agents/pi-embedded-runner-extraparams.live.test.ts`(启用 `OPENCLAW_LIVE_TEST=1`
有关当前运行命令,请参见 [Pi 开发工作流](/zh-CN/pi-dev)。
如需查看当前运行命令,请参见 [Pi 开发工作流](/zh-CN/pi-dev)。
## 相关内容

View File

@ -2,64 +2,63 @@
read_when:
- 重构渠道消息 UI、交互式负载或原生渠道渲染器
- 更改消息工具能力、投递提示或跨上下文标记
- 调试 Discord Carbon 导入扇出或渠道插件运行时加载
- 调试 Discord Carbon 导入扇出或渠道插件运行时惰性加载
summary: 将语义消息呈现与渠道原生 UI 渲染器解耦。
title: 渠道呈现重构计划
x-i18n:
generated_at: "2026-04-24T04:04:50Z"
generated_at: "2026-04-27T06:55:56Z"
model: gpt-5.4
provider: openai
source_hash: f983c4d14580e8a66744c7e5f23dd9846c11e926181a8441d60f346cec6d1eea
source_hash: 5608e7806a2a20e73ee82f1b1f0fcbbb4c865232df984d3d98b91e5b721998f5
source_path: plan/ui-channels.md
workflow: 15
---
## 状态
## Status
已为共享智能体、CLI、插件能力以及出站投递界面实现:
已为共享智能体、CLI、插件能力和出站投递表面完成实现:
- `ReplyPayload.presentation` 用于承载语义消息 UI。
- `ReplyPayload.delivery.pin` 用于承载已发送消息的置顶请求。
- 共享消息操作现在暴露 `presentation`、`delivery` 和 `pin`,而不是提供商原生的 `components`、`blocks`、`buttons` 或 `card`
- 核心通过插件声明的出站能力来渲染或自动降级消息呈现
- Discord、Slack、Telegram、Mattermost、Microsoft Teams 和 Feishu 渲染器均已接入通用契约。
- Discord 渠道控制平面代码不再导入基于 Carbon 的 UI 容器。
- `ReplyPayload.presentation` 承载语义消息 UI。
- `ReplyPayload.delivery.pin` 承载已发送消息的置顶请求。
- 共享消息操作暴露 `presentation`、`delivery` 和 `pin`,而不是提供商原生的 `components`、`blocks`、`buttons` 或 `card`
- Core 通过插件声明的出站能力来渲染或自动降级 presentation
- Discord、Slack、Telegram、Mattermost、MS Teams 和 Feishu 渲染器会消费这一通用契约。
- Discord 渠道控制平面代码不再导入由 Carbon 支持的 UI 容器。
规范文档现位于 [Message Presentation](/zh-CN/plugins/message-presentation)。
请将本计划保留为历史实现背景;如果契约、渲染器或回退行为发生变化,
请更新该规范指南。
规范文档现位于 [消息呈现](/zh-CN/plugins/message-presentation)。
请将此计划保留为历史实现背景;如契约、渲染器或回退行为发生变化,请更新规范指南。
## 问题
## Problem
当前的渠道 UI 分散在多个不兼容的界面中:
渠道 UI 当前分散在多个彼此不兼容的表面中:
- 核心通过 `buildCrossContextComponents` 拥有一个偏向 Discord 形态的跨上下文渲染钩子。
- Discord `channel.ts` 可以导入原生 Carbon UI,例如 `DiscordUiContainer`,这会将运行时 UI 依赖拉入渠道插件控制平面。
- 智能体和 CLI 暴露了原生负载逃逸口,例如 Discord `components`、Slack `blocks`、Telegram 或 Mattermost `buttons`,以及 Teams 或 Feishu `card`
- `ReplyPayload.channelData` 同时承载传输提示和原生 UI 封
- 通用 `interactive` 模型已经存在,但它比 Discord、Slack、Teams、Feishu、LINE、Telegram 和 Mattermost 已经使用的更丰富布局窄。
- Core 通过 `buildCrossContextComponents` 拥有一个具备 Discord 形态的跨上下文渲染器钩子。
- Discord `channel.ts` 可以导入原生 Carbon UI(通过 `DiscordUiContainer`,这会将运行时 UI 依赖拉入渠道插件控制平面。
- 智能体和 CLI 暴露了原生负载逃生口,例如 Discord 的 `components`、Slack 的 `blocks`、Telegram 或 Mattermost 的 `buttons`,以及 Teams 或 Feishu 的 `card`
- `ReplyPayload.channelData` 同时承载传输提示和原生 UI 封。
- 通用 `interactive` 模型已经存在,但它比 Discord、Slack、Teams、Feishu、LINE、Telegram 和 Mattermost 已经使用的更丰富布局窄。
这使核心感知了原生 UI 形态,削弱了插件运行时懒加载能力,也让智能体拥有了过多提供商专属方式来表达相同的消息意图。
这使得 Core 需要感知原生 UI 形状,削弱了插件运行时的惰性加载,并让智能体拥有过多提供商特定的方式来表达相同的消息意图。
## 目标
## Goals
- 核心根据声明的能力决定消息的最佳语义呈现方式。
- 扩展声明能力,并将语义呈现渲染为原生传输负载。
- Core 根据声明的能力决定消息的最佳语义呈现方式。
- 扩展声明能力,并将语义呈现渲染为原生传输负载。
- Web 控制 UI 与聊天原生 UI 保持分离。
- 共享智能体或 CLI 消息界面不暴露原生渠道负载
- 不受支持的呈现功能自动降级为最佳文本表示。
- 诸如置顶已发送消息之类的投递行为属于通用投递元数据,而不是呈现。
- 原生渠道负载不通过共享智能体或 CLI 消息表面暴露
- 不受支持的呈现特性会自动降级为最佳文本表示。
- 诸如置顶已发送消息之类的投递行为属于通用投递元数据,而不是呈现。
## 非目标
## Non goals
- 不为 `buildCrossContextComponents` 提供向后兼容 shim
- 不公开 `components`、`blocks`、`buttons` 或 `card` 这类原生逃逸口。
- 核心不导入渠道原生 UI 库。
- 不为内置渠道提供提供商专属 SDK 接缝。
- 不为 `buildCrossContextComponents` 提供向后兼容垫片
- 不`components`、`blocks`、`buttons` 或 `card` 提供公共原生逃生口。
- Core 不导入渠道原生 UI 库。
- 不为内置渠道提供提供商特定的 SDK 接缝。
## 目标模型
## Target model
`ReplyPayload` 添加一个由核心拥有的 `presentation` 字段。
`ReplyPayload` 添加一个由 Core 拥有的 `presentation` 字段。
```ts
type MessagePresentationTone = "neutral" | "info" | "success" | "warning" | "danger";
@ -90,17 +89,17 @@ type MessagePresentationOption = {
};
```
在迁移过程中,`interactive` 会变成 `presentation` 的一个子集:
在迁移期间,`interactive` 会成为 `presentation` 的一个子集:
- `interactive` 文本块映射到 `presentation.blocks[].type = "text"`
- `interactive` 按钮块映射到 `presentation.blocks[].type = "buttons"`
- `interactive` 选择块映射到 `presentation.blocks[].type = "select"`
外部智能体和 CLI schema 现在使用 `presentation``interactive` 仍作为现有回复生成器的内部遗留解析 / 渲染辅助器保留
外部智能体和 CLI schema 现在使用 `presentation``interactive` 仍保留为内部遗留解析/渲染辅助,以支持现有 reply 生产者
## 投递元数据
## Delivery metadata
非 UI 的发送行为添加一个由核心拥有的 `delivery` 字段。
不属于 UI 的发送行为添加一个由 Core 拥有的 `delivery` 字段。
```ts
type ReplyPayloadDelivery = {
@ -118,14 +117,14 @@ type ReplyPayloadDelivery = {
- `delivery.pin = true` 表示置顶第一条成功投递的消息。
- `notify` 默认值为 `false`
- `required` 默认值为 `false`对于不支持的渠道或置顶失败的情况,会自动降级并继续投递。
- 手动 `pin`、`unpin` 和 `list-pins` 消息操作仍用于现有消息。
- `required` 默认值为 `false`不支持的渠道或置顶失败时会自动降级,继续完成投递。
- 手动 `pin`、`unpin` 和 `list-pins` 消息操作仍保留,用于现有消息。
当前的 Telegram ACP 话题绑定应从 `channelData.telegram.pin = true` 移至 `delivery.pin = true`
当前 Telegram ACP 主题绑定应从 `channelData.telegram.pin = true` 迁移到 `delivery.pin = true`
## 运行时能力契约
## Runtime capability contract
呈现和投递渲染钩子添加到运行时出站适配器中,而不是控制平面渠道插件中。
presentation 和 delivery 渲染钩子添加到运行时出站适配器,而不是控制平面渠道插件中。
```ts
type ChannelPresentationCapabilities = {
@ -163,16 +162,16 @@ type ChannelOutboundAdapter = {
};
```
核心行为:
Core 行为:
- 解析目标渠道和运行时适配器。
- 查询其呈现能力。
- 在渲染前对不受支持的块进行降级
- 查询 presentation 能力。
- 在渲染前降级不受支持的块
- 调用 `renderPresentation`
- 如果没有渲染器,则将呈现转换为文本回退。
- 成功发送后,当请求 `delivery.pin` 且渠道支持时,调用 `pinDeliveredMessage`
- 如果不存在渲染器,则将 presentation 转换为文本回退。
- 成功发送后,当请求 `delivery.pin` 且渠道支持时,调用 `pinDeliveredMessage`
## 渠道映射
## Channel mapping
Discord
@ -187,27 +186,27 @@ Slack
Telegram
- 将 text、context 和 dividers 渲染为文本。
- 在已配置且目标界面允许时,将 actions 和 select 渲染为内联键盘。
- 在禁用内联按钮时使用文本回退。
- 将 ACP 题置顶迁移到 `delivery.pin`
- 将 text、context 和 divider 渲染为文本。
- 在配置允许且目标表面支持时,将 actions 和 select 渲染为内联键盘。
- 当内联按钮被禁用时使用文本回退。
- 将 ACP 题置顶迁移到 `delivery.pin`
Mattermost
- 在配置时将 actions 渲染为交互按钮。
- 其他块使用文本回退。
- 在配置允许时将 actions 渲染为交互按钮。
- 其他块渲染为文本回退。
Microsoft Teams
MS Teams
- 将 `presentation` 渲染为 Adaptive Cards。
- 保留手动 pin / unpin / list-pins 操作。
- 如果 Graph 对目标会话的支持足够可靠,可选择实现 `pinDeliveredMessage`
- 保留手动 pin/unpin/list-pins 操作。
- 如果目标会话的 Graph 支持可靠,可选择实现 `pinDeliveredMessage`
Feishu
- 将 `presentation` 渲染为交互卡片。
- 保留手动 pin / unpin / list-pins 操作。
- 如果 API 行为足够可靠,可选择实现用于已发送消息置顶的 `pinDeliveredMessage`
- 将 `presentation` 渲染为交互卡片。
- 保留手动 pin/unpin/list-pins 操作。
- 如果 API 行为可靠,可选择为已发送消息置顶实现 `pinDeliveredMessage`
LINE
@ -215,50 +214,50 @@ LINE
- 对不支持的块回退为文本。
- 从 `channelData` 中移除 LINE UI 负载。
纯文本或能力限的渠道:
纯文本或能力限的渠道:
- 使用保守格式将 presentation 转换为文本。
## 重构步骤
## Refactor steps
1. 重新应用 Discord 发布修复:从基于 Carbon 的 UI 中拆分 `ui-colors.ts`,并从 `extensions/discord/src/channel.ts` 中移除 `DiscordUiContainer`
2. `ReplyPayload`、出站负载规范化、投递摘要和 hook 负载中添加 `presentation``delivery`
3. 在一个窄范围的 SDK / 运行时子路径中添加 `MessagePresentation` schema 和解析辅助函数。
4. 用语义化呈现能力替换消息能力中的 `buttons`、`cards`、`components` 和 `blocks`
5. 为呈现渲染和投递置顶添加运行时出站适配器钩子。
6. 用 `buildCrossContextPresentation` 替换跨上下文组件构建逻辑
1. 重新应用 Discord 发布修复,将 `ui-colors.ts` 从由 Carbon 支持的 UI 中拆分出来,并从 `extensions/discord/src/channel.ts` 中移除 `DiscordUiContainer`
2. `presentation``delivery` 添加到 `ReplyPayload`、出站负载规范化、投递摘要和钩子负载中
3. 在一个窄的 SDK/运行时子路径中添加 `MessagePresentation` schema 和解析辅助函数。
4. 用语义 presentation 能力替换消息能力中的 `buttons`、`cards`、`components` 和 `blocks`
5. 为 presentation 渲染和 delivery 置顶添加运行时出站适配器钩子。
6. 用 `buildCrossContextPresentation` 替换跨上下文组件构
7. 删除 `src/infra/outbound/channel-adapters.ts`,并从渠道插件类型中移除 `buildCrossContextComponents`
8. 修改 `maybeApplyCrossContextMarker`,使其附加 `presentation`不是原生参数。
9. 更新插件分发发送路径,使其只消费语义化呈现和投递元数据。
8. 修改 `maybeApplyCrossContextMarker`,使其附加 `presentation`原生参数。
9. 更新插件分发发送路径,使其仅消费语义 presentation 和 delivery 元数据。
10. 移除智能体和 CLI 的原生负载参数:`components`、`blocks`、`buttons` 和 `card`
11. 移除创建原生 message-tool schema 的 SDK 辅助函数,替换为 presentation schema 辅助函数。
12. 从 `channelData` 中移除 UI / 原生封;在审查每个剩余字段前,仅保留传输元数据。
13. 迁移 Discord、Slack、Telegram、Mattermost、Microsoft Teams、Feishu 和 LINE 渲染器。
14. 更新 message CLI、渠道页面、插件 SDK 和能力扩展手册文档。
11. 移除用于创建原生消息工具 schema 的 SDK 辅助函数,改为使用 presentation schema 辅助函数。
12. 从 `channelData` 中移除 UI/原生封;在审查每个剩余字段前,仅保留传输元数据。
13. 迁移 Discord、Slack、Telegram、Mattermost、MS Teams、Feishu 和 LINE 渲染器。
14. 更新消息 CLI、渠道页面、插件 SDK 和能力扩展手册文档。
15. 对 Discord 和受影响的渠道入口点运行导入扇出分析。
本次重构中,第 1-11 步以及第 13-14 步已为共享智能体、CLI、插件能力和出站适配器契约完成实现。第 12 步仍是针对提供商私有 `channelData` 传输封装的更深层内部清理工作。第 15 步仍属于后续验证项,前提是我们希望获得超出类型 / 测试门禁之外的量化导入扇出数据。
此次重构中,步骤 1-11 和 13-14 已针对共享智能体、CLI、插件能力和出站适配器契约实现。步骤 12 仍是针对提供商私有 `channelData` 传输信封的更深入内部清理工作。步骤 15 仍作为后续验证,前提是我们希望获得超出类型/测试门禁之外的量化导入扇出数据。
## 测试
## Tests
添加或更新:
- Presentation 规范化测试。
- 针对不受支持块的 presentation 自动降级测试。
- 针对插件分发和核心投递路径的跨上下文标记测试。
- 针对 Discord、Slack、Telegram、Mattermost、Microsoft Teams、Feishu、LINE 和文本回退的渠道渲染矩阵测试。
- 面向插件分发和 Core 投递路径的跨上下文标记测试。
- 针对 Discord、Slack、Telegram、Mattermost、MS Teams、Feishu、LINE 和文本回退的渠道渲染矩阵测试。
- 证明原生字段已移除的消息工具 schema 测试。
- 证明原生标志已移除的 CLI 测试。
- 覆盖 Carbon 的 Discord 入口点导入懒加载回归测试。
- 覆盖 Telegram 和通用回退的投递置顶测试。
- 针对 Carbon 的 Discord 入口点导入惰性回归测试。
- 涵盖 Telegram 和通用回退的 delivery 置顶测试。
## 未决问题
## Open questions
- `delivery.pin` 是否应在第一阶段就为 Discord、Slack、Microsoft Teams 和 Feishu 实现,还是先只做 Telegram
- `delivery` 最终是否应吸收现有字段,例如 `replyToId`、`replyToCurrent`、`silent` 和 `audioAsVoice`,还是继续聚焦于发送后行为?
- presentation 是否应直接支持图片或文件引用,还是媒体暂时继续与 UI 布局分离?
- 第一阶段是否应为 Discord、Slack、MS Teams 和 Feishu 实现 `delivery.pin`,还是仅先支持 Telegram
- `delivery` 最终是否应吸收现有字段,例如 `replyToId`、`replyToCurrent`、`silent` 和 `audioAsVoice`,还是继续聚焦于发送后行为?
- Presentation 是否应直接支持图片或文件引用,还是媒体暂时仍与 UI 布局分离?
## 相关内容
## Related
- [渠道概览](/zh-CN/channels)
- [消息呈现](/zh-CN/plugins/message-presentation)

View File

@ -1,25 +1,25 @@
---
read_when:
- 添加或修改消息卡片、按钮或选择器渲染
- 构建支持富出站消息的渠道插件
- 构建支持富出站消息的渠道插件
- 更改消息工具的呈现方式或投递能力
- 调试提供商特定的卡片 / 块 / 组件渲染回归问题
summary: 渠道插件的语义化消息卡片、按钮、选择器、后备文本和投递提示
- 调试提供商特定的卡片 / 块 / 组件渲染回归问题
summary: 渠道插件的语义化消息卡片、按钮、选择器、回退文本和投递提示
title: 消息呈现
x-i18n:
generated_at: "2026-04-24T03:06:50Z"
generated_at: "2026-04-27T06:55:59Z"
model: gpt-5.4
provider: openai
source_hash: 1c8c3903101310de330017b34bc2f0d641f4c8ea2b80a30532736b4409716510
source_hash: 23ef0eab890ee174c1433f72e84932a84a481f2bcf4b69bc793a2660ec94b10c
source_path: plugins/message-presentation.md
workflow: 15
---
消息呈现是 OpenClaw 用于富出站聊天 UI 的共享契约。
消息呈现是 OpenClaw 用于富出站聊天 UI 的共享契约。
它让智能体、CLI 命令、审批流程和插件只需描述一次消息意图,
而每个渠道插件都可以尽可能渲染为最佳的原生形态。
同时每个渠道插件都可以尽可能渲染出最合适的原生形态。
对可移植的消息 UI,请使用 presentation
对可移植的消息 UI 使用 presentation
- 文本区块
- 简短的上下文 / 页脚文本
@ -28,12 +28,12 @@ x-i18n:
- 选择菜单
- 卡片标题和语气
不要向共享消息工具中添加新的提供商原生字段,例如 Discord `components`、Slack
`blocks`、Telegram 的 `buttons`、Teams 的 `card` 或 Feishu 的 `card`。这些字段是由渠道插件负责生成的渲染输出。
不要向共享消息工具中添加新的提供商原生字段,例如 Discord `components`、Slack
`blocks`、Telegram `buttons`、Teams `card` 或 Feishu `card`。这些都是由渠道插件负责的渲染器输出。
## 契约
插件作者从以下位置导入公契约:
插件作者从以下位置导入公契约:
```ts
import type {
@ -84,17 +84,17 @@ type ReplyPayloadDelivery = {
按钮语义:
- `value` 是应用动作值;当渠道支持可点击控件时,它会通过该渠道现有的交互路径路由回来。
- `url` 是链接按钮。它可以在没有 `value` 的情况下存在。
- `label` 是必填项,也会用于文本后备内容
- `style`提示性信息。渲染器应将不支持的样式映射到安全的默认值,而不是导致发送失败。
- `url` 是链接按钮。它可以在没有 `value` 的情况下单独存在。
- `label` 是必填项,也会用于文本回退
- `style`建议性的。渲染器应将不受支持的样式映射为安全的默认值,而不是让发送失败。
选择器语义:
- `options[].value` 是被选中的应用值。
- `placeholder`提示性信息;对于没有原生选择器支持的渠道,可能会被忽略
- 如果某个渠道不支持选择器,后备文本会列出这些标签。
- `placeholder`建议性的,原生不支持选择器的渠道可以忽略它
- 如果某个渠道不支持选择器,回退文本会列出这些标签。
## 生产示例
## 生产示例
简单卡片:
@ -116,7 +116,7 @@ type ReplyPayloadDelivery = {
}
```
仅 URL 的链接按钮:
URL 的链接按钮:
```json
{
@ -166,7 +166,7 @@ openclaw message send --channel telegram \
--pin
```
使用显式 JSON 的置顶投递:
显式 JSON 的置顶投递:
```json
{
@ -204,8 +204,8 @@ const adapter: ChannelOutboundAdapter = {
};
```
能力字段刻意保持为简单的布尔值。它们描述的是渲染器可以交互化呈现什么
而不是每一个原生平台限制。渲染器仍然负责处理平台特定限制,例如最大按钮数、区块数和卡片大小。
能力字段刻意保持为简单布尔值。它们描述的是渲染器能将哪些内容做成交互式
而不是每一个原生平台限制。渲染器仍然负责处理平台特定限制,例如最大按钮数、区块数和卡片大小。
## 核心渲染流程
@ -214,36 +214,36 @@ const adapter: ChannelOutboundAdapter = {
1. 规范化 presentation 载荷。
2. 解析目标渠道的出站适配器。
3. 读取 `presentationCapabilities`
4. 当适配器能够渲染该载荷时,调用 `renderPresentation`
5. 当适配器不存在或无法渲染时,回退为保守的文本。
6. 通过正常的渠道投递路径发送结果载荷。
4. 当适配器可以渲染该载荷时,调用 `renderPresentation`
5. 当适配器缺失或无法渲染时,回退为保守的文本。
6. 通过正常的渠道投递路径发送生成的载荷。
7. 在第一条消息成功发送后,应用诸如 `delivery.pin` 之类的投递元数据。
核心负责后备行为,因此生产者可以保持渠道无关。渠道插件则负责原生渲染和交互处理。
核心负责回退行为,因此生产方可以保持渠道无关。渠道插件则负责原生渲染和交互处理。
## 降级规则
Presentation 必须能在受限渠道上安全发送
Presentation 必须能安全地发送到能力受限的渠道
后备文本包括
回退文本包含
- `title` 作为第一行
- `text` 区块作为普通段落
- `context` 区块作为紧凑的上下文行
- `divider` 区块作为视觉分隔符
- 按钮标签,对于链接按钮还包括 URL
- 选择器选项标签
- 第一行的 `title`
- 作为普通段落的 `text` 区块
- 作为紧凑上下文行的 `context` 区块
- 作为可视分隔符的 `divider` 区块
- 按钮标签,包括链接按钮的 URL
- 选择项标签
不受支持的原生控件应降级处理,而不是导致整个发送失败。
不受支持的原生控件应当降级,而不是让整次发送失败。
示例:
- 当 Telegram 的内联按钮被禁用时,会发送文本后备内容
- 没有选择器支持的渠道会将选择器选项列为文本。
- 仅 URL 按钮会变成原生链接按钮,或者变成后备 URL 行
- 非必需的置顶失败不会导致已投递的消息失败。
- 当 Telegram 的内联按钮被禁用时,发送文本回退
- 不支持选择器的渠道会将选择项列为文本。
- 仅含 URL 的按钮会变成原生链接按钮,或者回退为一行 URL 文本
- 可选的置顶失败不会让已投递的消息失败。
主要例外是 `delivery.pin.required: true`;如果置顶被请求为必需,
而渠道无法置顶已发送消息,则投递会报告失败。
主要例外是 `delivery.pin.required: true`;如果请求将置顶设为必需,
渠道无法置顶已发送消息,则投递会报告失败。
## 提供商映射
@ -251,36 +251,35 @@ Presentation 必须能在受限渠道上安全发送。
| 渠道 | 原生渲染目标 | 说明 |
| --------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Discord | Components 和组件容器 | 为现有提供商原生载荷生产者保留旧版 `channelData.discord.components`,但新的共享发送应使用 `presentation`。 |
| Slack | Block Kit | 为现有提供商原生载荷生产保留旧版 `channelData.slack.blocks`,但新的共享发送应使用 `presentation`。 |
| Telegram | 文本加内联键盘 | 按钮 / 选择器需要目标表面支持内联按钮能力;否则使用文本后备。 |
| Discord | Components 和 component containers | 为现有提供商原生载荷生产方保留旧版 `channelData.discord.components`,但新的共享发送应使用 `presentation`。 |
| Slack | Block Kit | 为现有提供商原生载荷生产保留旧版 `channelData.slack.blocks`,但新的共享发送应使用 `presentation`。 |
| Telegram | 文本加内联键盘 | 按钮 / 选择器要求目标表面具备内联按钮能力;否则会使用文本回退。 |
| Mattermost | 文本加交互式 props | 其他区块会降级为文本。 |
| Microsoft Teams | Adaptive Cards | 当同时提供普通 `message` 文本和卡片时,普通 `message` 文本会一并包含。 |
| Feishu | 交互式卡片 | 卡片头部可使用 `title`;正文会避免重复该标题。 |
| 普通渠道 | 文本后备 | 没有渲染器的渠道仍会获得可读输出。 |
| Microsoft Teams | Adaptive Cards | 当同时提供普通 `message` 文本和卡片时,卡片中会包含普通 `message` 文本。 |
| Feishu | 交互式卡片 | 卡片头部可使用 `title`;正文会避免重复该标题。 |
| 纯文本渠道 | 文本回退 | 即使没有渲染器的渠道,也仍能获得可读输出。 |
提供商原生载荷兼容性只是为现有 reply 生产者提供的过渡便利。
这并不是向共享原生字段中添加新字段的理由。
对提供商原生载荷的兼容性,是为现有 reply 生产方提供的过渡性便利。
这并不是添加新的共享原生字段的理由。
## Presentation 与 InteractiveReply
`InteractiveReply` 是较早的内部子集,供审批和交互辅助工具使用。
它支持:
`InteractiveReply` 是旧的内部子集,供审批和交互辅助工具使用。它支持:
- 文本
- 按钮
- 选择器
`MessagePresentation`规范的共享发送契约。它新增了:
`MessagePresentation`标准的共享发送契约。它新增了:
- 标题
- 语气
- 上下文
- 分隔线
- 仅 URL 按钮
- 仅 URL 按钮
- 通过 `ReplyPayload.delivery` 提供的通用投递元数据
在桥接旧代码时,使用 `openclaw/plugin-sdk/interactive-runtime` 中的辅助工具
在桥接旧代码时,使用 `openclaw/plugin-sdk/interactive-runtime` 中的辅助函数
```ts
import {
@ -295,34 +294,33 @@ import {
## 投递置顶
置顶属于投递行为,不属于 presentation。请使用 `delivery.pin`,而不是
`channelData.telegram.pin` 之类的提供商原生字段。
置顶是投递行为,不是呈现。使用 `delivery.pin`,而不是提供商原生字段,例如 `channelData.telegram.pin`
语义:
- `pin: true` 会置顶第一条成功投递的消息。
- `pin.notify` 默认为 `false`
- `pin.required` 默认为 `false`
- 非必需的置顶失败会降级处理,并保留已发送消息不变。
- 可选的置顶失败会降级,并保留已发送消息不变。
- 必需的置顶失败会导致投递失败。
- 分块消息会置顶第一个已投递分块,而不是尾分块。
- 分块流式传输消息会置顶第一个已投递分块,而不是尾分块。
对于提供商支持这些操作的现有消息,手动 `pin`、`unpin` 和 `pins` 消息动作仍然存在。
## 插件作者检查清单
- 当渠道能够渲染或安全降级语义化 presentation 时,在 `describeMessageTool(...)` 中声明 `presentation`
- 向运行时出站适配器添加 `presentationCapabilities`
- 当渠道可以渲染或安全降级语义化 presentation 时,在 `describeMessageTool(...)` 中声明 `presentation`
- `presentationCapabilities` 添加到运行时出站适配器
- 在运行时代码中实现 `renderPresentation`,而不是在控制平面插件设置代码中实现。
- 不要在高频的设置 / 目录路径中引入原生 UI 库
- 在渲染器和测试中保留平台限制处理
- 为不支持的按钮、选择器、URL 按钮、标题 / 文本重复,以及混合 `message``presentation` 发送添加后备测试。
- 仅当提供商可以置顶已发送消息 id 时,才通过 `deliveryCapabilities.pin``pinDeliveredMessage` 添加置顶投递支持。
- 不要通过共享消息动作 schema 暴露新的提供商原生卡片 / 区块 / 组件 / 按钮字段。
- 不要将原生 UI 库放入高频的设置 / 目录路径中
- 在渲染器和测试中保留平台限制。
- 为不支持的按钮、选择器、URL 按钮、标题 / 文本重复,以及混合 `message``presentation` 发送添加回退测试。
- 仅当提供商能够置顶已发送消息 id 时,才通过 `deliveryCapabilities.pin``pinDeliveredMessage` 添加置顶投递支持。
- 不要通过共享消息动作 schema 暴露新的提供商原生 card / block / component / button 字段。
## 相关文档
- [Message CLI](/zh-CN/cli/message)
- [消息 CLI](/zh-CN/cli/message)
- [插件 SDK 概览](/zh-CN/plugins/sdk-overview)
- [插件架构](/zh-CN/plugins/architecture-internals#message-tool-schemas)
- [渠道呈现重构计划](/zh-CN/plan/ui-channels)