@chronoai/toolkit/dom
将时间轴的内容自动挂载到指定 DOM 元素上。支持多条时间轴同时挂载、流式更新、多种写入模式。仅用于浏览器环境。
AI 原始输出的提取和格式转换请使用
@chronoai/toolkit/output-parser。
安装
已包含在 @chronoai/toolkit 中,无需单独安装。
import { DomMountFeature } from '@chronoai/toolkit/dom';
为什么需要这个 Feature?
在使用 ChronoAI 时,AI 响应经过 output-parser 提取文本、经过格式转换后,最终都存储在时间轴上。但从时间轴到页面渲染这一步,通常需要在每个项目中手写 useObserver + DOM 操作逻辑。
DomMountFeature 把这段重复逻辑标准化:声明"哪条时间轴的内容挂到哪个 DOM 元素上",Feature 自动处理流式更新、元素查找、写入策略。
快速开始
agent.use(DomMountFeature, {
mounts: [
{ source: 'rendered-html', target: '#output' },
],
});
当 rendered-html 时间轴写入新值时,内容会自动同步到 #output 元素的 innerHTML。
多条时间轴挂载
agent.use(DomMountFeature, {
mounts: [
{ source: 'rendered-html', target: '#output' },
{ source: 'thinking-html', target: '#thinking', mode: 'text' },
{ source: 'chat-bubble', target: '#chat', mode: 'append' },
],
});
每条挂载独立运作,互不影响。
写入模式
通过 mode 参数控制内容如何写入 DOM 元素:
| mode | 行为 | 适用场景 |
|---|---|---|
'html'(默认) | el.innerHTML = value | 渲染 HTML 内容 |
'text' | el.textContent = value | 纯文本显示,自动转义 HTML |
'append' | el.insertAdjacentHTML('beforeend', value) | 聊天气泡逐条追加 |
(el, value) => void | 自定义函数 | 完全控制写入逻辑 |
自定义写入函数
agent.use(DomMountFeature, {
mounts: [{
source: 'rendered-html',
target: '#output',
mode: (el, value) => {
el.innerHTML = value;
el.scrollTop = el.scrollHeight; // 自动滚到底部
},
}],
});
target 指定方式
target 支持三种形式:
| 类型 | 示例 | 说明 |
|---|---|---|
| CSS 选择器 | '#output' | 首次写入时懒查找,之后缓存 |
| HTMLElement | document.getElementById('output') | 直接传入已有元素 |
| 工厂函数 | () => document.getElementById('output') | 首次写入时调用,适合 DOM 延迟渲染场景 |
// 工厂函数:DOM 延迟渲染时使用
agent.use(DomMountFeature, {
mounts: [{
source: 'rendered-html',
target: () => document.querySelector('.dynamic-container'),
}],
});
流式更新
默认开启流式监听(streaming: true)。当源时间轴通过 stream().feed() 推送流式帧时,DOM 会实时更新,无需等到 commit。
如果只需在最终 commit 后才更新 DOM:
{
source: 'rendered-html',
target: '#output',
streaming: false,
}
完整链路示例
从 AI 原始输出到页面渲染的完整管道:
import { OutputParserFeature, stripFences, xmlTag } from '@chronoai/toolkit/output-parser';
import { DomMountFeature } from '@chronoai/toolkit/dom';
// 1. 解析:从 AI 响应中提取 <response> 标签内容
agent.use(OutputParserFeature, {
source: 'ai-response',
timeline: 'ai-parsed',
pipeline: [
stripFences(),
xmlTag('response'),
],
});
// 2. 挂载:将解析结果的某个字段渲染到页面
agent.use(DomMountFeature, {
mounts: [
{ source: 'ai-parsed', target: '#output' },
],
});
如果中间需要 Markdown → HTML 转换或 XSS 消毒,可在
output-parser的custom步骤中完成,也可以在DomMountFeature的自定义mode函数中处理。
类型导出
| 类型 | 说明 |
|---|---|
DomMountFeatureConfig | Feature 配置 |
DomMountEntry | 单条挂载配置 |
DomWriteMode | 写入模式类型 |
时间轴
外部时间轴
| 名称 | 值类型 | 说明 |
|---|---|---|
mount.source(用户指定,引用) | string | 监听的源时间轴,值更新时自动同步到 DOM |
内部时间轴
无。
配置参数
agent.use(DomMountFeature, config) 的 config 支持以下参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
mounts | DomMountEntry[] | 是 | 挂载列表 |
DomMountEntry
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
source | string | 是 | — | 源时间轴名称(引用模式,可跨 toolkit / 跨 Feature) |
target | string | HTMLElement | () => HTMLElement | null | 是 | — | 挂载目标:CSS 选择器、元素实例或工厂函数 |
mode | DomWriteMode | 否 | 'html' | 写入模式 |
streaming | boolean | 否 | true | 是否监听流式帧更新 |