Files
hunjing/docs/architecture/frontend-content-rendering.md
chenxin 42513d13c6 📝 docs: 建立魂镜完整 1.0 设计文档体系
- 产品层:产品宪章与永久禁域、产品定义、完整 1.0 范围与发布门、道家文化语言体系、指标与反指标
- 研究层:参考项目研究(deepseek-harness、pi、MemOS、模型网关)、灵台原生引擎研究(业界原生引擎架构理念与道家文化出处)
- 架构层:系统、Agent 运行时(周天体系)、插件系统、灵台引擎(C++ 双形态)、媒体与设备、社区协作市场、前端富内容渲染、数据、记忆与知识
- 契约层:协议与稳定标识、API 总体约定、Native API、兼容网关、实时与 Webhook、内部端口、统一 ContentBlock 与流式(含分支对话交互态)、灵台 C ABI 与 gRPC Service、API 表面、HTTP 与事件、运行观测
- 决策:ADR-001 至 ADR-023(模块化单体、每 attempt 持久化、候选记忆、OAuth 2.1、灵台引擎、双形态部署、大周天演化、宪章、三界作用域、私箧与保全态、叩心、周天统一等)
- 交付:WP-01 至 WP-15 实施 TODO 与设计阶段交接文档
- 工程:AGENTS.md 工程规则(含 C++/灵台规范)、CLAUDE.md 引用、.gitignore
2026-09-09 21:07:14 +08:00

