@dreo-design/embed-agent
v1.0.9
Published
Page-attached AI Agent chat widget — one script tag, full agent experience.
Readme
embed-agent
页面附着式 AI Agent 对话 Widget — 一行引入,完整体验。
<script src="https://unpkg.com/embed-agent/dist/embed-agent.js"></script>
<script>
EmbedAgent.init({
getEmbedToken: () => fetch('/api/embed/token', { method: 'POST' }).then(r => r.json()),
})
</script>embed-agent 为任意 Web 页面提供 AI Agent 聊天能力。一行 <script> 或一个 import,与任何后端配合使用。
为什么用 embed-agent?
| 你的问题 | embed-agent 怎么解决 |
|---------|-------------------|
| "我想在 CRM 里加个聊天机器人" | EmbedAgent.init({ container: '#chat-panel', ... }) |
| "我后端不是 ClawBuilder" | 后端无关 — 你只需要提供一个 POST /embed/token 端点 |
| "我需要暗色模式" | bootstrap 里传 theme: { mode: 'dark', primaryColor: '#7c3aed' } |
| "AI 会发决策卡片,我需要处理" | SurfaceInlinePanel 开箱即用地渲染 surface.render 命令 |
| "我后端 API 路径不一样" | urls: { chatHistory: '/v2/conv/{roomId}', ws: '/v2/ws/{roomId}' } |
快速开始
npm(React / Vue / 任意框架)
npm install embed-agent// package.json — 安装时自动复制 Widget 静态文件
{ "scripts": { "postinstall": "cp -r node_modules/embed-agent/widget-dist public/widget" } }import { EmbedAgent } from 'embed-agent'
EmbedAgent.init({
getEmbedToken: async () => {
const res = await fetch('/api/embed/token', { method: 'POST' })
const { data } = await res.json()
return { embedToken: data.embed_token, roomId: data.room_id, apiBase: 'https://api.example.com' }
},
getPageContext: () => ({ v: 1, page: { url: location.href, title: document.title } }),
})Script 标签(任意 HTML 页面)
<script src="https://unpkg.com/embed-agent/dist/embed-agent.js"></script>
<script>
EmbedAgent.init({
widgetUrl: 'https://your-app.example.com/widget/index.html',
getEmbedToken: () => fetch('/api/embed/token', { method: 'POST' }).then(r => r.json()),
})
</script>架构
┌─ 宿主页面 ───────────────────────────────────────────────────────┐
│ EmbedAgent.init({ getEmbedToken, getPageContext }) │
│ │
│ ┌──────────────┐ postMessage ┌─────────────────────────┐ │
│ │ SDK (5.5 KB) │ ◄──────────────► │ Widget iframe (1.2 MB) │ │
│ │ FAB + 面板 │ ea:bootstrap │ React SPA + Semi UI │ │
│ └──────────────┘ ea:context ... └───────────┬─────────────┘ │
│ │ │
│ REST + WebSocket │
│ │ │
│ ┌───────────▼───────────┐ │
│ │ 你的后端 │ │
│ │ POST /embed/token │ │
│ │ GET /chats/... │ │
│ │ WS /ws │ │
│ └───────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘三层清晰分离:SDK 负责 DOM + postMessage,Widget 是自包含的聊天 SPA,你的后端 只需提供一个 token 签发端点。Widget 已预构建好 — 复制 widget-dist/ 到 public 目录即可。
核心特性
| 特性 | 说明 |
|---------|-------------|
| 🔌 两种集成模式 | 悬浮 FAB 按钮,或内联嵌入任意 <div> |
| 🎨 可主题化 | 暗色/亮色模式 + 自定义主色 |
| 🧠 AI 流式回复 | ai_start → ai_token → ai_end,rAF 批量渲染 |
| 📊 丰富内容 | Markdown、代码块、图表(recharts)、决策卡、统计卡 |
| 🔒 PostMessage 隔离 | SDK ↔ Widget 通过 iframe 沙箱通信 |
| 📝 页面上下文注入 | 页面 URL、标题、用户选中、表单数据 → AI 上下文 |
| 🔄 自动重连 | WebSocket 指数退避重连 |
| 💾 离线队列 | WS 断开时缓存消息,重连后自动发送 |
| 🔑 Token 刷新 | ea:token_expired → ea:token_refresh 协议 |
| 🧩 可扩展渲染器 | surfaceRenderers.register('myCard', MyComponent) |
| 📦 SDK 零依赖 | src/ 纯 JS — 无框架、无 npm 依赖 |
API 一览
// 初始化 — 悬浮 FAB 模式
EmbedAgent.init({ getEmbedToken: ... })
// 或者 — 多实例 + 内联
const w = EmbedAgent.createWidget({
container: '#chat-box', // 内联模式(无 FAB)
getEmbedToken: () => fetch(...),
getPageContext: () => ({ v: 1, page: { url: location.href } }),
on: {
ready: () => {},
action: (name, payload) => {}, // 用户点击了某个交互卡片
tokenExpiring: () => fetch(...).then(d => w.refreshToken(d.token)),
},
})
w.open(); w.close(); w.destroy()参阅 对接文档 了解完整 API 参考、数据契约和后端要求。
参阅 扩展指南 了解自定义渲染器、主题、URL 模板和 Launcher 定制。
包结构
embed-agent/
├── src/ # SDK — 纯 JS(5 个文件,0 依赖)
├── widget/ # Widget — React SPA(20 个文件)
├── dist/ # SDK 构建产物(IIFE + ESM)→ npm publish
├── widget-dist/ # Widget 构建产物 → 复制到 public/widget/
├── docs/
│ ├── integration.md # 完整 API + 后端契约
│ └── extending.md # 定制指南:渲染器、主题、URL
├── DESIGN.md # 架构总览
├── README.md # 英文首页
└── README.zh-CN.md # 你在这里本地开发
npm install
npm run dev # Widget 开发服务器 → http://localhost:5173
npm run build # SDK + Widget 生产构建
npm test # vitestLicense
MIT
