first commit
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
# 钉钉文档改写流程
|
||||
|
||||
本文只处理已有文档的结构和排版策略。普通执行入口固定为 `+fetch`、`+update` 或 `+checkpoint-update`;这些 shortcut 统一确认、写入与验证。原子 `doc read/update/block` 只保留给 shortcut 未公开参数的 JSONML 专家路径,使用前必须读取精确 leaf Schema。
|
||||
|
||||
## 适用边界
|
||||
|
||||
进入本文前,必须已经确认用户要改写的是已有钉钉文档 (`adoc`)。如果用户要新建、要操作表格 / AI 表格 / 文件 / 知识库空间 / 发消息,不要套用本文。
|
||||
|
||||
本文覆盖:
|
||||
|
||||
- 已有文档的局部改写、润色、章节补充
|
||||
- 段落 ↔ 列表 ↔ 表格 的形态转换
|
||||
- 块级精修(callout、分栏、附件插入)
|
||||
- overwrite 整篇改写的风险提示与执行
|
||||
- JSONML 无损结构改写的入口
|
||||
|
||||
本文不覆盖:
|
||||
|
||||
- 新建文档(见 [doc-create-workflow.md](./doc-create-workflow.md))
|
||||
- 知识库空间管理
|
||||
- 文档权限、消息分发、待办分派
|
||||
|
||||
---
|
||||
|
||||
## 一、核心原则
|
||||
|
||||
### 1.1 精准手术优于全量覆盖
|
||||
|
||||
**默认走精准手术**——只改用户指定的章节或 block,不动其他内容。具体路径见 §3 速查表。
|
||||
|
||||
### 1.2 保真约束
|
||||
|
||||
改写时必须**原样保留**以下要素,**不许**替换为纯文本/姓名/链接/占位符:
|
||||
|
||||
- `@人` 引用(用户、机器人、群)
|
||||
- `@文档` / `@群` 等卡片引用
|
||||
- 已上传的附件、图片
|
||||
- 用户原话引用块
|
||||
- 表格表头(除非语义错误且用户确认)
|
||||
|
||||
JSONML 模式下这些元素的节点结构见 [doc-jsonml-schema.md](../format/doc-jsonml-schema.md)。
|
||||
|
||||
### 1.3 编辑形态优先级
|
||||
|
||||
**改写已有文档优先 JSONML,markdown / element 只在 JSONML 不适用时兜底**:
|
||||
|
||||
| 优先级 | 形态 | 适用 |
|
||||
|--------|------|------|
|
||||
| ① 首选 | `--content-format jsonml` | 保真度最高;callout / 分栏 / 表格 / @人 / 附件 / 颜色 / 嵌套结构都能 1:1 round-trip;写入端有 validator 兜底(§4.4) |
|
||||
| ② 次选 | `--content-format element`(JSON,老接口) | JSONML 不支持某个块字段时;或快速插入 callout / 分栏不想构造 JSONML 时;不保真改写正文 |
|
||||
| ③ 兜底 | markdown(不带 `--content-format` 即默认)| 纯文本追加、整篇重排骨架;callout / 分栏 / 颜色 / 部分属性会被 markdown 还原过程丢失 |
|
||||
|
||||
实操判断:
|
||||
|
||||
- 用户给已有 nodeId 要「改一段、改属性、加 callout、动结构」——走 §4.4 JSONML 路径
|
||||
- 用户要「在末尾追加一节纯文本 / 整篇按新骨架重写」——走 §4.2 / §4.5 markdown 路径
|
||||
- 同一次任务里两类需求都有——分别走对应路径,**不要**为了省事全部 markdown overwrite
|
||||
|
||||
### 1.4 写入风险提示
|
||||
|
||||
`doc update` 在以下场景可能产生**静默失败**(返回 success=true 但实际写入不完整):
|
||||
|
||||
- **overwrite 降级为 append**:大文档 overwrite 被后端静默降级,导致旧内容未清除、新内容追加在末尾
|
||||
- **分块 append 内容截断**:超长文档分片写入时部分片段丢失或顺序错乱
|
||||
- **编码/通道问题**:特殊终端下 UTF-8 内容传输乱码
|
||||
|
||||
因此写入必须通过带确认与验证的 shortcut。`+update/+checkpoint-update` 返回的验证结果是主证据;禁止无条件追加一次原子 `doc read`,只有 partial/unknown 或需要定点结构检查时才用 `+fetch`。
|
||||
|
||||
---
|
||||
|
||||
## 二、读取策略
|
||||
|
||||
改写前必须先读现有内容,但要节省上下文。按粒度选读取方式(按 §1.3 优先级排序,**优先 JSONML**):
|
||||
|
||||
| 用户需求 | 读取方式 | 定位方法 |
|
||||
|----------|----------|----------|
|
||||
| 单块精修(首选)| `doc block list --node <id> --content-format jsonml` → 拿 uuid → `doc block list --node <id> --content-format jsonml --block-id <uuid>` 读子树 | 节点结构见 [doc-jsonml-schema.md](../format/doc-jsonml-schema.md) |
|
||||
| 多处保真改写 / 改 root sectPr | `+fetch --node <id> --detail full` | 解析 JSONML;担心并发覆盖时记下 revision |
|
||||
| 整篇按新骨架重写(纯文本场景)| `+fetch --node <id>` | 直接处理 markdown 全文 |
|
||||
| 末尾追加纯文本章节 | 不必读全文,直接 §4.2 append | 必要时 `+fetch --scope section` 看末尾衔接 |
|
||||
| 老接口快速找 BLOCK_ID(无需 jsonml 时)| `doc block list --node <id>` | 默认输出 JSON;用 `grep -B2 -A2 "<关键词>"` 在 children 里定位(结构 `{"blocks":[{...,"children":[...]}]}`,jq 需 `..\|.text? // empty` 递归查文本) |
|
||||
|
||||
读取后,把改写计划告诉用户(要改哪几节、走 JSONML 还是 markdown、改成什么形态),等用户确认后再写。
|
||||
|
||||
---
|
||||
|
||||
## 三、改写路径速查
|
||||
|
||||
按用户请求形态查表,跳到对应详细节执行(**按 §1.3 优先级排序:JSONML 路径在前,markdown / element 兜底在后**):
|
||||
|
||||
| 用户请求 | 推荐路径 | 详细节 |
|
||||
|----------|----------|--------|
|
||||
| 改某一章 / 某一节(首选) | block list 拿 uuid → block update --content-format jsonml | §4.4 路径 B |
|
||||
| 改属性 / 改 mark / 改颜色不动文本 | block update --content-format jsonml | §4.4 路径 B |
|
||||
| 插入 callout / 分栏 / 嵌套结构(首选) | block insert --content-format jsonml --element '[...]' | §4.4 路径 B |
|
||||
| 多处保真改写 / 改 root sectPr | 整篇 JSONML overwrite(默认不带 --revision;并发敏感时再加) | §4.4 路径 A |
|
||||
| 中间插一段纯文本 | block insert(element JSON 或 jsonml) | §4.3 / §4.4 |
|
||||
| 末尾追加一节纯文本 | doc update --mode append(markdown) | §4.2 |
|
||||
| 整篇按新骨架重写 | overwrite 全文(优先 JSONML;纯文本可用 markdown) | §4.5 |
|
||||
| 段落转表格 / 表格转段落 | block update --content-format jsonml;或 markdown overwrite 单段 | §4.4 / §4.1 |
|
||||
| 插入附件 / 图片 | doc media insert | §4.3 |
|
||||
| 一次追加 >200KB 内容 | 分块 append + 用户风险确认 + 逐片记录 | §4.6 |
|
||||
| 兜底:纯文本快速替换某段 | doc update --content overwrite(markdown) | §4.1 |
|
||||
|
||||
---
|
||||
|
||||
## 四、改写路径详细
|
||||
|
||||
> **首选 JSONML(§4.4)**——保真度最高且 validator 兜底;本节其余路径(markdown / element)仅在 §1.3 列出的"次选 / 兜底"场景下使用。
|
||||
|
||||
### 4.1 段落级 overwrite(markdown 兜底路径)
|
||||
|
||||
> 适用范围:**纯文本**改写一段或替换某节内容。若该段含 callout / 分栏 / 颜色 / @人 / 附件 / 嵌套结构,**改走 §4.4 路径 B**——markdown 还原会丢失这些元素。
|
||||
|
||||
```bash
|
||||
dws doc +update --node <nodeId> --command overwrite --content "<新内容>" --doc-format markdown
|
||||
```
|
||||
|
||||
或写入临时文件:
|
||||
|
||||
```bash
|
||||
dws doc +update --node <nodeId> --command overwrite --content @./drafts/<name>-section.md --doc-format markdown
|
||||
```
|
||||
|
||||
> ⚠️ **overwrite 须用户确认**——尤其是整篇文档 overwrite。
|
||||
|
||||
### 4.2 追加章节(markdown)
|
||||
|
||||
> 适用范围:在文档末尾加 X 章 / 补充纯文本段落。追加内容若含 callout / 分栏等富结构,先用本节 append 一个占位段落,再用 §4.4 路径 B 的 `block insert --content-format jsonml` 替换/精修。
|
||||
|
||||
```bash
|
||||
dws doc +update --node <nodeId> --command append --content @./drafts/<name>-append.md --doc-format markdown
|
||||
```
|
||||
|
||||
按 [doc-style-guideline.md](./doc-style-guideline.md) 的元素选择规则准备追加内容。
|
||||
|
||||
### 4.3 块级精修(element JSON 次选路径)
|
||||
|
||||
> 适用范围:JSONML 不支持某个字段时,或快速插入 callout / 分栏不想构造 JSONML 时。**默认优先 §4.4 路径 B**(block update/insert `--content-format jsonml`),本节是老接口次选路径。
|
||||
|
||||
```bash
|
||||
# 列出所有 block,定位 BLOCK_ID
|
||||
dws doc block list --node <nodeId>
|
||||
|
||||
# 改一个 block 的文本
|
||||
dws doc block update --node <nodeId> --block-id <BLOCK_ID> --content "替换后的内容" --content-format element
|
||||
|
||||
# 在某个 block 后插入
|
||||
dws doc block insert --node <nodeId> --ref-block <BLOCK_ID> --where after --heading "补充说明" --level 2 --content-format element
|
||||
|
||||
# 插入复杂块(callout / 分栏)—— element 默认按 JSON 解析
|
||||
dws doc block insert --node <nodeId> --ref-block <BLOCK_ID> --where after --content-format element \
|
||||
--element '{"blockType":"callout","callout":{"emoji":"⚠️","bgColor":"#FDE2E0","content":[{"text":"高风险操作,先备份"}]}}'
|
||||
|
||||
# 若改写过程已经在用 JSONML,整段精修也可走 jsonml 路径(uuid 必须 == --block-id)
|
||||
dws doc block insert --node <nodeId> --ref-block <BLOCK_ID> --where after --content-format jsonml \
|
||||
--element '["container",{"uuid":"co_new","subType":"colorBlocks","metadata":{"bgcolor":"#FDE2E0","border":"#F5C2C7"}},["p",{"uuid":"co_new_p1"},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"高风险操作,先备份"]]]]'
|
||||
```
|
||||
|
||||
字段结构以 [doc-block.md](../doc-block.md) 为准,不要猜。callout 字段名不确定时,先用 `doc block list --node <id> --block-type callout` 抓现有 callout 实例看真实字段。整段 JSONML 形态与可复制范例见 §4.4 与 [doc-jsonml-cookbook.md](../format/doc-jsonml-cookbook.md)。
|
||||
|
||||
### 4.4 JSONML 无损改写(**首选路径**)
|
||||
|
||||
> 改写已有文档**默认走本节**——保真度最高,callout / 分栏 / 表格 / @人 / 附件 / 颜色 / 嵌套都能 1:1 round-trip;写入端有 validator 兜底。其他路径(§4.1/4.2/4.3/4.5 markdown)仅在 §1.3 列出的"次选 / 兜底"场景下使用。
|
||||
|
||||
两条子路径:
|
||||
|
||||
**路径 B:单 block JSONML 精修(最常用——只动一个 block 时的默认选择)**
|
||||
|
||||
```bash
|
||||
# 1. 列出所有 block 拿到 uuid
|
||||
dws doc block list --node <nodeId> --content-format jsonml
|
||||
|
||||
# 2. 读单个 block 完整子树
|
||||
dws doc block list --node <nodeId> --content-format jsonml --block-id <BLOCK_UUID>
|
||||
|
||||
# 3. 改完后写回(uuid 必须 == --block-id)
|
||||
dws doc block update --node <nodeId> --block-id <BLOCK_UUID> --content-format jsonml \
|
||||
--element '["p", {"uuid": "<BLOCK_UUID>"}, ["span", {"data-type": "text"}, ["span", {"data-type": "leaf"}, "新内容"]]]'
|
||||
|
||||
# 在某个 block 前/后插入新 block
|
||||
dws doc block insert --node <nodeId> --ref-block <BLOCK_UUID> --where after --content-format jsonml \
|
||||
--element '["container", {"uuid": "co1", "subType": "colorBlocks", "metadata": {"bgcolor": "#E8F2FE", "border": "#B3D4FC"}}, ["p", {"uuid": "co1p1"}, ["span", {"data-type": "text"}, ["span", {"data-type": "leaf"}, "提示内容"]]]]'
|
||||
```
|
||||
|
||||
**路径 A:整篇 JSONML overwrite(一次改多处、改 root 级 sectPr 才用)**
|
||||
|
||||
```bash
|
||||
# 1. 读出完整 JSONML 结构(输出含 revision,普通改写场景下不需要)
|
||||
dws doc +fetch --node <nodeId> --detail full --format json
|
||||
|
||||
# 2. 解析 JSON,修改 jsonml 数组中的目标节点
|
||||
# 节点结构见 doc-jsonml-schema.md,可复制范例见 doc-jsonml-cookbook.md
|
||||
|
||||
# 3. 写回工作目录内相对文件 ./drafts/doc_modified.json,格式 {"jsonml": [...]}
|
||||
|
||||
# 4. 提交修改(默认直接覆盖,不做并发检查)
|
||||
dws doc +update --node <nodeId> --command overwrite --content @./drafts/doc_modified.json \
|
||||
--doc-format jsonml
|
||||
```
|
||||
|
||||
> **并发安全模式(担心被并发覆盖时使用)**:如果担心多 agent 同时改这篇文档,可以把第 1 步 read 返回的 `revision` 通过 `--revision <N>` 透传给第 4 步:服务端会做并发检查,版本不一致返回 `VersionConflict`,此时回到第 1 步重读重写即可。普通单 agent 改写场景默认不传 `--revision`。
|
||||
|
||||
#### JSONML 写入端的 validator
|
||||
|
||||
写入命令(`doc create/update` + `doc block insert/update`)走 **validate** 一步,不做结构修复:
|
||||
|
||||
| 行为 | 缺省 | `--fix-jsonml` |
|
||||
|------|------|----------------|
|
||||
| JSON 语法修复(括号/逗号补全) | ✗ | ✓(打印 `[FIX]`) |
|
||||
| validator 阻断(HasErrors → 拒发) | ✓ | ✓ |
|
||||
| root 校验(仅 doc create/update) | ✓ | ✓ |
|
||||
|
||||
报错格式(agent 友好):
|
||||
|
||||
```
|
||||
$[2][2]: paragraph child must be span wrapper, got raw string.
|
||||
Suggestion: ["span",{"data-type":"text"},["span",{"data-type":"leaf"},"<your text>"]]
|
||||
```
|
||||
|
||||
设计要点:
|
||||
|
||||
- 缺省为严格模式:不做结构修复,裸字符串、缺 uuid 等错误会被 validator 抦下。
|
||||
- `doc create/update` 要求 body 必须以 `["root", ...]` 为根节点,缺少会报错。`doc block insert/update` 不要求 root。
|
||||
- `--fix-jsonml`:启用 JSON 语法修复(修复 LLM 遗漏的括号/逗号),推荐 agent 调用。
|
||||
|
||||
**何时不走本节、改用 markdown**:纯文本追加章节(§4.2)、整篇按全新骨架重写(§4.5,且无富结构需要保留时)、只在乎"加一段文字"且确认目标段落无 callout / 分栏 / 颜色 / @人 / 附件。其余场景默认本节。
|
||||
|
||||
字段细节见 [doc-jsonml-schema.md](../format/doc-jsonml-schema.md);可复制范例见 [doc-jsonml-cookbook.md](../format/doc-jsonml-cookbook.md)。
|
||||
|
||||
### 4.5 整篇 overwrite
|
||||
|
||||
适合「按新风格重写整篇」「按新骨架重组结构」。
|
||||
|
||||
**形态选择(按 §1.3 优先级)**:
|
||||
|
||||
- 若原文档含 callout / 分栏 / 颜色 / @人 / 附件 / 嵌套结构且需要保留——**走 §4.4 路径 A**(整篇 JSONML overwrite;默认不带 `--revision`,担心并发时再加)
|
||||
- 若是纯文本骨架重写、原文档没有富结构需要保真——走本节 markdown overwrite
|
||||
|
||||
执行前必须先向用户**显式提示**:
|
||||
|
||||
> 注意:本次操作将覆盖整篇文档内容(约 {size})。可能存在以下风险:
|
||||
> - 大文档 overwrite 可能被后端静默降级为 append,导致**旧内容残留 + 新内容追加在末尾**
|
||||
> - markdown overwrite 会丢失原文档的 callout / 分栏 / 颜色等富结构;如需保真改走 §4.4 路径 A
|
||||
> - 写入完成后我会回读校验,发现异常会主动报告
|
||||
>
|
||||
> 是否继续?
|
||||
|
||||
得到确认后执行(markdown 兜底路径):
|
||||
|
||||
```bash
|
||||
dws doc +checkpoint-update --node <nodeId> --mode overwrite --content @./drafts/<name>-full.md
|
||||
```
|
||||
|
||||
读取 `+checkpoint-update` 的 checkpoint、write、verify 步骤;只有 partial/unknown 时才按 §6 恢复。
|
||||
|
||||
### 4.6 超长内容追加(分块 append)
|
||||
|
||||
当一次性追加内容 **超过 200KB** 时,必须拆分为多片 `--mode append`,并在执行第一片**之前**向用户发出截断风险提示等待确认。
|
||||
|
||||
完整规范(提示话术模板、触发条件、失败处理)见 [04-document.md «分块 append 截断风险提示»](../../04-document.md)。
|
||||
|
||||
update 场景下的额外约束:
|
||||
|
||||
1. 按段落/标题边界切分,**禁止**在表格、代码块、列表内部截断
|
||||
2. 每写一片记录已写入的最后一个标题/段落标记,供 §6 回读比对
|
||||
3. 与既有内容衔接位置不能产生悬空标题或断列表
|
||||
|
||||
---
|
||||
|
||||
## 五、改写时的样式约束
|
||||
|
||||
按 [doc-style-guideline.md](./doc-style-guideline.md) 处理:
|
||||
|
||||
- **文档类型保持不变**;用户明确要求转型时除外(如从「执行型 SOP」改成「说明型接口文档」)
|
||||
- **同类信息保持一致**:改写时不要把原本统一的元素改为多种表达
|
||||
- **颜色/emoji 语义**:改写后仍满足 style guideline §5「颜色与视觉语义」的一致性
|
||||
- **不删除附件/图片**;用户明确要求时除外
|
||||
|
||||
---
|
||||
|
||||
## 六、回读验收
|
||||
|
||||
`+update/+checkpoint-update` 已统一确认与验证。正常成功禁止额外整篇读取;partial/unknown 或确需检查富结构时,使用最小范围 `+fetch`。
|
||||
|
||||
校验要点:
|
||||
|
||||
- 改写章节的关键标题、段落首句、表格表头是否符合预期
|
||||
- overwrite 后旧内容是否真的被清除
|
||||
- append 后新内容是否在期望位置
|
||||
- 表格、代码块、列表跨块元素是否完整
|
||||
- @人、附件、图片等保真要素是否原样保留
|
||||
|
||||
### 异常处理
|
||||
|
||||
| 现象 | 可能原因 | 处理 |
|
||||
|------|----------|------|
|
||||
| overwrite 后旧内容残留 + 新内容追加在末尾 | overwrite 被静默降级为 append | 告知用户 overwrite 降级,按下方「先清空再重建」路径修复 |
|
||||
| append 后部分片段缺失 | 分块写入丢失 | 定位缺失片段,针对该段单独再 append 一次 |
|
||||
| @人 / 附件被替换为纯文本 | 改写时未走保真约束 | 用 JSONML 无损编辑修复(§4.4)|
|
||||
| 整篇内容乱序 | 写入顺序异常 | 报告给用户;若可重做,按下方「先清空再重建」路径修复 |
|
||||
|
||||
**禁止**在未回读的情况下向用户报告"已完成"。
|
||||
|
||||
---
|
||||
|
||||
## 七、交付口径
|
||||
|
||||
只报告已经验证过的信息:
|
||||
|
||||
- 改写涉及的章节范围
|
||||
- 改写后的 nodeId 与 docUrl
|
||||
- 回读验收结果(哪些章节确认改写成功、保真要素是否完整)
|
||||
- 如有缺失或异常,说明具体位置和已采取的修复动作
|
||||
|
||||
未回读前,不要说「内容完整」「改写完成」。
|
||||
Reference in New Issue
Block a user