185 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端富内容实时渲染
## 1. 适用客户端
同一渲染内核服务 Next.js Web、Tauri Desktop 和 Tauri Mobile。平台差异只位于资源加载、文件保存、设备能力和性能档位;ContentBlock 与流状态机保持一致。
推荐组件:
- Markdown:`react-markdown` + `remark-gfm` + 受控 remark/rehype 插件;
- Code:Shiki,高亮 Worker 与缓存;
- Math:KaTeX 为默认,MathJax 只作为兼容回退;
- Mermaid:Mermaid strict mode,在 Worker/隔离容器渲染 SVG;
- 长列表:`@tanstack/react-virtual`;
- 媒体:原生 image/video/audio,使用受控资源 URL;
- 状态:TanStack Query 管服务端资源;轻量本地 store 管流 accumulator 和 UI 状态。
新增依赖前仍需按 AGENTS.md 查当前维护状态和已安装能力。
## 2. 渲染流水线
```mermaid
flowchart LR
SSE[SSE Events] --> ACC[Event Accumulator]
ACC --> STORE[Block Store]
STORE --> PARSE[Incremental Parse]
PARSE --> SAFE[Sanitize and Validate]
SAFE --> RENDER[Typed Renderers]
RENDER --> DOM[Accessible UI]
FINAL[Completed Message] --> RECON[Reconcile]
RECON --> STORE
```
各层职责:
1. Event Accumulator:校验 run sequence 与 block delta index,去重和检测缺口。
2. Block Store:以 `message_id/block_id` 保存原始 block、流状态和 renderer 状态。
3. Parse:只对允许增量的类型做节流解析。
4. Sanitize:URL、Markdown AST、SVG、公式和媒体元数据安全处理。
5. Renderer:按 Block type 分派,未知类型显示兼容占位而不崩溃。
6. Reconcile:`content.block.completed` 与 `message.completed` 到达后用权威快照替换临时状态。
## 3. 流状态机
```mermaid
stateDiagram-v2
[*] --> pending
pending --> streaming : block.started
streaming --> streaming : ordered delta
streaming --> awaiting_replay : delta gap
awaiting_replay --> streaming : replay filled
awaiting_replay --> completed : final snapshot
streaming --> completed : block.completed
streaming --> failed : block.failed
streaming --> cancelled : block.cancelled
failed --> completed : retry/resource ready
completed --> [*]
cancelled --> [*]
```
- 乱序 delta 暂存在小窗口;超过窗口请求重放,不猜顺序。
- 重复 delta 根据 `(block_id, delta_index)` 丢弃。
- 连接断开保留乐观内容并标记“正在恢复”;最终 GET Run/Message 对账。
- Final snapshot 与累积 hash 不一致时记录前端诊断并以服务端快照为准。
## 4. Markdown 增量渲染
### 4.1 策略
- 原始增量文本始终保留;AST 是可丢弃派生状态。
- 以 50–100 ms 或换行边界节流解析,不逐 token 全量重渲染。
- 未闭合 fence、链接、表格、强调或数学定界符保持源码/纯文本展示,不自动补造语义。
- Completed 后对完整 Markdown 再解析一次,替换临时 AST。
- 大 Block 分段渲染,避免每次 delta 重建整个消息树。
### 4.2 安全
- 禁用原始 HTML;若以后开放,仅对可信内部内容使用严格 allowlist。
- 链接协议允许 `https`、`mailto` 和内部资源 scheme;拒绝 `javascript`、危险 `data`、`file`。
- 外链打开使用 `noopener noreferrer`,并显示目标域。
- Markdown 图片规范化为 Image Block;不直接加载任意第三方跟踪像素。
## 5. Code 与 Shiki
- 流式时先用等宽纯文本展示;完整行或节流窗口后发送 Worker 高亮。
- Shiki grammar 按需加载并缓存;未知语言回退 plain text。
- 超大代码块关闭实时高亮,完成后按可见区域高亮。
- 提供复制、换行、下载、语言、文件名和行号;复制取原始源码,不从高亮 DOM 提取。
- 代码永不在渲染器执行;可执行动作是独立 Tool/Approval。
## 6. 数学公式
### 6.1 解析
- Native Math Block 直接按 `notation` 处理。
- Markdown 中只有闭合 `$...$`、`$$...$$`、`\(...\)`、`\[...\]` 才触发公式渲染。
- 流式未闭合公式显示转义源码和稳定占位,避免页面反复跳动。
- KaTeX 解析失败显示 `fallback_text` 或源码,并提供错误详情展开。
### 6.2 安全和可访问性
- KaTeX `trust=false`,限制宏、展开深度和输入长度;禁用 URL/HTML 注入命令。
- 生成 MathML/ARIA;Block 公式提供自然语言 `fallback_text`、变量和单位说明。
- 用户可切换“渲染公式/显示源码”。
- 常见公式描述采用“名称 → 公式 → 变量/单位 → 适用条件 → 示例”的结构,不把推导过程混入隐藏思维。
## 7. Mermaid
- 流式期间不渲染图,仅展示代码骨架和进度。
- `block.completed` 后把源码发送 Worker;验证节点数、边数、字符数和超时。
- Mermaid 使用 `securityLevel: strict`,禁止 click、HTML label、外部资源和任意初始化指令。
- 输出 SVG 再经 sanitizer;SVG 不允许 script、foreignObject、事件属性或外部 URL。
- 渲染失败显示源码、错误摘要和“复制到 Mermaid 编辑器”的安全动作,不空白。
- 提供缩放、平移、适配宽度、下载 SVG/PNG、文本替代和全屏。
- 图表在移动端默认源码/缩略图折叠,按需展开,防止长宽溢出。
## 8. 图片、视频和音频
### 图片
- 使用 `file_id` 换取短期授权 URL;响应式尺寸、懒加载、占位、失败重试和 alt。
- 不信任服务端文件名/MIME;资源域返回正确 Content-Type、CSP、CORP 和 `nosniff`。
- 大图支持查看器、缩放和下载;不默认将 EXIF 暴露给其他用户。
### 视频
- 等待 `resource_ready` 后显示 poster;使用 HLS/DASH 或受控 MP4。
- 提供字幕、转写、时长、加载/转码状态和失败说明。
- 自动播放默认关闭;有声音播放必须由用户手势触发。
### 音频
- 显示波形/时长/转写;流式 TTS 与固化 Audio Block 分离。
- 实时语音使用 WebSocket 播放队列,不把每帧写入 React 树。
- 支持打断、静音、速度和字幕;停止后清空未播放帧。
## 9. Agent、工具和审批展示
- AgentStatus Block 显示当前阶段、ChildRun、预算、等待和取消操作,不展示隐藏推理。
- ToolCall Block 默认显示工具名、用途、状态、耗时和脱敏参数摘要;敏感详情走诊断授权。
- ApprovalRequest 必须显示动作、目标、影响、费用、数据范围、有效期、允许/拒绝按钮。
- ToolResult 区分成功、错误、未知结果和产物,不把错误结果渲染成普通助手文本。
- 并行 ChildRun 使用树/时间线,主消息流只展示汇总状态,避免刷屏。
## 10. 长列表与性能
- Conversation/Community/Diagnostics 使用虚拟滚动,Block 高度由 ResizeObserver 缓存。
- 流式中的当前 Message 可脱离虚拟列表单独渲染,完成后归档入列表。
- Markdown AST、Shiki tokens、Mermaid SVG 和 Math 渲染按 content hash 缓存。
- Worker 处理高亮、Mermaid 和重解析;主线程只提交最终安全树。
- `prefers-reduced-motion` 关闭非必要动画;流式光标不引发布局抖动。
- 建立不同设备性能档:关闭实时代码高亮、降低 Avatar 帧率、延迟复杂图渲染,而不丢失内容。
## 11. 可访问性
- 每个 Block 使用正确语义元素和可聚焦操作。
- 新 delta 不持续抢夺屏幕阅读器焦点;用节流 `aria-live` 汇报状态。
- 图像必有 alt;图表有 title/caption/源码替代;音视频有字幕/转写。
- 数学提供 MathML 和 fallback text;代码支持键盘复制和横向滚动。
- 工具确认、错误和费用不能只靠颜色表达。
- Avatar/动效不阻塞核心内容和操作。
## 12. 失败与降级
| 失败 | 展示 |
| --- | --- |
| Markdown 解析失败 | 转义纯文本 |
| Shiki 失败 | plain code |
| Math 失败 | fallback text + source |
| Mermaid 失败 | source + error summary |
| 媒体未就绪 | progress placeholder |
| 媒体失败 | retry/download details |
| 未知 Block type | “当前客户端暂不支持” + JSON-safe summary |
| SSE 断线 | recovering 状态 + replay/final fetch |
| hash 不一致 | final snapshot + diagnostic marker |
降级必须保留用户内容,不以空白、崩溃或静默删除处理。
## 13. 测试
- 对每种 Block 建立 canonical fixture、流式分片、断线、重复、乱序、失败和未知类型测试。
- Markdown/Math/Mermaid 做 XSS、URL、SVG、宏膨胀和资源耗尽测试。
- 浏览器组件测试覆盖键盘、屏幕阅读器、reduced motion 和移动布局。
- Playwright 覆盖从 SSE 到 Markdown/公式/Mermaid/媒体/Tool Approval 的端到端流程。
- 对 1 MB Markdown、万行代码、复杂 Mermaid、长公式和大量消息做性能基线。