Full State Stream
按约定对象范围发送完整状态快照;说明覆盖、版本顺序、历史保留与传输成本,避免将快照等同于完整编辑协议。
#concept
#evergreen
#ai
#architecture
[!info] related notes
- 所属 MOC: LLM Streaming MOC
- 对比: Delta Stream, Append Event Stream
- 综合对比: Delta Stream vs Append Stream
- 输出模型: LLM 输出四层模型
Full State Stream
一句话定义
Full State Stream 在约定对象范围内发送完整快照,接收方用较新的版本替换状态。快照可表现重写后的结果,但 undo、并发编辑和光标映射仍需要独立的历史与冲突处理机制。
这是应用层快照模型,不是某个编辑器的已验证内部协议。下面的事件名为示意;JSONL 每行一个对象。
核心机制
数据模型
每个事件携带从头到当前的完整文本:
{ "type": "state", "content": "你" }
{ "type": "state", "content": "你好" }
{ "type": "state", "content": "你好世界" }
前端操作
// 直接用最新快照替换渲染
function onState(fullText: string) {
render(fullText)
}
快照是否“完整”取决于其定义范围,例如仅文本不包含光标、附件或未保存的人类编辑。前端可不拼接文本,但仍须判定对象 ID、revision 和本地编辑状态,不能把最后收到的旧快照当成最新状态。
更复杂的协议结构
对于编辑器场景,状态快照可以包含结构化信息:
{
"type": "document.state",
"data": {
"content": "完整的文档文本...",
"cursors": [{ "user": "ai", "position": 3 }],
"highlights": [{ "range": [0, 3], "type": "new" }],
"metadata": { "revision": 1 }
}
}
最小场景
AI 编辑器的实时预览伪代码:假定调用方已选择可接收的新版本,并将事件 data 传入;辅助函数、DocumentState 和 history 由应用定义。
let currentDocument = ""
function onDocumentState(state: DocumentState) {
currentDocument = state.content
renderEditor(currentDocument)
// 若用于撤销,需保存独立不可变版本并定义本地/远端历史策略。
history.push(structuredClone(state))
}
适用场景
| 场景 | 说明 |
|---|---|
| 文档内 AI 写作 | 可用快照预览替换结果;不推断特定产品使用此协议 |
| AI editor | 富文本编辑器的 AI 辅助 |
| 文档生成器 | 生成完整文档的实时预览 |
| Code generation preview | 代码生成的实时展示 |
优势
- 文本投影可直接覆盖,省去逐片拼接;版本选择与编辑器状态协调仍需逻辑
- 保存历史快照可支持状态回退;只保留最新快照无法 undo,多人编辑还需定义撤销范围
- 可携带替换后的结果、光标或高亮;局部编辑操作和坐标含义须额外约定
局限
- 若每新增一个字符都发送从头累计的全文,未压缩负载为 1+2+…+n,即 O(n²);固定次数快照、压缩或合并发送不适用同一结论
- 快照可在任意时刻发送,并不必须等待语义单元;序列化大小和发送频率共同影响延迟
- 长文本高频快照的传输量较大,可降低快照频率或结合增量事件
- 发送端需要取得完整状态并序列化,开销取决于状态大小与频率
边界与易混淆点
- 若线上实际传输的是相对于某个版本的 diff,消费者仍需基线与补丁应用;它不再是每个网络事件都可独立恢复状态的全量快照。
- 适合编辑器但不是编辑器专用:任何需要”随时可以拿到完整状态”的场景都可以用。
- 和 Delta Stream 是两个极端:Delta 只传增量,State 传全量。实际系统通常在两者之间取平衡。