@yumiai/chat-widget
v0.4.4
Published
JetPave ChatWidget SDK — Agent conversation UI component
Readme
@yumiai/chat-widget
Agent 对话 UI 组件 — 为 AI Agent 系统提供开箱即用的聊天界面。
特性
- SSE 实时流式渲染 — POST-based Server-Sent Events,支持认证、自动重连
- Streamdown Markdown — 代码高亮、Mermaid 图表、LaTeX 数学公式、CJK 排版优化
- 多轮对话管理 — 轮次分隔、清屏滚动、动态置顶(带防抖与滞后阈值)
- 子 Agent 嵌套 — 折叠式子 Agent 卡片,支持
call_agent工具链路可视化 - 工具调用卡片 — MCP 工具生命周期(生成 → 执行 → 完成),buffering 动画
- Todo/Checklist — 实时任务进度面板,按 Phase → Group → Task 三级结构展示
- HITL 表单 — Human-in-the-Loop 交互,支持 JSON Schema / HTML Schema 动态表单
- 富文档查看器 — PDF、图片、代码、3D/STEP、KiCad 原理图/PCB、Markdown、HTML 等 20+ 格式(CWRF-001/003)
- 溯源图谱 — 3D 推理图谱可视化,支持节点过滤、深度控制、详情面板(CWRF-004)
- 选区交互 — 文档选区工具条、Ask/Copy 拦截、上下文引用芯片(CWRF-002)
- Headless Controller —
useChatWidgetController将业务逻辑与 UI 分离,支持自定义渲染(CWRF-004) - 国际化 (i18n) —
localeprop 支持zh-CN/en-US,可自定义消息字典 - 打字机效果 — 基于
requestAnimationFrame的逐字展开,自动对齐 Markdown 安全边界 - CSS 隔离 — 所有类名
ycw-前缀,CSS 变量驱动主题,不污染宿主样式 - Adapter 模式 — 认证、API 地址、Token 刷新完全由消费方注入,零耦合
安装
npm install @yumiai/chat-widgetPeer Dependencies(必需):
{
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"antd": "^5.0.0 || ^6.0.0"
}可选 Peer Dependencies(溯源 3D 图谱):
{
"three": ">=0.150.0",
"react-force-graph-3d": "^1.29.0",
"three-spritetext": "^1.10.0"
}快速开始
import { ChatWidget, DefaultJetAgentsAdapter } from '@yumiai/chat-widget'
import '@yumiai/chat-widget/style.css'
const adapter = new DefaultJetAgentsAdapter({
baseUrl: 'https://your-jetagents-server.com',
getToken: () => localStorage.getItem('access_token'),
refreshToken: async () => {
const res = await fetch('/api/auth/refresh', { method: 'POST' })
const { token } = await res.json()
localStorage.setItem('access_token', token)
return token
},
onAuthFailure: () => window.location.href = '/login',
})
function App() {
return (
<ChatWidget
adapter={adapter}
sessionId={123}
config={{
theme: 'light',
showPinnedArea: true,
enableTypewriter: true,
typewriterSpeed: 30,
displayLevels: [0, 1, 2],
}}
onReady={(api) => console.log('Widget ready', api)}
onError={(err) => console.error(err)}
height="100vh"
renderFooter={(api) => (
<input
onKeyDown={(e) => {
if (e.key === 'Enter' && api) {
api.sendMessage(e.currentTarget.value, 'agent-666')
e.currentTarget.value = ''
}
}}
placeholder="输入消息..."
/>
)}
/>
)
}自定义 Adapter
DefaultJetAgentsAdapter 适配 JetAgents 后端 API。对于其他后端系统,实现 ChatWidgetAdapter 接口即可:
import type { ChatWidgetAdapter } from '@yumiai/chat-widget'
class MyAdapter implements ChatWidgetAdapter {
async createSession(agentId: string) { /* ... */ }
async getSessionDetail(sessionId: number) { /* ... */ }
async getSessionHistory(sessionId: number) { /* ... */ }
async getResourceContent(sessionId: number, resourceId: string) { /* ... */ }
async submitHITLResponse(response) { /* ... */ }
getStreamUrl(): string { return '/api/stream' }
getAuthHeaders(): Record<string, string> { return {} }
}详细接口定义见 docs/02-adapter-interface.md。完整 API 文档见 docs/11-api-reference.md。
Headless Controller(CWRF-004)
如果需要完全自定义 UI,可直接使用 useChatWidgetController Hook:
import { useChatWidgetController } from '@yumiai/chat-widget'
function MyCustomChat({ adapter }) {
const {
executionStatus,
connectionStatus,
rounds,
sendMessage,
widgetAPI,
} = useChatWidgetController({
adapter,
sessionId: 123,
onStatusChange: (s) => console.log('status:', s),
onRoundChange: (r) => console.log('new round:', r),
onConnectionChange: (c) => console.log('connection:', c),
})
return (
<div>
{rounds.map((round) => (
<div key={round.id}>{/* 自定义轮次渲染 */}</div>
))}
</div>
)
}溯源图谱(CWRF-004)
溯源组件可作为子路径单独导入(需安装 three.js 可选依赖):
import { ProvenanceGraphDrawerContent, useProvenanceGraph } from '@yumiai/chat-widget/provenance'
function ProvenancePanel({ sessionId }) {
const { graph, loading } = useProvenanceGraph({
sessionId,
enabled: !!sessionId,
fetcher: (sid, params) => myApi.getProvenanceGraph(sid, params),
})
if (loading) return <Spin />
return <ProvenanceGraphDrawerContent graph={graph} />
}API 参考
ChatWidgetProps
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| adapter | ChatWidgetAdapter | 必填 | 后端适配器实例 |
| sessionId | string \| number | — | 会话 ID,传入后自动加载历史 |
| config | ChatWidgetConfig | DEFAULT_CONFIG | UI 配置 |
| renderHeaderExtra | (sessionId) => ReactNode | — | 头部右侧额外内容插槽 |
| renderFooter | (api) => ReactNode | — | 底部输入区插槽 |
| onReady | (api: ChatWidgetAPI) => void | — | Widget 就绪回调 |
| onArtifactClick | (artifact: Artifact) => void | — | 产出物点击回调 |
| onHITLSubmit | (response) => Promise<void> | — | HITL 表单提交回调 |
| onStatusChange | (status: ExecutionStatus) => void | — | 执行状态变化回调 |
| onError | (error: Error) => void | — | 错误回调 |
| locale | 'zh-CN' \| 'en-US' | 'zh-CN' | UI 语言 |
| renderToolResult | (data: ToolCallData) => ReactNode | — | 自定义工具结果渲染 |
| onSelectionAsk | (ref: FileReference) => void | — | 文档选区"提问"回调 |
| onBeforeCopy | (ref: FileReference) => void | — | 文档选区"复制"拦截 |
| height | number \| string | 600 | 容器高度 |
| theme | 'light' \| 'dark' \| 'auto' | 'auto' | 主题 |
ChatWidgetAPI
通过 onReady 或 renderFooter 获取的 API 对象:
| 方法 | 签名 | 说明 |
|------|------|------|
| sendMessage | (message: string, agentId?: string) => void | 发送消息并建立 SSE 连接 |
| getCurrentRound | () => Round \| null | 获取当前轮次 |
| getAllRounds | () => Round[] | 获取全部轮次 |
| scrollToBottom | () => void | 滚动到底部 |
| getStatus | () => ExecutionStatus | 获取执行状态 |
构建
npm run build # 生产构建(ESM + CJS + DTS)
npm run dev # 开发模式(watch)
npm run test # 运行测试
npm run typecheck # TypeScript 类型检查发布
本地发布用 npm login 交互登录(凭证由 npm 保存在用户目录,不要把 token 明文写进仓库内的 .npmrc);CI 发布用 CI 注入的环境变量 token(如 NODE_AUTH_TOKEN)。
npm login # 一次性登录(或由 CI 注入 token)
npm version patch # 升版本
npm publish --access public目录结构
chat-widget/
├── src/
│ ├── index.ts # 公共导出
│ ├── types.ts # 类型定义
│ ├── errors.ts # 错误类型
│ ├── ChatWidget.tsx # 主组件(thin shell)
│ ├── ChatWidget.css # 主样式(ycw- 前缀)
│ ├── controller/ # Headless Controller (CWRF-004)
│ │ ├── useChatWidgetController.ts
│ │ └── index.ts
│ ├── hooks/
│ │ ├── useSSE.ts # SSE 连接 Hook
│ │ ├── useMessageAggregator.ts # 消息聚合 Hook
│ │ └── useAttentionManager.ts # 注意力通知 Hook
│ ├── adapters/
│ │ └── DefaultJetAgentsAdapter.ts # JetAgents 默认适配器
│ ├── provenance/ # 溯源图谱 (CWRF-004)
│ │ ├── api.ts # ProvenanceGraphFetcher
│ │ ├── GraphBuilder.ts # 图构建器
│ │ ├── components/ # 3D 图谱、面板、过滤器
│ │ └── hooks/ # useProvenanceGraph
│ ├── components/
│ │ ├── FileViewer/ # 富文档查看器 (CWRF-001/003)
│ │ ├── SplitPanel/ # 分屏面板 (CWRF-002)
│ │ ├── ContextBridge/ # 选区交互 (CWRF-002)
│ │ ├── PinnedArea.tsx
│ │ ├── MessageContent.tsx
│ │ ├── ChildAgentCard.tsx
│ │ ├── ToolCardBuffering.tsx
│ │ ├── TodoCard.tsx
│ │ ├── PlanCard.tsx
│ │ └── SchemaFormRenderer.tsx
│ └── i18n/ # 国际化字典
├── tests/ # 集成测试
├── docs/ # 设计文档
├── tsup.config.ts # 构建配置(双入口:main + provenance)
├── vitest.config.ts # 测试配置
└── package.json文档目录
| 编号 | 文档 | 内容 | |------|------|------| | 01 | 架构设计 | 整体架构、数据流、消息路由规则、滚动与置顶 | | 02 | Adapter 接口规范 | ChatWidgetAdapter 接口、DefaultJetAgentsAdapter | | 03 | SSE 协议规范 | SSEMessage 结构、NotificationType、控制消息 | | 04 | 组件详解 | 各组件职责、渲染逻辑、Props | | 05 | 主题与样式 | CSS 变量、Light/Dark 主题、动画 | | 06 | 性能优化 | RAF 批量更新、Map 索引、延迟拼接、打字机 | | 07 | 时序图与架构图 | Mermaid 时序图、状态机、组件关系图、消息路由流程图 | | 08 | 错误处理与重连 | 错误类型、401 Token 刷新、自动重连、容错策略 | | 09 | 消息聚合引擎深度解析 | 索引体系、分段策略、短残片回溯、MCP 聚合、chunk 去重 | | 10 | 测试策略 | 测试分层、Mock 工厂、E2E 蓝图、覆盖率要求 | | 11 | API 参考文档 | 完整 Props/API/类型定义、导出清单 | | 12 | 原始设计规范 | 原始设计背景、消息协议、验收标准(移植自 JetForge) | | 13 | UI 设计规范 | 颜色、排版、间距、动画、响应式、无障碍(移植自 JetForge) |
License
Proprietary — YumiAI
