--- name: openclaw-a2ui description: > 为 OpenClaw webchat 回复增加个性化富 UI 展示,基于 HTML 直出渲染。 【默认启用】凡是结构化内容(列表、数据、步骤、表格、摘要、状态、代码等)一律用 HTML 卡片回复。 纯文字聊天(简单问答、闲聊)不强制套卡片。 当用户要求安装/迁移 openclaw-a2ui、启用 HTML 渲染、配置 DOMPurify 白名单扩展、 安装 skill-ui-bridge plugin,或排查 webchat 中 HTML 不渲染的问题时,参考底部安装章节。 --- # openclaw-a2ui > **本技能已验证(2026-03-18):style / div / grid / flex / table / img / svg 全部渲染正常。** > **除非用户要求纯文字,否则所有结构化内容必须用 HTML 卡片输出。** ### Changelog - **v1.0.2(2026-03-18)**:骨架屏优化 - 骨架插入到 `.chat-text` 直接父节点(气泡本身),并设 `inline-block + min-width: 320px` 撑开气泡 - `.sui-skeleton` 固定 `width: 320px; display: block`,解决 inline-block 气泡宽度塌陷问题 - 骨架行结构调整:标题行 12px / 正文行 8px / 底部两段不等宽细线,比例更自然 - 移除骨架时还原气泡 `display` 和 `minWidth` - **v1.0.1(2026-03-09)**:流式骨架屏 + 淡入动画,findBubble 隐藏整体气泡 - **v1.0.0(待更新)**:**单卡片模式** - 默认所有结构化回复使用单一 CompositeCard 统一承载,减少多卡片的视觉碎片化。 --- ## ⚠️ HTML 不渲染?先看这里 如果 webchat 中 HTML 被显示为纯文本、标签被转义、或样式无效,**不要尝试手动修改 DOMPurify 配置**。根本原因是 `skill-ui-bridge` 插件未安装,解决方式: | 现象 | 原因 | 解决方式 | |------|-- |------| | HTML 标签显示为文本(如 `<div>`) | marked.js 未开启 rawHTML | 安装 skill-ui-bridge 插件(见底部安装章节) | | 样式被剥离,只剩裸文字/标签 | DOMPurify 未 patch,style/div 等被过滤 | 安装 skill-ui-bridge 插件(见底部安装章节) | | 部分标签渲染,部分不渲染 | 插件未加载成功 | 检查安装验证步骤 5、6 | `skill-ui-bridge` 插件安装后会**自动** patch DOMPurify 和 marked.js,无需手动配置白名单。 --- ## 触发规则(优先级由高到低) | 场景 | 处理方式 | |------|-- | | 结构化内容(列表、步骤、数据、表格、统计、对比、状态) | ✅ **必须用单一卡片显示,无文本前后缀** | | 有标题 + 正文的摘要/说明 | ✅ **用单一 CompositeCard 承载所有内容**(单卡片模式) | | 代码 + 说明 | ✅ **优先用单一 CodeCard**,必要时在 Card内嵌入代码块 | | 简单一句话回答 | ⚪ 纯文字即可 | | 用户明确说"纯文字"/"不要卡片" | ❌ 不用卡片 | > **💡 单卡片模式强制规则:** > > **所有结构化内容必须只用卡片显示,不要有文本 + 卡片的组合形式。** > > - ✅ **正确**:所有内容(标题、要点、数据)都在一个 CompositeCard 内展示 > - ❌ **错误**:先写一段文字说明,再跟一个卡片 > - ❌ **错误**:卡片后再追加额外解释性文本 > > **目标:**每张回复只出现一张卡片(或无卡片),避免视觉碎片化和信息重复。 > > 例如: > ```markdown > ❌ 错误写法(多元素组合): > 这是关于 AI Agent 的最新趋势,请查看下方卡片。 > >
... > > 以上数据截至 3 月 18 日。 > > --- > > ✅ 正确写法(单卡片模式): >
> > > > >
> ``` --- ## 输出方式(唯一方式) 直接在回复正文中输出 HTML,**不要包裹在代码块里**,webchat 会直接渲染。 ### ⚠️ 强制要求:每张卡片最外层必须带 `class="a2ui"` skill-ui-bridge 通过检测 `class="a2ui"` 识别需要渲染的 HTML,**缺少此 class 的卡片不会被渲染**。 ```html
卡片内容
``` ### ⚠️ 关键规则:HTML 与文字必须分段 marked.js 在解析时,如果 HTML 和普通文字混在同一段落,会把 HTML 标签转义成文本显示。 **❌ 错误写法(HTML 夹在文字中间):** ``` 以下是热榜内容:
感兴趣可以点击查看。 ``` **✅ 正确写法(HTML 单独成段,前后空行隔开):** ``` 以下是热榜内容:
感兴趣可以点击查看。 ``` 规则: - HTML 卡片前后必须有**空行**(不能紧跟文字) - 文字说明放在卡片**之前**或**之后**,单独成段 - **单卡片模式优先**:多卡片连续输出时,考虑合并为一个 CompositeCard --- ## 设计规范(所有卡片统一) ``` 背景: #ffffff 圆角: 12px(卡片)/ 8px(内部元素)/ 999px(badge/tag) 阴影: 0 2px 12px rgba(0,0,0,0.08) 主色: #5865f2(蓝紫) 成功: #22c55e 警告: #f59e0b 错误: #ef4444 信息: #3b82f6 标题色: #1a1a2e 正文色: #374151 说明色: #6b7280 分割线: #f0f0f0 底色块: #f8fafc 最大宽: 600px 外边距: margin:8px 0 字体: -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif ``` --- ## 卡片模板速查 ### TextCard — 文字摘要 ```html
【标题】

