- 产品层:产品宪章与永久禁域、产品定义、完整 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
254 lines
11 KiB
Markdown
254 lines
11 KiB
Markdown
# 统一富内容与流式协议
|
||
|
||
## 1. 目标
|
||
|
||
同一套 `ContentBlock` 用于 Native Message、Agent 输出、社区内容、私信、协作评论和结构化产物。用户编辑可接受 Markdown 内嵌 Mermaid/数学语法;服务端在保存或发送前解析并规范化为类型化 Block。
|
||
|
||
原则:
|
||
|
||
- 类型化 Block 是 API 和存储规范形态;
|
||
- Markdown 是常用创作输入和可移植表示,不是所有媒体的唯一协议;
|
||
- 每个 Block 有稳定 ID 和独立状态,可局部流式、报错、重试、替换和无障碍展示;
|
||
- 不执行 HTML、JavaScript、Mermaid click callback 或不可信媒体脚本。
|
||
|
||
## 2. Content 容器
|
||
|
||
```json
|
||
{
|
||
"content": [
|
||
{"id": "block_01...", "type": "markdown", "text": "## 结论\n..."},
|
||
{"id": "block_02...", "type": "mermaid", "source": "flowchart LR\nA-->B"},
|
||
{"id": "block_03...", "type": "math", "notation": "latex", "display": "block", "source": "E=mc^2"},
|
||
{"id": "block_04...", "type": "image", "file_id": "file_01...", "alt": "架构图"}
|
||
]
|
||
}
|
||
```
|
||
|
||
所有 Block 通用字段:
|
||
|
||
| 字段 | 必需 | 说明 |
|
||
| --- | --- | --- |
|
||
| `id` | 是 | Message 内稳定 `block_` ID |
|
||
| `type` | 是 | Block 类型 |
|
||
| `status` | 响应中 | `pending`、`streaming`、`completed`、`failed`、`cancelled` |
|
||
| `annotations` | 否 | citation、来源、敏感度、语言等类型化标注 |
|
||
| `metadata` | 否 | 只允许 Schema 登记字段,不存任意秘密 |
|
||
|
||
`id` 在创建请求中可省略,由服务端生成;流事件必须携带服务端 Block ID。
|
||
|
||
## 3. Block 类型
|
||
|
||
### 3.1 文本与结构
|
||
|
||
| `type` | 关键字段 | 流式策略 |
|
||
| --- | --- | --- |
|
||
| `text` | `text`, `language?` | 字符增量 |
|
||
| `markdown` | `text`, `flavor="hunjing-gfm-v1"` | 字符增量,安全增量解析 |
|
||
| `code` | `source`, `language?`, `filename?` | 字符增量,Shiki 节流高亮 |
|
||
| `quote` | `content[]`, `source_ref?` | 子 Block 增量 |
|
||
| `table` | `columns`, `rows`, `caption?` | 行级追加或完成后展示 |
|
||
| `callout` | `kind`, `title?`, `content[]` | 子 Block 增量 |
|
||
|
||
Markdown 方言支持 CommonMark/GFM 的标题、段落、列表、引用、表格、任务列表、链接、图片引用、行内代码和 fenced code。原始 HTML 默认禁用。
|
||
|
||
### 3.2 数学公式
|
||
|
||
```json
|
||
{
|
||
"id": "block_math",
|
||
"type": "math",
|
||
"notation": "latex",
|
||
"display": "block",
|
||
"source": "\\int_0^1 x^2 dx = \\frac{1}{3}",
|
||
"fallback_text": "从 0 到 1 的 x² 积分等于 1/3",
|
||
"label": "公式 1"
|
||
}
|
||
```
|
||
|
||
- `notation` 1.0 为 `latex` 或 `asciimath`;服务端规范化优先输出 LaTeX。
|
||
- `display` 为 `inline` 或 `block`。
|
||
- `fallback_text` 是可访问性与解析失败降级描述,不是隐藏推理。
|
||
- Markdown 输入支持 `$...$`、`$$...$$`、`\(...\)`、`\[...\]`;只有闭合定界符后才转换为 Math Block。
|
||
- 常见公式描述应同时包含公式与自然语言说明,例如变量、单位、适用条件和来源,不能只输出不可读符号。
|
||
|
||
### 3.3 Mermaid
|
||
|
||
```json
|
||
{
|
||
"id": "block_mermaid",
|
||
"type": "mermaid",
|
||
"source": "sequenceDiagram\nA->>B: request",
|
||
"title": "请求时序",
|
||
"caption": "客户端到网关的调用",
|
||
"fallback_code_language": "mermaid"
|
||
}
|
||
```
|
||
|
||
- 只在 Block `completed` 后渲染;流式期间展示代码/骨架和“图表生成中”。
|
||
- 禁止 `click`、外部脚本、HTML label、任意 URL callback 和危险初始化配置。
|
||
- 渲染使用 strict security level、隔离 worker/iframe 和超时/节点数/源码长度限制。
|
||
- 解析失败展示转义后的 Mermaid 源码与错误摘要,不丢失内容。
|
||
- Markdown fenced ` ```mermaid ` 在规范化时转换为 Mermaid Block。
|
||
|
||
### 3.4 媒体与文件
|
||
|
||
| `type` | 关键字段 |
|
||
| --- | --- |
|
||
| `image` | `file_id` 或受控 `url_ref`, `alt`, `width?`, `height?`, `caption?` |
|
||
| `video` | `file_id`, `poster_file_id?`, `caption?`, `transcript_file_id?`, `duration_ms?` |
|
||
| `audio` | `file_id`, `transcript?`, `duration_ms?`, `waveform?` |
|
||
| `file` | `file_id`, `filename`, `media_type`, `size_bytes`, `description?` |
|
||
| `gallery` | `items[]`(image/video refs), `layout?` |
|
||
| `avatar` | `asset_id`, `format`(live2d/vrm/gltf), `preview_file_id?` |
|
||
|
||
- API 不接受 `file://`、`javascript:`、`data:text/html` 等 URL。
|
||
- 内部资源使用 `file_id`,下载通过授权 API 或短期签名 URL。
|
||
- 图片 `alt` 必需;视频应提供字幕/转写状态;音频应提供转写或文本摘要。
|
||
- 媒体生成流只发送 `asset.progress` 与最终 File/Media Block,不把未完成二进制塞进 SSE JSON。
|
||
|
||
### 3.5 Agent 与工具
|
||
|
||
| `type` | 说明 |
|
||
| --- | --- |
|
||
| `tool_call` | 工具名、调用 ID、参数脱敏视图、状态和审批引用 |
|
||
| `tool_result` | 调用 ID、结构化摘要、文件引用、错误状态 |
|
||
| `agent_status` | Agent/ChildRun、阶段、进度和等待原因 |
|
||
| `approval_request` | 动作、影响、参数摘要、有效期和 Approval ID |
|
||
| `artifact` | Run 产物 ID、类型、版本和下载/打开动作 |
|
||
| `citation` | 来源 ID、标题、引用文本与定位(文本区间、图像区域、PDF 页区、音视频时间码);保存原文快照,来源正影后提示后继版本 |
|
||
| `error` | 局部 Block 错误、可否重试和 fallback |
|
||
|
||
普通 Message API 不允许客户端伪造系统产生的 `tool_call`、`tool_result`、`agent_status` 和 `approval_request`;这些 Block 只由 Runtime 写入。
|
||
|
||
## 4. Markdown 输入规范化
|
||
|
||
当客户端提交 `markdown` Block:
|
||
|
||
1. 保存用户原始 Markdown 的规范化副本及 hash;
|
||
2. 使用确定性 parser 解析 AST;
|
||
3. fenced `mermaid` 转为 Mermaid Block;
|
||
4. 闭合数学定界符转为 Math Block;
|
||
5. fenced 其他语言转为 Code Block;
|
||
6. Markdown 图片只允许已上传 `file_id` 语法或经过 URL 安全代理的 HTTPS URL;
|
||
7. 输出 canonical ContentBlock 列表和 parser version;
|
||
8. 编辑后重新规范化,创建 Message Revision,不静默改旧 Block。
|
||
|
||
导出可选择 canonical JSON 或重建的 Hunjing Markdown;重建时复杂 Block 使用稳定 fenced/directive 语法。
|
||
|
||
## 5. 流式事件
|
||
|
||
Run SSE 使用统一 envelope;Block 事件如下:
|
||
|
||
```text
|
||
content.block.started
|
||
content.block.delta
|
||
content.block.progress
|
||
content.block.completed
|
||
content.block.failed
|
||
content.block.cancelled
|
||
message.completed
|
||
```
|
||
|
||
### 5.1 Started
|
||
|
||
```json
|
||
{
|
||
"type": "content.block.started",
|
||
"data": {
|
||
"message_id": "message_01...",
|
||
"block": {"id": "block_01...", "type": "markdown", "status": "streaming"},
|
||
"index": 0
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5.2 Delta
|
||
|
||
```json
|
||
{
|
||
"type": "content.block.delta",
|
||
"data": {
|
||
"message_id": "message_01...",
|
||
"block_id": "block_01...",
|
||
"delta_index": 7,
|
||
"delta": {"type": "text_append", "text": "新增文本"}
|
||
}
|
||
}
|
||
```
|
||
|
||
Delta 类型:
|
||
|
||
- `text_append`:text/markdown/code/math/mermaid source 追加;
|
||
- `json_patch`:只用于 Schema 明确允许的结构化 Block,采用受限 RFC 6902 子集;
|
||
- `row_append`:table 追加完整行;
|
||
- `annotation_add`:追加 citation/来源;
|
||
- `resource_ready`:绑定已完成 file/media/artifact;
|
||
- `status_replace`:Agent/tool/approval 状态转换。
|
||
|
||
每个 Block 的 `delta_index` 从 0 单调递增;同一 delta 可重放,客户端按 `(block_id, delta_index)` 去重。缺口出现时暂停该 Block 增量展示,并通过 Run 重放或最终 Message 对账。
|
||
|
||
### 5.3 Completed
|
||
|
||
```json
|
||
{
|
||
"type": "content.block.completed",
|
||
"data": {
|
||
"message_id": "message_01...",
|
||
"block": {
|
||
"id": "block_01...",
|
||
"type": "markdown",
|
||
"status": "completed",
|
||
"text": "完整权威内容"
|
||
},
|
||
"content_hash": "sha256:..."
|
||
}
|
||
}
|
||
```
|
||
|
||
Completed Block 是该 Block 的权威快照。客户端丢弃临时解析状态,以完整 Block 重建并校验 hash。`message.completed` 携带最终 Message ID、Block 顺序和版本,最终 GET Message 可恢复所有内容。
|
||
|
||
## 6. 分级实时策略
|
||
|
||
| 内容 | 流式展示 |
|
||
| --- | --- |
|
||
| Plain text / Markdown | 增量显示;解析节流;未闭合结构以文本态保留 |
|
||
| Code | 增量显示;按行/时间片重新高亮,不逐 token 运行 Shiki |
|
||
| Inline/Block Math | 累积到完整定界符或 Block 完成后渲染;此前显示源码占位 |
|
||
| Mermaid | 只在 Block completed 后渲染;此前显示源码/骨架 |
|
||
| Image/Video/Audio/File | progress 占位;`resource_ready` 后加载;失败可重试 |
|
||
| Table | 完整行追加,避免半行抖动 |
|
||
| Tool/Agent/Approval | 状态替换,不拼接自由文本 |
|
||
|
||
## 7. 限制与安全
|
||
|
||
- 单 Message、Block、源码、节点、表格、媒体和嵌套深度的限额由配置发布,但 Schema 必须有硬上限。
|
||
- Markdown URL 经 scheme/host 校验,外链加 `noopener noreferrer`,可选经安全跳转页。
|
||
- HTML 默认不解析;需要 HTML 的可信内部 Block 也必须经 allowlist sanitizer。
|
||
- KaTeX/MathJax 禁用信任命令、宏注入和外部资源;限制宏展开和源码长度。
|
||
- Shiki 只高亮不执行代码;复制/下载保留原源码。
|
||
- Mermaid 渲染隔离且不允许交互脚本。
|
||
- 媒体采用 CSP、正确 Content-Type、`nosniff` 和独立对象域。
|
||
|
||
## 8. 兼容 API 映射
|
||
|
||
OpenAI/Anthropic Content Block 在 Gateway Adapter 转为内部 Block,但兼容响应仍保持目标协议。无法映射的 Native 类型:
|
||
|
||
- 优先转换为目标协议支持的 text/image/document/tool block;
|
||
- Mermaid/math/code 可降级为 Markdown/fenced source;
|
||
- video/audio/avatar/artifact 使用文本说明 + 受控文件引用;
|
||
- 不能无损、安全表达时返回明确 unsupported,不伪造协议字段。
|
||
|
||
## 9. 分支对话交互态
|
||
|
||
分支对话(镜树)在流式协议之上的交互态语义(承接旧版镜树专题 PRD,字段与枚举进入 OpenAPI 前以本节为基线):
|
||
|
||
- **临时芽体**(Block `status: streaming` 的未完成答复):完成后才固化为权威快照;流式期间展示为进行态,不进入归真候选。
|
||
- **残答**(`interrupted`):被停止或中断的不完整答复封存可查,不作为完成答复;默认上下文不自动包含。
|
||
- **续生**(`generation_resume`):从残答继续生成时创建**新** Message 并引用残答来源;残答本身不被修改或"补全"。
|
||
- **引用合流**(`citation_intake`):树间内容经显式引用带入另一棵树,以 citation/引文锚表达;不物理合并两树,被引内容保留原树的界域与归真作用域。
|
||
- **结题**(`topic_conclusion`):标记主题阶段完成并生成可审阅总结(总结内容走候选确认);结题后仍可复照继续,不删除历史。
|
||
- **回响**(`task_echo`):后台受托任务完成后,结果以回响形态回到原分支,作为带来源的观察呈现(`agent_status`/`artifact` Block);经用户接纳并归真后才成为正式答复。
|
||
- **上下文镜**(`context_mirror`):发送或继续前向用户渐进展示实际采用的上下文范围、压缩与省略项;与 ContextSnapshot 同源数据,是用户可见的透明视图而非诊断特权。
|
||
|
||
不变量:重新生成不覆盖旧候答;后代节点绑定用户实际依据的候答;已归真经历不因切换候答、删除旁枝或移动工作入口而回滚;未归真旁枝不自动入忆。
|