【正文内容】

``` ### ListCard — 列表/要点 ```html
【标题】
``` ### DataCard — 键值对 / 参数 ```html
【标题】 【状态 badge,可选】

【字段名】 【字段值】
``` ### StatsCard — 统计数字 ```html
【标题】
【数字】
【说明】
``` ### AlertCard — 提示/警告/成功/错误 ```html
ℹ️
【标题】
【内容】
``` ### StepsCard — 步骤流程 ```html
【标题】
1
【步骤标题】
【步骤说明】
N
【最后步骤】
【说明】
``` ### TableCard — 数据表格 ```html
【标题】
【列名】
【值】
``` Badge 色值参考: - 成功/完成:`background:#dcfce7;color:#16a34a` - 进行中:`background:#fef9c3;color:#b45309` - 失败/错误:`background:#fee2e2;color:#b91c1c` - 中性/待定:`background:#f1f5f9;color:#475569` ### ProgressCard — 进度条 ```html
【标题】
【项目名】 【百分比】
``` ### CompositeCard — **推荐:单一复合卡片(承载所有内容)** **✅ 单卡片模式最佳实践示例:** ```html
🔥 今日热门新闻精选
3 月 18 日 • AI | 国际局势 | 国家发展 | 体育快讯
📰 国际焦点
中东冲突升级:以军击毙伊朗高级官员,霍尔木兹海峡受阻影响全球能源

以色列国防部长宣称在空袭中击毙两名伊朗高级官员,其中包括前核谈判战略顾问拉里贾尼和志愿民兵指挥官苏莱曼尼。受霍尔木兹海峡袭击影响,全球油价大幅上涨,布伦特原油突破100美元/桶。

📍 来源:新华社/央视新闻
💻 科技前沿
AI技术迎来重大突破:英伟达推开源AI代理平台,阿里巴巴发布"悟空"AI工作平台

英伟达推出开源AI代理平台NemoClaw,预测业务规模有望突破1万亿美元。阿里巴巴发布全球首个企业原生AI工作平台"悟空",将嵌入钉钉。

📍 来源:财新/36氪
🔗 查看详情 ⚙️ 更多选项
``` ### CodeCard — 代码展示 ```html
【语言,如 bash / python / typescript】
【代码内容】
``` ### ImageCard — 图片展示 ```html
【描述】
【标题】
【说明】
``` --- ## 组合使用与最佳实践 ### ✅ **单卡片模式(推荐)** - 所有内容放入一个 CompositeCard,用子模块划分信息块 - 减少视觉碎片化,提升阅读体验 - 适合:新闻汇总、报告摘要、任务清单等多元素场景 ```html
标题区域
模块1: 国际焦点
模块2: 科技前沿
模块3: 国家发展
底部标签栏
``` ### ⚠️ **多卡片模式(特殊需求时使用)** - 仅在特殊需求时使用:如独立代码块 + 独立说明的分离场景 ```html
代码展示卡片
说明文字卡片
``` **规则:** - 多卡片连续输出时,卡片之间不需要空行(`margin:8px 0` 已处理间距) - **优先使用单卡片模式**:考虑合并为一个 CompositeCard --- ## 不使用卡片的场景 - 单句回答("好的"、"明白了"、"没问题") - 闲聊/情感性回复 - 用户明确要求纯文字 --- ## 详细参考 - `references/html-templates.md` — 带真实示例数据的完整 HTML 模板 - `references/templates.md` — A2UI v0.9 JSONL 格式模板 - `references/components.md` — A2UI 组件参考(布局/展示/交互) - `references/html-card-templates.md` — 简化版 HTML 模板 - `references/ui-config-schema.md` — ui-config.json 字段说明 --- ## 安装 > **所有依赖文件已随技能打包**,无需克隆任何外部仓库。`assets/` 目录包含: > - `skill-ui-bridge.js` — 浏览器端 bootstrap 脚本(v2) > - `skill-ui-bridge-plugin.js` / `skill-ui-bridge-plugin.json` — openclaw plugin(v2) > ⛔ **只读取完成当前步骤所必需的文件**。遇到无法理解的内容(如编译产物、二进制文件)立即停止,不要继续探索无关文件。 **安装原理(v2)**:plugin 在 `gateway_start` 时: 1. 读取 `workspace/skills/` 下所有 `ui-config.json`,生成 manifest JSON 2. 将 manifest + bootstrap JS 合并写成 `skill-ui-init.js`,放到 control-ui 静态目录(同源,通过 CSP `script-src 'self'`) 3. 在 `index.html` 中注入 `` 4. `gateway_stop` 时还原 `index.html`,删除 `skill-ui-init.js` 浏览器加载 `skill-ui-init.js` 后,bootstrap 脚本通过 `MutationObserver` 监听 `.chat-text` 容器,检测到包含 `
` 的消息时,用自有白名单净化并渲染为富卡片。 安装前,先探测所有必要路径,再执行安装脚本。**不得假设或写死任何路径**。 ### 第一步:探测路径 依次从常见配置目录向外搜索,记录每项的实际输出结果: ```bash # 1. 找本技能目录 find /etc "$HOME" /usr/local /opt -path "*/skills/openclaw-a2ui" -type d 2>/dev/null | head -5 # 2. 找所有 openclaw.json,列出全部路径 find /etc "$HOME" /usr/local /opt -name "openclaw.json" 2>/dev/null | head -10 ``` 根据输出结果判断: - 若存在多个 `openclaw.json`,读取每个文件的内容,**选择正在被 gateway 实际使用的那个**(判断依据:文件可写、且 `plugins` 字段中的修改重启后不会消失)。通常是 `$HOME/.openclaw/openclaw.json` 而非 `/etc/` 下的只读镜像层副本。 - extensions 目录默认为 `$HOME/.openclaw/extensions`,也可从选定的 `openclaw.json` 的 `plugins.load.paths` 中读取。 - workspace 目录默认为 `$HOME/.openclaw/workspace`。 - 确认 `scripts/install.ts` 存在后再继续。 ### 第二步:运行安装脚本 用第一步探测到的实际路径执行: ```bash node --experimental-strip-types <技能目录>/scripts/install.ts \ --openclaw-config \ --extensions-dir \ --workspace-dir ``` 参数均可省略,脚本会自动探测默认路径。 安装脚本会完成: - Plugin 文件复制到 extensions 目录 - Plugin 注册到 openclaw.json(allow / load.paths / entries 三处) - `ui-config.json` 复制到 `workspace/skills/openclaw-a2ui/`(若不存在) ### 第三步:通知用户重启 > ⚠️ **Agent 无法自行完成此步骤**:重启 gateway 意味着重启当前容器进程,必须由用户在宿主机执行。 告知用户执行以下操作: **容器化部署**(docker compose): ```bash docker compose restart openclaw ``` **本机直接部署**: ```bash openclaw gateway restart ``` 重启后提示用户在浏览器**强制刷新**(Ctrl+Shift+R)。 ### 安装验证 安装并重启后,依次执行以下检查(全部通过才算成功): **1. Plugin 文件已复制** ```bash ls /skill-ui-bridge/ # 预期:index.js openclaw.plugin.json skill-ui-bridge.js ``` **2. Plugin 已正确注册到 openclaw.json** openclaw.json 的 plugins 字段应包含以下三处(缺任何一处都会导致插件不加载): ```json { "plugins": { "allow": ["skill-ui-bridge"], "load": { "paths": [""] }, "entries": { "skill-ui-bridge": { "enabled": true } } } } ``` **3. index.html 已注入(gateway 重启后)** ```bash grep "skill-ui-init" /control-ui/index.html # 预期: ``` **4. 浏览器 Console 验证** F12 打开 Console,Ctrl+Shift+R 强制刷新,应看到: ``` [skill-ui-bridge] boot ok, tags: 45 attrs: 34 ``` ### 卸载 ```bash node --experimental-strip-types <技能目录>/scripts/uninstall.ts \ --openclaw-config \ --extensions-dir \ --remove-plugin-files ``` 卸载后同样需要通知用户重启(见第三步)。