mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 14:02:43 +08:00
chore: sync lark-doc skill from online-doc
This commit is contained in:
@@ -8,45 +8,44 @@ metadata:
|
||||
cliHelp: "lark-cli docs --help; lark-cli docs +create --help; lark-cli docs +fetch --help; lark-cli docs +update --help; lark-cli docs +resource-download --help; lark-cli docs +resource-update --help; lark-cli docs +resource-delete --help"
|
||||
---
|
||||
|
||||
# docs
|
||||
# docs (v2)
|
||||
|
||||
**身份:文档操作默认使用 `--as user`。首次使用前执行 `lark-cli auth login`。**
|
||||
|
||||
> **CRITICAL — API 版本:本 skill 使用 v2 API。执行 `docs +create`、`docs +fetch`、`docs +update` 时必须显式传入 `--api-version v2`。**
|
||||
|
||||
```bash
|
||||
# 常用示例
|
||||
lark-cli docs +fetch --doc "文档URL或token"
|
||||
lark-cli docs +create --content '<title>标题</title><p>内容</p>'
|
||||
lark-cli docs +update --doc "文档URL或token" --command append --content '<p>内容</p>'
|
||||
lark-cli docs +fetch --api-version v2 --doc "文档URL或token"
|
||||
lark-cli docs +create --api-version v2 --content '<title>标题</title><p>内容</p>'
|
||||
lark-cli docs +update --api-version v2 --doc "文档URL或token" --command append --content '<p>内容</p>'
|
||||
```
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
**CRITICAL — 执行对应操作前,MUST 先用 Read 工具读取以下文件,缺一不可:**
|
||||
1. [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md) — 认证、权限处理、全局参数(所有操作通用)
|
||||
2. **读取文档(`docs +fetch`)** → 必读 [`lark-doc-fetch.md`](references/lark-doc-fetch.md)(`--scope` / `--detail` 选择、局部读取策略、`<fragment>` / `<excerpt>` 输出结构)
|
||||
3. **创建或编辑文档内容** → 必读 [`lark-doc-xml.md`](references/lark-doc-xml.md)(XML 语法规则,仅当用户明确要求 Markdown 时改读 [`lark-doc-md.md`](references/lark-doc-md.md))和 [`lark-doc-style.md`](references/style/lark-doc-style.md)(元素选择、丰富度规则、颜色语义);从零创建时加读 [`lark-doc-create-workflow.md`](references/style/lark-doc-create-workflow.md);编辑已有文档时加读 [`lark-doc-update.md`](references/lark-doc-update.md) 和 [`lark-doc-update-workflow.md`](references/style/lark-doc-update-workflow.md)
|
||||
1. **读取文档(`docs +fetch --api-version v2`)** → 必读 [`lark-doc-fetch.md`](references/lark-doc-fetch.md)(`--scope` / `--detail` 选择、局部读取策略、`<fragment>` / `<excerpt>` 输出结构)
|
||||
2. **创建或编辑文档内容** → 必读 [`lark-doc-xml.md`](references/lark-doc-xml.md)(XML 语法规则,仅当用户明确要求 Markdown 时改读 [`lark-doc-md.md`](references/lark-doc-md.md))和必读 [`lark-doc-style.md`](references/style/lark-doc-style.md)(写作原则:默认段落、按体裁、组件克制);从零创建时加读 [`lark-doc-create-workflow.md`](references/style/lark-doc-create-workflow.md);编辑已有文档时加读 [`lark-doc-update.md`](references/lark-doc-update.md) 和 [`lark-doc-update-workflow.md`](references/style/lark-doc-update-workflow.md)
|
||||
|
||||
**未读完以上文件就执行相应操作会导致参数选择错误或格式错误。**
|
||||
|
||||
> **格式选择规则(全局):**
|
||||
> - **创建 / 导入场景**(`docs +create`,或 `docs +update --command append/overwrite` 的整段写入):XML 和 Markdown 都可以。用户提供 `.md` 本地文件、或明确说"导入 Markdown"时,直接用 Markdown;否则默认 XML(可用 callout、grid、checkbox 等富 block)。
|
||||
> - **创建 / 导入场景**(`docs +create`,或 `docs +update --command append/overwrite` 的整段写入):XML 和 Markdown 都可以。用户提供 `.md` 本地文件、或明确说"导入 Markdown"时,直接用 Markdown;否则默认 XML。
|
||||
> - **精准编辑场景**(`docs +update` 的 `str_replace` / `block_insert_after` / `block_replace` / `block_delete` / `block_move_after` 等局部精修指令):优先使用 XML(`--doc-format xml`,即默认值)。XML 能稳定表达 block 结构和样式,局部精修更可控;不要因为 Markdown 更简单就自行切换。
|
||||
|
||||
## 快速决策
|
||||
- 用户要**复制文档 / 创建文档副本 / 另存为副本**时,切到 [`lark-drive`](../lark-drive/SKILL.md),按其中的复制指引使用 `lark-cli drive files copy`;不要用 `docs +fetch` + `docs +create` 重建正文,也不要走 `drive +export` / `drive +import`。
|
||||
- 先判定任务路径:找文档 / 导入导出走 [`lark-drive`](../lark-drive/SKILL.md);只读 / 摘要用 `docs +fetch` 默认 `simple`;明确旧文本 → 新文本直接 `str_replace`;只有 block 链接、评论锚点、插入 / 替换 / 删除 / 移动才局部 fetch `with-ids`;保真改写已有内容才读 `full`
|
||||
- block 直达链接格式:`文档基础 URL#block_id`;没有 block_id 时局部 fetch `with-ids`
|
||||
- 连续执行多个文档写操作时,必须按 [`lark-doc-update.md`](references/lark-doc-update.md) 的「Block ID 生命周期」判断旧 block ID 是否还能复用;`overwrite` / `block_replace` / `block_delete` 后不要复用受影响的旧 ID,插入 / 复制后要重新 fetch 才能拿到新 block ID
|
||||
- 用户需要在文档内**创建、复制或移动**资源块(画板、电子表格、多维表格等)时,必须先读取 [`lark-doc-xml.md`](references/lark-doc-xml.md) 的「三、资源块」章节
|
||||
- 写文档时,由内容和用户意图决定表达形式;流程、架构、路线图、关键指标等信息可以使用画板,但不要默认把重要信息都画板化
|
||||
- 新增画板必须隔离到 SubAgent:简单图由 SubAgent 直接插入 `<whiteboard type="svg">完整 SVG</whiteboard>`,不读 `lark-whiteboard`;复杂图才由主 Agent 先建 `<whiteboard type="blank"></whiteboard>`,再启动 SubAgent 读取 `lark-whiteboard` 写入
|
||||
- 用户给了明确字数要求(写 N 字 / x-y 字 / x 字左右 / 上下浮动)→ 生成或改写后用 `scripts/count_chars.py`(lark-doc skill 根的 `scripts/` 下,对齐飞书「总字数」)校验,按 create/update workflow 的「字数校验」闭环处理(最多 2 轮,不达标如实告知)
|
||||
- 新增画板:思维导图/时序图/类图/饼图/甘特图用 Mermaid,由**主 Agent 直接插入** `<whiteboard type="mermaid">…</whiteboard>`,无需 SubAgent;其他图表隔离到 SubAgent——简单图由 SubAgent 直接插入 `<whiteboard type="svg">完整 SVG</whiteboard>`(不读 `lark-whiteboard`),复杂图由主 Agent 先建 `<whiteboard type="blank"></whiteboard>`,再启动 SubAgent 读取 `lark-whiteboard` 写入
|
||||
- 用户说"看一下文档里的图片/附件/素材""预览素材" → 用 `lark-cli docs +media-preview`
|
||||
- 用户明确说"下载素材" → 用 `lark-cli docs +media-download`
|
||||
- 用户明确说"下载/更新/删除文档封面图" → 用 `lark-cli docs +resource-download/+resource-update/+resource-delete --type cover`
|
||||
- `resource-*` 目前仅支持 Docx 封面资源;其他图片、附件或素材请走 `+media-*`
|
||||
- 如果目标是画板/whiteboard/画板缩略图 → 只能用 `lark-cli docs +media-download --type whiteboard`(不要用 `+media-preview`)
|
||||
- 拿到 spreadsheet URL/token 后 → 切到 `lark-sheets` 做对象内部操作
|
||||
- 用户需要统计文档的**总字数 / 总字符数**(word count / character count)时,先读取 [`lark-doc-word-stat.md`](references/lark-doc-word-stat.md),并按其中流程调用 [`scripts/doc_word_stat.py`](scripts/doc_word_stat.py);统计口径以该脚本为准,不要改用其他方式自行计算。
|
||||
- 用户说"给文档加评论""查看评论""回复评论""给评论加/删除表情 reaction" → 切到 `lark-drive` 处理
|
||||
- 文档内容中出现嵌入的 `<sheet>`、`<bitable>` 或 `<cite file-type="sheets|bitable">` 标签时 → **必须主动提取 token 并切到对应技能下钻读取内部数据**,不能只呈现标签本身
|
||||
|
||||
@@ -56,8 +55,7 @@ lark-cli docs +update --doc "文档URL或token" --command append --content '<p>
|
||||
| `<bitable token="..." table-id="...">` | `token` -> app_token, `table-id` | [`lark-base`](../lark-base/SKILL.md) |
|
||||
| `<cite type="doc" file-type="sheets" token="..." sheet-id="...">` | 同 `<sheet>` | [`lark-sheets`](../lark-sheets/SKILL.md) |
|
||||
| `<cite type="doc" file-type="bitable" token="..." table-id="...">` | 同 `<bitable>` | [`lark-base`](../lark-base/SKILL.md) |
|
||||
| `<vc-transcribe-tab vc-node-id="...">` | `vc-node-id` -> note_id | [`lark-note`](../lark-note/SKILL.md):先 `note +detail --note-id <vc-node-id>` |
|
||||
| `<synced_reference src-token="..." src-block-id="...">` | `src-token` -> doc_token, `src-block-id` -> block_id | 用 `docs +fetch` 读取 src-token 文档,定位 block |
|
||||
| `<synced_reference src-token="..." src-block-id="...">` | `src-token` -> doc_token, `src-block-id` -> block_id | 用 `docs +fetch --api-version v2` 读取 src-token 文档,定位 block |
|
||||
|
||||
## Shortcuts(推荐优先使用)
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
> **前置条件(MUST READ):** 生成文档内容前,必须先用 Read 工具读取以下文件,缺一不可:
|
||||
> 1. [`lark-doc-xml.md`](lark-doc-xml.md) — XML 语法规则(使用 Markdown 格式时改读 [`lark-doc-md.md`](lark-doc-md.md))
|
||||
> 2. [`lark-doc-style.md`](style/lark-doc-style.md) — 排版指南(元素选择、丰富度规则、颜色语义)
|
||||
> 3. [`lark-doc-create-workflow.md`](style/lark-doc-create-workflow.md) — 从零创作工作流(Code-Act Loop、并行执行策略)
|
||||
> 2. [`lark-doc-style.md`](style/lark-doc-style.md) — 写作原则(默认段落、按体裁、组件克制)
|
||||
> 3. [`lark-doc-create-workflow.md`](style/lark-doc-create-workflow.md) — 从零创作工作流(Code-Act Loop、单 Agent 串行撰写)
|
||||
>
|
||||
> **未读完以上文件就生成内容会导致格式错误。**
|
||||
|
||||
从 XML(默认)或 Markdown 内容创建一个新的飞书云文档。
|
||||
|
||||
> **⚠️ 格式选择规则:** 创建 / 导入场景下 XML 和 Markdown 都可以——用户提供 `.md` 本地文件、或明确说"导入 Markdown"时,直接用 Markdown;没有明确指示时默认 XML(表达能力更强,支持 callout、grid、checkbox 等富 block 类型)。不要在用户没要求的情况下主动从 XML 切到 Markdown,也不要在用户已给出 Markdown 时强行改成 XML。
|
||||
> **⚠️ 格式选择规则:** 创建 / 导入场景下 XML 和 Markdown 都可以——用户提供 `.md` 本地文件、或明确说"导入 Markdown"时,直接用 Markdown;没有明确指示时默认 XML(表达能力更强,可承载更丰富的结构化内容)。不要在用户没要求的情况下主动从 XML 切到 Markdown,也不要在用户已给出 Markdown 时强行改成 XML。
|
||||
|
||||
## 命令
|
||||
|
||||
@@ -72,8 +72,8 @@ lark-cli docs +create --doc-format markdown --title "项目计划" --content $'#
|
||||
|
||||
## 参考
|
||||
|
||||
- [`lark-doc-create-workflow.md`](style/lark-doc-create-workflow.md) — 从零创作工作流(Code-Act Loop、并行执行策略)
|
||||
- [`lark-doc-style.md`](style/lark-doc-style.md) — 文档样式指南(元素选择 + 丰富度规则 + 颜色语义)
|
||||
- [`lark-doc-create-workflow.md`](style/lark-doc-create-workflow.md) — 从零创作工作流(Code-Act Loop、单 Agent 串行撰写)
|
||||
- [`lark-doc-style.md`](style/lark-doc-style.md) — 文档写作原则(默认段落、按体裁、组件克制)
|
||||
- [`lark-doc-xml.md`](lark-doc-xml.md) — XML 语法规范
|
||||
- [`lark-doc-fetch.md`](lark-doc-fetch.md) — 获取文档
|
||||
- [`lark-doc-update.md`](lark-doc-update.md) — 更新文档
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
> **前置条件(MUST READ):** 生成文档内容前,必须先用 Read 工具读取以下文件,缺一不可:
|
||||
> 1. [`lark-doc-xml.md`](lark-doc-xml.md) — XML 语法规则(使用 Markdown 格式时改读 [`lark-doc-md.md`](lark-doc-md.md))
|
||||
> 2. [`lark-doc-style.md`](style/lark-doc-style.md) — 排版指南(元素选择、丰富度规则、颜色语义)
|
||||
> 3. [`lark-doc-update-workflow.md`](style/lark-doc-update-workflow.md) — 改写增强工作流(Code-Act Loop、并行执行策略)
|
||||
> 2. [`lark-doc-style.md`](style/lark-doc-style.md) — 写作原则(默认段落、按体裁、组件克制)
|
||||
> 3. [`lark-doc-update-workflow.md`](style/lark-doc-update-workflow.md) — 改写增强工作流(Code-Act Loop、单 Agent 串行改写)
|
||||
>
|
||||
> **未读完以上文件就生成内容会导致格式错误。**
|
||||
|
||||
@@ -232,7 +232,7 @@ lark-cli docs +update --doc "<doc_id>" --command str_replace \
|
||||
|
||||
> **`docs +update` 不能直接编辑已有画板的内容。** 本命令只能**新增**画板块;要修改已有画板,先用 `docs +fetch` 取到 `<whiteboard token="...">`,再按 [`lark-doc-whiteboard.md`](lark-doc-whiteboard.md) 启动 SubAgent 读取 [`lark-whiteboard`](../../lark-whiteboard/SKILL.md) 并写入。
|
||||
|
||||
画板的语法选型与插入示例见 [`lark-doc-style.md`](style/lark-doc-style.md) 的「画板语法与插入」章节。
|
||||
画板的语法选型与插入示例见 [`lark-doc-xml.md`](lark-doc-xml.md) 与 [`lark-doc-whiteboard.md`](lark-doc-whiteboard.md)。
|
||||
|
||||
## 最佳实践
|
||||
|
||||
@@ -252,8 +252,8 @@ lark-cli docs +update --doc "<doc_id>" --command str_replace \
|
||||
|
||||
## 参考
|
||||
|
||||
- [`lark-doc-update-workflow.md`](style/lark-doc-update-workflow.md) — 改写增强工作流(Code-Act Loop、并行执行策略)
|
||||
- [`lark-doc-style.md`](style/lark-doc-style.md) — 文档样式指南(元素选择 + 丰富度规则 + 颜色语义)
|
||||
- [`lark-doc-update-workflow.md`](style/lark-doc-update-workflow.md) — 改写增强工作流(Code-Act Loop、单 Agent 串行改写)
|
||||
- [`lark-doc-style.md`](style/lark-doc-style.md) — 文档写作原则(默认段落、按体裁、组件克制)
|
||||
- [`lark-doc-xml.md`](lark-doc-xml.md) — XML 语法规范
|
||||
- [`lark-doc-fetch.md`](lark-doc-fetch.md) — 获取文档
|
||||
- [`lark-doc-create.md`](lark-doc-create.md) — 创建文档
|
||||
|
||||
@@ -13,8 +13,8 @@ p, h1-h9, ul, ol, li, table, thead, tbody, tr, th, td, blockquote, pre, code, hr
|
||||
## 容器标签
|
||||
|标签|说明|关键属性|
|
||||
|-|-|-|
|
||||
| `<callout>` | 高亮框,子块仅支持文本、标题、列表、待办、引用 | `emoji`(默认 bulb), `background-color`, `border-color`, `text-color` |
|
||||
| `<grid>` + `<column>` | 分栏布局,各列 width-ratio 之和为 1 | `width-ratio` |
|
||||
| `<callout>` | 高亮框,子块仅支持文本、标题、列表、待办、引用。**强提醒专用,使用前先看 `lark-doc-style.md` 的写作原则** | `emoji`(默认 bulb), `background-color`, `border-color`, `text-color` |
|
||||
| `<grid>` + `<column>` | 分栏布局,各列 width-ratio 之和为 1。**使用前先看 `lark-doc-style.md` 的写作原则** | `width-ratio` |
|
||||
| `<whiteboard>` | 嵌入画板 | `type`: `blank` \| `mermaid` \| `plantuml` \| `svg` |
|
||||
| `<pre>` | (代码块,内含 `code`)| `lang`, `caption` |
|
||||
| `<figure>` | 视图容器 | `view-type` |
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
## 典型 Code-Act Loop 流程
|
||||
|
||||
### 步骤一:规划与初始创建(串行)
|
||||
### 步骤一:规划与撰写(单 Agent 串行)
|
||||
|
||||
正文由主 Agent 一人从规划到撰写从头到尾完成,**不拆分给并行子 Agent 分节写**——文档要靠全局视角保证前后连贯、不重复、不矛盾;分节并行会丢掉这个视角,也无法执行「全文级」的组件约束(这类约束没有任何单节子 Agent 看得到全文)。
|
||||
|
||||
1. 分析用户需求:受众、目的、范围
|
||||
2. 设计大纲:根据任务自然选择结构。可以是短文、纪要、FAQ、方案、报告、清单或其他形式;不要默认套固定章节、固定开头或固定富 block 配比
|
||||
@@ -24,36 +26,47 @@
|
||||
- ⚠️ 创建较长文档时,**不要**一次性把完整章节内容塞进 `--content`。超长 `--content` 容易触发字符/参数限制。
|
||||
- 完整内容留到步骤二,由各 Agent 用 `block_insert_after --block-id <章节标题 block_id>` 分段写入。
|
||||
- ⚠️ **`@file` 路径限制**:`--content @file` 只接受当前工作目录下的相对路径,传绝对路径(如 `@/tmp/xxx.md`)会报 `unsafe file path`。需要落盘时,将文件写在 cwd 下,用完自行清理。
|
||||
3. `docs +create --api-version v2` 创建并撰写:
|
||||
- **短文档**:一次写入完整内容
|
||||
- **长文档**:先建骨架(标题 + 各级标题),再由主 Agent **顺序逐节**用 `block_insert_after --block-id <章节标题 block_id>` 补全正文;写完一节再写下一节,始终带着已写内容的上下文,保证衔接、不重复
|
||||
- ⚠️ 不要一次性把超长完整内容塞进 `--content`,容易触发字符/参数限制;长文按节分次写入
|
||||
- ⚠️ 同一节内多次插入时,要锚到**上一个新插入的 block**(按 [`lark-doc-update.md`](../lark-doc-update.md) 的「Block ID 生命周期」),否则反复锚同一个标题会让段落顺序颠倒
|
||||
- ⚠️ 若先建骨架写了占位摘要,补正文时**删除占位摘要**,不要留残渣
|
||||
- ⚠️ **`@file` 路径限制**:`--content @file` 只接受当前工作目录下的相对路径,传绝对路径(如 `@/tmp/xxx.md`)会报 `unsafe file path`。需要落盘时,将文件写在 cwd 下,用完自行清理
|
||||
|
||||
### 步骤二:分段撰写(并行 Agent)
|
||||
### 步骤二:整合审查与画板识别(串行)
|
||||
|
||||
4. Spawn Agent 并行撰写各章节。每个 Agent 需收到:
|
||||
- 文档 token、负责的章节范围、用户目标、目标读者和已有风格线索
|
||||
- `lark-doc-xml.md` 和 `lark-doc-style.md` 的完整路径(Agent 须先读取)
|
||||
- 使用 `block_insert_after --block-id <章节标题 block_id>` 写入对应章节内容
|
||||
4. `docs +fetch --api-version v2 --detail with-ids` 获取文档,审查整体效果
|
||||
5. 评估内容是否满足用户目标:事实是否完整、结构是否清楚、语气是否匹配、是否保留必要素材;检查跨节有无重复、矛盾或断流。再按 `lark-doc-style.md` 的写作原则**逐节核对**,发现问题就地定向修正:
|
||||
- **去列举**:叙述性内容(背景 / 现状 / 认识 / 分析 / 成效等)是否被做成了列举?是则改成段落;列举只留给真正并列的具体措施 / 步骤 / 清单。
|
||||
- **查"通篇一是二是"**:是不是每个方面 / 每节都齐刷刷"一是 / 二是 / 三是"、几乎没有叙述段落?是则给背景 / 认识 / 分析 / 过渡补上段落,「一是 / 二是」只收到列具体问题 / 措施那一处(纯清单 / 台账类除外)。
|
||||
- **查编号**:全篇是否一套、不跳号、不跳级;**有没有中文序号 + 阿拉伯小数混用(一、+ 1.1)**。
|
||||
- **查呈现**:成行成列的数据是否该用表格却写成了段落 / "A+B+C"串?"小标题 + 一句话"的小项是否被升成了标题?是则按 `lark-doc-style.md` §二改成表格 / 标签行 / 加粗引导句段落。
|
||||
- **查组件**:高亮块 / 分栏 / 画板 / 颜色是否克制、符合体裁。
|
||||
6. **画板识别**:逐章节扫描,判断是否有段落用图明显比文字更易懂(流程 / 架构 / 时间线 / 对比 / 占比等,见 `lark-doc-style.md` 的画板原则)。默认用文字,只有确需图示才记录需要插图的章节、推荐画板类型、mermaid/SVG 路径和用于画图的源内容
|
||||
|
||||
### 步骤三:整合审查与画板识别(串行)
|
||||
### 步骤三:画板处理与润色
|
||||
|
||||
5. `docs +fetch --detail with-ids` 获取文档,审查整体效果
|
||||
6. 评估内容是否满足用户目标:事实是否完整、结构是否清楚、语气是否匹配、是否保留必要素材
|
||||
7. **画板意图识别**:逐章节扫描,按 `lark-doc-style.md`「画板意图识别」表判断是否有段落适合用图表达。重要信息优先画板化,记录需要插图的章节、推荐画板类型、mermaid/SVG 路径和用于画图的源内容
|
||||
7. **优先处理步骤二识别出的画板需求**:参考 [lark-doc-whiteboard.md](../lark-doc-whiteboard.md) 中的方式插入图表画板。画板渲染仍隔离到 SubAgent(见下方「画板 SubAgent 子任务要求」),正文本身不交给子 Agent
|
||||
8. 由**主 Agent 自行润色**(不另起内容子 Agent,正文始终一人维护):文字密集且不易读时,优先拆段、加小标题或调整顺序——叙述内容保持成段,**不要默认改成列表**,只有确属并列要点 / 步骤才用列表(见 `lark-doc-style.md`);只有确实存在行列数据时才用 `<table>`。其余富 block 的取舍一律遵循 `lark-doc-style.md` 的写作原则,不主动堆叠。需要明显分隔的主题可补充 `<hr/>`,不强制章节间都使用。本地图片使用 `docs +media-insert` 插入
|
||||
|
||||
### 步骤四:画板处理与润色(并行 Agent)
|
||||
|
||||
8. **优先处理步骤三识别出的画板需求**:
|
||||
参考 [lark-doc-whiteboard.md](../lark-doc-whiteboard.md)中的方式,插入图表画板。
|
||||
9. Spawn 内容改写 Agent 定向润色:
|
||||
- 文字密集且不易读时,优先拆段、改列表、增加小标题或调整顺序;只有确实存在行列数据、并列对比或强提醒信息时,才考虑 `<table>` / `<grid>` / `<callout>`
|
||||
- 需要明显分隔的主题可补充 `<hr/>`,不强制章节间都使用
|
||||
- 本地图片使用 `docs +media-insert` 插入
|
||||
**仅当**用户给了明确字数要求(写 N 字 / x-y 字 / x 字左右 / 上下浮动)时执行;否则**跳过本步**。字数必须用脚本量,不要自己估。
|
||||
|
||||
1. 把要求归一成参数:`>x`→`--min x`;`<y`→`--max y`;`x-y`→`--min x --max y`;`x 字左右`→`--approx x`(自动 ±10%)
|
||||
2. 量实际字数(对齐飞书「总字数」):`uv run scripts/count_chars.py --doc <document_id> <上面的目标参数>`(脚本在 lark-doc skill 根的 `scripts/` 下)
|
||||
3. 看输出 `verdict`:`pass` 即通过;`under` → 在最该展开的节补**实质内容**(非注水);`over` → 从最长/最冗余处删减。改完**重新跑脚本复测**
|
||||
4. **最多 2 轮**。2 轮后仍不达标:停止,不得为达标而注水或删关键内容;如实汇报【目标区间 / 当前字数 / 差值与方向 / 已试 2 轮 / 未达原因】并交付文档链接,**禁止谎称达标**
|
||||
|
||||
|
||||
## Agent 子任务要求
|
||||
|
||||
内容改写 Agent 必须收到:文档 token、章节范围(标题/block ID)、`lark-doc-xml.md` 和 `lark-doc-style.md` 路径、用户目标/风格要求、具体的 `docs +update` command 和 `--block-id`。
|
||||
## 画板 SubAgent 子任务要求
|
||||
|
||||
Mermaid 图由主 Agent 直接插入 `<whiteboard type="mermaid">...</whiteboard>`,无需 SubAgent。
|
||||
|
||||
SVG SubAgent 必须收到:文档 token、插入位置(标题/block ID)、图表目标、源内容片段、`lark-doc-xml.md` 路径,以及[lark-doc-whiteboard.md](../lark-doc-whiteboard.md) 中的 "SVG 设计 Workflow" 指南。它只负责插入一个 `<whiteboard type="svg">...</whiteboard>`,不改其他正文,也不读取 `lark-whiteboard`。
|
||||
SVG SubAgent 必须收到:文档 token、插入位置(标题/block ID)、图表目标、源内容片段、`lark-doc-xml.md` 路径,以及 [lark-doc-whiteboard.md](../lark-doc-whiteboard.md) 中的 "SVG 设计 Workflow" 指南。它只负责插入一个 `<whiteboard type="svg">...</whiteboard>`,不改其他正文,也不读取 `lark-whiteboard`。
|
||||
|
||||
已有画板更新 SubAgent 必须收到:board_token、图表目标、推荐画板类型、源内容片段、[`../../../lark-whiteboard/SKILL.md`](../../../lark-whiteboard/SKILL.md) 路径。它只负责写入画板,不改文档正文。
|
||||
|
||||
@@ -1,86 +1,59 @@
|
||||
# 文档表达组件参考
|
||||
# 飞书文档写作原则
|
||||
|
||||
本文件说明飞书文档可用的结构化表达方式,供模型在需要时选择。它不是固定模板,也不是强制排版规范。
|
||||
写飞书文档,像一个该领域资深的人类作者那样写,而不是把内容"装配"成组件。
|
||||
本文只讲"何时用、什么风格";具体标签 / 命令语法见 [`lark-doc-xml.md`](../lark-doc-xml.md)。
|
||||
|
||||
默认原则:优先理解用户目标、受众、素材形态和已有文档风格,由模型自主决定结构、语气和视觉呈现。只有当用户明确要求“美化、重排版、做成报告/方案/看起来更专业”等,或内容本身明显需要结构化承载时,才主动使用下列组件。
|
||||
## 一、用户明确要求优先
|
||||
|
||||
## 一、核心原则
|
||||
用户点名要某种格式——高亮块、分栏、列表、某编号体例、表格、画板、某模板、某已有文档的风格——**一律照用户的来,下面的"默认克制"全部让位**。用户给了样例或已有文档,就沿用它的结构与语气。
|
||||
|
||||
1. **服务内容,而非套模板**:先判断信息最自然的表达方式,再选择段落、列表、表格、分栏、画板等元素
|
||||
2. **尊重用户风格**:用户给出样例、语气、结构或已有文档时,优先沿用;没有要求时不强行使用固定开头、固定章节或固定视觉组件
|
||||
3. **适度结构化**:结构化 block 用于降低理解成本,不为了“丰富”而堆叠
|
||||
4. **保持一致但不过度统一**:同类信息可使用相近表达,但允许因内容差异采用不同形式
|
||||
5. **图示服务理解**:流程、架构、对比、风险、路线图、指标趋势等内容在图示明显降低理解成本时,可使用画板表达
|
||||
## 二、默认写连贯段落
|
||||
|
||||
## 二、元素选择指南
|
||||
用户没指定时,**默认是连贯段落**;其余按内容类型分流,别一律"少用结构",也别什么都升标题:
|
||||
|
||||
需要图表时,按类型选择插入方式:思维导图/时序图/类图/饼图/甘特图可用 `<whiteboard type="mermaid">` 直接内嵌;其他新图表可启动 SubAgent 插入 `<whiteboard type="svg">完整 SVG</whiteboard>`;只有编辑**已有**画板时才调用 **lark-whiteboard** skill。
|
||||
| 内容 | 用什么 | ❌ 别 |
|
||||
|---|---|---|
|
||||
| 叙述、论证、分析、说明 | **连贯段落** | 拆成列举 |
|
||||
| 真·行列数据(预算、指标、对比、排期、字段说明) | **表格** | 写成段落或"A+B+C"串 |
|
||||
| 字段:值(主题、时长、负责人等,少量) | **加粗标签行**或一句话 | 每字段一个标题 |
|
||||
| 方法 / 措施 + 每项一段描述 | **加粗引导句段落**(「**全程督导。**…」) | 每项升标题 |
|
||||
| 纯短并列项(无描述,如材料清单) | 列表 | — |
|
||||
| 章节(内容成块、需在目录导航) | 标题层级 | — |
|
||||
|
||||
| 场景 | 可选表达方式 |
|
||||
|--------------------------------------------|---------------------------------------|
|
||||
| 少数需要视觉提醒的短句,如风险、限制、待确认事项或关键提醒 | 需要视觉提醒时可用 `<callout>`;普通结论、摘要或章节导语优先使用段落、列表、小标题或加粗 |
|
||||
| 方案对比 / 优劣势 / Before vs After | 简短对比可用段落、列表或 `<grid>`;维度较多且需要逐项比较时再考虑 `<table>` 或画板 |
|
||||
| 简短低风险对比 | `<grid>` 2 列分栏 |
|
||||
| 需要按行列精确比较或查阅的数据,如指标、清单、字段说明、排期 | 可用 `<table>`;短要点、步骤、摘要或普通说明优先使用段落、列表或小标题 |
|
||||
| 任务清单 / 检查项 | `<checkbox>` |
|
||||
| 代码片段 | `<pre lang="x" caption="说明">` |
|
||||
| 引用 / 公式 | `<blockquote>` / `<latex>` |
|
||||
| 操作入口 / 跳转链接 | `<button>` / `<a type="url-preview">` |
|
||||
| 流程图 / 时间线 / 示意图 / 自定义图形 / 架构图 / 数据图 / 思维导图等 | 画板图表 |
|
||||
- 判断标准:**去掉结构后能顺成段落,就用段落;成行成列的数据,就用表格。**
|
||||
- **红线一:标题层级只给"章节"。** "小标题 + 一两句话"的小项(字段、方法、要点)不该占标题层级——按上表降成标签行 / 加粗引导句段落(否则目录里全是没信息量的条目)。
|
||||
- **红线二:列举(「一是 / 二是」「第一 / 第二」「(1)(2)(3)」)只给真正并列的具体项,且别每节都用。**
|
||||
- 「一是 / 二是」是党务列举的措辞——只用在列具体的**问题 / 措施**那一处;背景、现状、认识、分析、过渡、总结**一律成段**。
|
||||
- **整篇每段 / 每节都"一是 / 二是",和"每段一个 bullet"是同一个骨架化的错——不因为是党务就变对**(纯清单 / 台账类除外)。
|
||||
|
||||
## 三、按体裁写
|
||||
|
||||
### 画板意图识别
|
||||
- **公文 / 法律 / 学术 / 申报 / 项目方案等严肃正式提交物**:靠规范的标题层级、段落与编号体系表达;**默认不用高亮块、分栏**,要强调用加粗或规范小标题。
|
||||
- **面向公众号、微信等外部平台粘贴 / 发布的内容**:不用飞书特有富 block(高亮块、分栏等),粘出去会丢样式 / 错乱;改用标准标题、段落、列表、引用。
|
||||
- **一般文档**:以可读为先,不堆砌结构。
|
||||
|
||||
撰写或审查每个段落/章节时,**必须判断该内容是否适合用图表达**。满足以下任一特征时,应使用画板而非纯文本;如果该内容承载章节核心结论、关键决策或主要论据,即使结构较简单也优先画板化:
|
||||
## 四、编号与层级
|
||||
|
||||
| 内容特征 | 信号词 / 模式 | 推荐画板类型 |
|
||||
|-|-|-|
|
||||
| 多步骤的操作流程或决策路径 | "先…然后…最后"、"步骤 1/2/3"、"如果…则…否则" | 流程图 / 泳道图 |
|
||||
| 系统或模块间的依赖与交互 | "调用"、"依赖"、"上游/下游"、"请求→响应" | 架构图 |
|
||||
| 上下级或从属关系 | "汇报给"、"下属"、"隶属"、"团队结构" | 组织架构图 |
|
||||
| 时间线或阶段演进 | "Q1/Q2"、"里程碑"、"阶段一→阶段二"、日期序列 | 时间线 / 里程碑 |
|
||||
| 因果分析或问题归因 | "根因"、"原因"、"导致"、"影响因素" | 鱼骨图 |
|
||||
| 两个及以上方案/对象的多维度对比 | "vs"、"方案 A/B"、"优劣"、"对比" | 对比图 |
|
||||
| 层级递进或优先级排序 | "基础→进阶→高级"、"L1/L2/L3"、"核心→外围" | 金字塔图 |
|
||||
| 数值趋势或周期变化 | 带数字的时间序列、"增长/下降"、百分比变化 | 折线图 / 柱状图 |
|
||||
| 漏斗或转化率 | "转化率"、"漏斗"、"从…到…留存" | 漏斗图 |
|
||||
| 发散或归纳的思维结构 | "要点"、"维度"、"分支"、多层嵌套列表 | 思维导图 |
|
||||
| 循环或飞轮效应 | "正循环"、"飞轮"、"闭环"、"A 驱动 B 驱动 C" | 飞轮图 |
|
||||
| 占比分布 | "占比"、"份额"、"分布"、百分比加总 ≈100% | 饼图 / 树状图 |
|
||||
- **一套编号体例、全篇一致;最忌中文 + 阿拉伯混用。**
|
||||
- 公文 / 正式材料:「一、→(一)→ 1.→(1)」(全中文层级)。
|
||||
- 学术 / 技术 / 商业报告:「1 → 1.1 → 1.1.1」或「一、→(一)→ 1.」,**择一**。
|
||||
- ⚠️ **「一、」只能配「(一)」;要用阿拉伯小数就从顶层全用「1 / 1.1」。绝不「一、」配「1.1 / 2.1」**——这是最常见的混用。
|
||||
- **不混用**多套(别"第X部分"+"一、"+"1."混着来);**同级不跳号**;**不跳级**。
|
||||
- **编号 / 标题层级只给"章节"**,不要为了凑齐体例把每个小项都编上「(一)」、升成标题(小项怎么放见 §二)。
|
||||
- 简单的 1.2.3 并列项用**原生 `<ol seq="auto">`** 让飞书自动编号、自动对齐;「一、(一)」原生产不出,才手打成文字——此时用标题级别表达层次,**不靠手动缩进**、各级顶格(全角括号「()」叠手动缩进会视觉错位)。
|
||||
|
||||
**判断规则:**
|
||||
- 重要信息能图示就图示;不要为了省步骤把关键流程、架构、对比、风险链路写成纯文本
|
||||
- 低重要度、局部辅助信息才用 `<table>` / `<grid>` / `<callout>` 承载
|
||||
- 确定需要插入哪些图表后,参照 [lark-doc-whiteboard.md](../lark-doc-whiteboard.md) 中的方式,插入图表画板。
|
||||
## 五、飞书特有组件,克制使用
|
||||
|
||||
## 三、颜色语义
|
||||
- **高亮块 `<callout>`**:很重的强提醒信号,**默认不用**;只给"不提醒就会出错 / 遗漏"的关键项,全文极少(0~1 个),不要每节导语 / 结论都做成高亮块。
|
||||
- **分栏 `<grid>`**:仅左右信息量相当、确需并排对照的短内容;否则用段落或表格。
|
||||
- **画板**:默认用文字,只在**图示明显比文字更易懂**(流程、架构、时间线、对比、占比等)或用户要求时才用。怎么插、用哪种类型见 [`lark-doc-xml.md`](../lark-doc-xml.md) 与 [`lark-doc-whiteboard.md`](../lark-doc-whiteboard.md)。
|
||||
- **颜色**:默认朴素、不上色;需要时保持语义一致(信息蓝 / 成功绿 / 警告红 / 注意黄),不为装饰上色。可用色见 [`lark-doc-xml.md`](../lark-doc-xml.md) 的「美化系统」。
|
||||
|
||||
如果使用颜色,建议保持语义一致;不需要颜色时可以保持朴素文本风格:
|
||||
## 六、写完自检
|
||||
|
||||
| 语义 | emoji 前缀 | callout 背景色 | 文字色 |
|
||||
|-|-|-|-|
|
||||
| 信息、说明 | ℹ️ "说明:" | `light-blue` | `blue` |
|
||||
| 成功、推荐 | ✅ "推荐:" | `light-green` | `green` |
|
||||
| 警告 / 错误 / 风险 | ⚠️❌ | `light-red` | `red` |
|
||||
| 注意、待确认 | ❗"注意:" | `light-yellow` | `yellow` |
|
||||
| 中性、辅助 | — | `light-gray` | — |
|
||||
|
||||
- 表头可使用 `background-color="light-gray"`,也可以保持默认样式
|
||||
- 关键指标如使用 `<span text-color="green/red">` 突出,建议同时用 ↑↓ 或 +/- 标注方向(色觉无障碍)
|
||||
|
||||
## 四、排版规范
|
||||
|
||||
- 标题层级、段落长度、列表嵌套和 Grid 列数应以可读性为准,避免过深层级和过宽分栏
|
||||
- 文档开头可以是结论、背景、摘要、问题陈述、目录或直接正文,不强制使用 `<callout>`
|
||||
|
||||
## 五、质量自检
|
||||
|
||||
生成内容后可以从以下角度自检,但不要把这些项当作硬性比例或固定模板:
|
||||
|
||||
| 指标 | 自检问题 |
|
||||
|-|-|
|
||||
| 信息表达 | 当前结构是否符合用户目标,而不是套用固定报告模板? |
|
||||
| 阅读负担 | 是否有段落过长、层级过深、表格过宽或组件过多的问题? |
|
||||
| 风格匹配 | 是否延续了用户给定样例或已有文档风格? |
|
||||
| 组件必要性 | callout、grid、table、whiteboard 等是否真的提升理解? |
|
||||
| 保真度 | 改写时是否保留了原文事实、引用、图片、附件和资源块? |
|
||||
交付前快速回看:
|
||||
- 该成段的叙述是否被拆成了列表 / 序号?是否**每节都机械"一是 / 二是"、缺叙述**?
|
||||
- 成行成列的**数据是否该用表格**、却写成了段落或"A+B+C"串?
|
||||
- **"小标题 + 一句话"的小项是否被升成了标题**(目录里一堆没信息量的条目)?
|
||||
- 编号是否全篇一套、**没有中文 + 阿拉伯混用(一、+ 1.1)**、无跳号跳级?
|
||||
- 高亮块 / 分栏 / 画板 / 颜色是否克制、符合体裁?引用 / 图片 / 资源块是否保留?用户点名要的格式是否照做?
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
## 核心方法论 — Code-Act Loop
|
||||
通过自适应的 **Code-Act Loop** 驱动文档改写,而非固定模板式的工作流。每次任务都循环执行:
|
||||
1. **Plan(规划)** — 根据用户目标和文档当前状态,评估下一步该做什么
|
||||
2. **Execute(执行)** — 运行相应的 `lark-cli docs` 命令,或 **spawn** Agent 子任务并行推进
|
||||
2. **Execute(执行)** — 由主 Agent 自己运行 `lark-cli docs` 命令推进改写;仅画板渲染按需隔离到 SubAgent(见步骤二)
|
||||
3. **Observe(观察)** — 检查命令输出,验证正确性,确认内容是否满足用户目标
|
||||
4. **Iterate(迭代)** — 如需调整,回到 Plan 继续循环
|
||||
|
||||
@@ -19,37 +19,50 @@
|
||||
### 步骤一:分析与画板识别(串行)
|
||||
|
||||
1. **选择读取范围**(节省上下文的关键):
|
||||
- 用户只改某一节 / 文档较大 → 先 `docs +fetch --scope outline --max-depth 2` 拿目录,再 `docs +fetch --scope section --start-block-id <目标标题id> --detail with-ids` 精读该节(`section` 会自动展开到下一个同级/更高级标题前,不用手动算结束 block id)
|
||||
- 需要精确跨节区间 → `docs +fetch --scope range --start-block-id xxx --end-block-id yyy`(或 `--end-block-id -1` 读到末尾)
|
||||
- 用户只给了模糊关键词 → `docs +fetch --scope keyword --keyword xxx --context-before 1 --context-after 1 --detail with-ids`
|
||||
- 用户明确要改整篇 → `docs +fetch --detail with-ids`
|
||||
- 详见 [`lark-doc-fetch.md`](../lark-doc-fetch.md) "意图引导:选择正确的 --scope"
|
||||
- 用户只改某一节 / 文档较大 → 先 `docs +fetch --api-version v2 --scope outline --max-depth 2` 拿目录,再 `docs +fetch --api-version v2 --scope section --start-block-id <目标标题id> --detail with-ids` 精读该节(`section` 会自动展开到下一个同级/更高级标题前,不用手动算结束 block id)
|
||||
- 需要精确跨节区间 → `docs +fetch --api-version v2 --scope range --start-block-id xxx --end-block-id yyy`(或 `--end-block-id -1` 读到末尾)
|
||||
- 用户只给了模糊关键词 → `docs +fetch --api-version v2 --scope keyword --keyword xxx --context-before 1 --context-after 1 --detail with-ids`
|
||||
- 用户明确要改整篇 → `docs +fetch --api-version v2 --detail with-ids`
|
||||
- 详见 [`lark-doc-fetch.md`](../lark-doc-fetch.md) 的「选 `--scope`(读取范围)」
|
||||
2. 系统性评估:用户想改什么、现有文档风格是什么、哪些内容需要保留、哪些问题影响理解
|
||||
3. **画板意图识别**:逐章节扫描,按 `lark-doc-style.md`「画板意图识别」表判断哪些段落的信息适合用图表达。重要信息优先画板化,记录需要插图的章节(block ID)、推荐画板类型、mermaid/SVG路径和源内容片段
|
||||
3. **画板识别**:逐章节扫描,判断是否有段落用图明显比文字更易懂(流程 / 架构 / 时间线 / 对比 / 占比等,见 `lark-doc-style.md` 的画板原则)。默认用文字,只有确需图示才记录需要插图的章节(block ID)、推荐画板类型、mermaid/SVG路径和源内容片段
|
||||
4. 向用户简要说明改进计划(包含识别出的画板机会)
|
||||
|
||||
### 步骤二:定向改写(并行 Agent)
|
||||
### 步骤二:定向改写(单 Agent 串行)
|
||||
|
||||
5. **优先处理步骤一识别出的画板候选段落**:
|
||||
参考 [lark-doc-whiteboard.md](../lark-doc-whiteboard.md)中的方式,插入图表画板。
|
||||
6. Spawn 内容改写 Agent 在不重叠的章节上并行改进,各 Agent 收到文档 token 和特定 block ID:
|
||||
5. **优先处理步骤一识别出的画板候选段落**:参考 [lark-doc-whiteboard.md](../lark-doc-whiteboard.md) 中的方式插入图表画板。画板渲染仍隔离到 SubAgent(见下方「画板 SubAgent 子任务要求」),正文本身不交给子 Agent
|
||||
6. 由主 Agent **顺序逐节**改写,**不拆分给并行子 Agent**——这样能始终对照全文,保证风格一致、不重复、不顾此失彼,也能执行「全文级」的组件约束:
|
||||
- 沿用或轻微调整已有文档风格,除非用户要求彻底重排版
|
||||
- 优先通过重写段落、调整标题、拆分列表或补充小标题提升可读性
|
||||
- 富 block 是可选表达手段,不因固定比例而添加;画板类需求只走第 5 步
|
||||
- 优先通过重写段落、调整标题、补充小标题提升可读性;叙述内容保持成段,**不要默认改成列表**,只有确属并列要点 / 步骤才用列表(见 `lark-doc-style.md`)
|
||||
- 富 block 是可选表达手段,不因固定比例而添加,取舍遵循 `lark-doc-style.md` 的写作原则;画板类需求只走第 5 步
|
||||
|
||||
### 步骤三:验证(串行)
|
||||
|
||||
7. 获取更新后文档局部内容,检查是否符合用户目标和已有风格
|
||||
8. 检查是否满足用户目标并保留原有关键内容;如仍有明显问题则定向修正,向用户呈现结果
|
||||
8. 检查是否满足用户目标并保留原有关键内容。再按 `lark-doc-style.md` 的写作原则**逐节核对**,发现问题则定向修正:
|
||||
- **去列举**:叙述性内容(背景 / 现状 / 认识 / 分析 / 成效等)是否被做成了列举?是则改成段落;列举只留给真正并列的具体措施 / 步骤 / 清单。
|
||||
- **查"通篇一是二是"**:是不是每个方面 / 每节都齐刷刷"一是 / 二是 / 三是"、几乎没有叙述段落?是则给背景 / 认识 / 分析 / 过渡补上段落,「一是 / 二是」只收到列具体问题 / 措施那一处(纯清单 / 台账类除外)。
|
||||
- **查编号**:全篇是否一套、不跳号、不跳级;**有没有中文序号 + 阿拉伯小数混用(一、+ 1.1)**。
|
||||
- **查呈现**:成行成列的数据是否该用表格却写成了段落 / "A+B+C"串?"小标题 + 一句话"的小项是否被升成了标题?是则按 `lark-doc-style.md` §二改成表格 / 标签行 / 加粗引导句段落。
|
||||
- **查组件**:高亮块 / 分栏 / 画板 / 颜色是否克制、符合体裁。
|
||||
|
||||
## Agent 子任务要求
|
||||
修正后向用户呈现结果。
|
||||
|
||||
内容改写 Agent 必须收到:文档 token、章节范围(标题/block ID)、`lark-doc-xml.md` 和 `lark-doc-style.md` 路径、用户目标/风格要求、具体的 `docs +update` command 和 `--block-id`。
|
||||
### 步骤四:字数校验(无明确字数要求则跳过)
|
||||
|
||||
**仅当**用户给了明确字数要求(写 N 字 / x-y 字 / x 字左右 / 上下浮动)时执行;否则**跳过本步**。字数必须用脚本量,不要自己估。
|
||||
|
||||
1. 把要求归一成参数:`>x`→`--min x`;`<y`→`--max y`;`x-y`→`--min x --max y`;`x 字左右`→`--approx x`(自动 ±10%)
|
||||
2. 量实际字数(对齐飞书「总字数」):`uv run scripts/count_chars.py --doc <document_id> <上面的目标参数>`(脚本在 lark-doc skill 根的 `scripts/` 下)
|
||||
3. 看输出 `verdict`:`pass` 即通过;`under` → 在最该展开处补**实质内容**(非注水);`over` → 从最长/最冗余处删减。改完**重新跑脚本复测**
|
||||
4. **最多 2 轮**。2 轮后仍不达标:停止,不得为达标而注水或删关键内容;如实汇报【目标区间 / 当前字数 / 差值与方向 / 已试 2 轮 / 未达原因】并交付文档链接,**禁止谎称达标**
|
||||
|
||||
## 画板 SubAgent 子任务要求
|
||||
|
||||
Mermaid 图由主 Agent 直接插入 `<whiteboard type="mermaid">...</whiteboard>`,无需 SubAgent。
|
||||
|
||||
SVG SubAgent 必须收到:文档 token、插入位置(标题/block ID)、图表目标、源内容片段、`lark-doc-xml.md` 路径,以及[lark-doc-whiteboard.md](../lark-doc-whiteboard.md) 中的 "SVG 设计 Workflow" 指南。它只负责插入一个 `<whiteboard type="svg">...</whiteboard>`,不改其他正文,也不读取 `lark-whiteboard`。
|
||||
SVG SubAgent 必须收到:文档 token、插入位置(标题/block ID)、图表目标、源内容片段、`lark-doc-xml.md` 路径,以及 [lark-doc-whiteboard.md](../lark-doc-whiteboard.md) 中的 "SVG 设计 Workflow" 指南。它只负责插入一个 `<whiteboard type="svg">...</whiteboard>`,不改其他正文,也不读取 `lark-whiteboard`。
|
||||
|
||||
已有画板更新 SubAgent 必须收到:board_token、图表目标、推荐画板类型、源内容片段、[`../../../lark-whiteboard/SKILL.md`](../../../lark-whiteboard/SKILL.md) 路径。它只负责写入画板,不改文档正文。
|
||||
|
||||
**上下文节省提示**:Agent 如需在自己负责的章节内重新读取内容,优先用 `docs +fetch --scope section --start-block-id <章节标题id>`(自动覆盖整节),或 `--scope range --start-block-id xxx --end-block-id yyy` 精确区间,只拉自己的章节,不要重复拉全文。
|
||||
**上下文节省提示**:主 Agent 改某节时如需重新读取,优先用 `docs +fetch --api-version v2 --scope section --start-block-id <章节标题id>`(自动覆盖整节),或 `--scope range --start-block-id xxx --end-block-id yyy` 精确区间,只拉当前章节,不要重复拉全文。
|
||||
|
||||
133
skills/lark-doc/scripts/count_chars.py
Normal file
133
skills/lark-doc/scripts/count_chars.py
Normal file
@@ -0,0 +1,133 @@
|
||||
# /// script
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = []
|
||||
# ///
|
||||
"""
|
||||
统计飞书文档「总字数」,对齐飞书官方字数统计规则,用于字数遵循校验。
|
||||
|
||||
飞书官方规则(总字数):汉字 + 中文标点 + 英文单词 + 数字;英文标点、空格不计。
|
||||
计数源:文档 raw_content(飞书已抽取的纯文本,标签已剥离)。
|
||||
⚠️ raw_content 会包含 @文档 / @人 / 卡片等飞书「不计入字数」的嵌入内容文字。
|
||||
对「生成的散文」无影响(不含这些嵌入),与飞书一致;
|
||||
读取嵌入密集的已有文档会偏高,那不是本功能的目标场景。
|
||||
说明:数字按「位」计(每个数字算 1,与飞书总字符数口径一致);
|
||||
总字数含标题(飞书亦含标题)。
|
||||
|
||||
用法:
|
||||
# 给文档 token,自动取 raw_content 并计数
|
||||
uv run scripts/count_chars.py --doc <document_id>
|
||||
# 直接数一段文本(stdin / 文件)
|
||||
echo "文本" | uv run scripts/count_chars.py
|
||||
uv run scripts/count_chars.py --file draft.txt
|
||||
# 带目标校验(任选其一):
|
||||
uv run scripts/count_chars.py --doc <id> --min 380 --max 420 # 区间 [x,y]
|
||||
uv run scripts/count_chars.py --doc <id> --min 100 # >=x(>x)
|
||||
uv run scripts/count_chars.py --doc <id> --max 100 # <=y(<y)
|
||||
uv run scripts/count_chars.py --doc <id> --approx 400 # x 左右 = ±10%
|
||||
|
||||
输出 JSON:{total_words, total_chars, target:{min,max}, verdict, gap}
|
||||
verdict: pass | under | over | none(未给目标)
|
||||
gap: 距区间还差多少(under/over 均为正数,pass=0)——告诉你要 +gap 或 -gap 字
|
||||
"""
|
||||
import sys
|
||||
import re
|
||||
import json
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
|
||||
def fetch_raw_content(doc_id, identity):
|
||||
cmd = ["lark-cli", "api", "GET",
|
||||
f"/open-apis/docx/v1/documents/{doc_id}/raw_content", "--as", identity]
|
||||
try:
|
||||
out = subprocess.run(cmd, capture_output=True, text=True)
|
||||
except FileNotFoundError:
|
||||
sys.exit("未找到 lark-cli:请先安装/配置 lark-cli,或改用 --file / stdin 传入文本")
|
||||
if out.returncode != 0:
|
||||
sys.exit(f"取 raw_content 失败: {out.stderr or out.stdout}")
|
||||
try:
|
||||
return json.loads(out.stdout)["data"]["content"]
|
||||
except Exception as e:
|
||||
sys.exit(f"解析 raw_content 失败: {e}\n{out.stdout[:300]}")
|
||||
|
||||
|
||||
def is_hanzi(ch):
|
||||
o = ord(ch)
|
||||
return (0x4E00 <= o <= 0x9FFF or 0x3400 <= o <= 0x4DBF
|
||||
or 0xF900 <= o <= 0xFAFF or 0x20000 <= o <= 0x2A6DF)
|
||||
|
||||
|
||||
def is_zh_punct(ch):
|
||||
o = ord(ch)
|
||||
# CJK 符号与标点 / 兼容形式
|
||||
if 0x3000 <= o <= 0x303F or 0xFE10 <= o <= 0xFE1F or 0xFE30 <= o <= 0xFE4F:
|
||||
return True
|
||||
# 全角 ASCII 标点(排除全角数字 FF10-FF19、全角字母 FF21-FF3A / FF41-FF5A)
|
||||
if (0xFF01 <= o <= 0xFF0F or 0xFF1A <= o <= 0xFF20
|
||||
or 0xFF3B <= o <= 0xFF40 or 0xFF5B <= o <= 0xFF65
|
||||
or 0xFFE0 <= o <= 0xFFEE): # 全角货币 ¥£¢ 等
|
||||
return True
|
||||
return ch in "·—…“”‘’"
|
||||
|
||||
|
||||
def count(text):
|
||||
hanzi = sum(1 for ch in text if is_hanzi(ch))
|
||||
zh_punct = sum(1 for ch in text if is_zh_punct(ch))
|
||||
en_words = len(re.findall(r"[A-Za-zÀ-ÿĀ-ɏḀ-ỿ]+", text))
|
||||
digits = len(re.findall(r"[0-90-9]", text)) # 数字按位计
|
||||
total_words = hanzi + zh_punct + en_words + digits
|
||||
# 总字符数 = 所有非空白、非控制字符(仅供参考)
|
||||
total_chars = sum(1 for ch in text if (not ch.isspace()) and ord(ch) >= 0x20)
|
||||
return total_words, total_chars
|
||||
|
||||
|
||||
def judge(words, mn, mx):
|
||||
if mn is None and mx is None:
|
||||
return "none", 0
|
||||
if mn is not None and words < mn:
|
||||
return "under", mn - words
|
||||
if mx is not None and words > mx:
|
||||
return "over", words - mx
|
||||
return "pass", 0
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="飞书文档总字数统计与字数遵循校验")
|
||||
ap.add_argument("--doc", help="文档 document_id(自动取 raw_content)")
|
||||
ap.add_argument("--file", help="从文件读取文本")
|
||||
ap.add_argument("--as", dest="identity", default="user", help="身份:user(默认)|bot|auto")
|
||||
ap.add_argument("--min", type=int, help="字数下限(>=x)")
|
||||
ap.add_argument("--max", type=int, help="字数上限(<=y)")
|
||||
ap.add_argument("--approx", type=int, help="x 左右:自动展开为 [round(0.9x), round(1.1x)]")
|
||||
args = ap.parse_args()
|
||||
|
||||
if args.doc:
|
||||
text = fetch_raw_content(args.doc, args.identity)
|
||||
elif args.file:
|
||||
try:
|
||||
text = open(args.file, encoding="utf-8").read()
|
||||
except OSError as e:
|
||||
sys.exit(f"读取文件失败: {e}")
|
||||
elif not sys.stdin.isatty():
|
||||
text = sys.stdin.read()
|
||||
else:
|
||||
ap.error("需提供 --doc / --file 或从 stdin 传入文本")
|
||||
|
||||
mn, mx = args.min, args.max
|
||||
if args.approx is not None:
|
||||
mn, mx = round(args.approx * 0.9), round(args.approx * 1.1)
|
||||
|
||||
total_words, total_chars = count(text)
|
||||
verdict, gap = judge(total_words, mn, mx)
|
||||
|
||||
print(json.dumps({
|
||||
"total_words": total_words,
|
||||
"total_chars": total_chars,
|
||||
"target": {"min": mn, "max": mx},
|
||||
"verdict": verdict,
|
||||
"gap": gap,
|
||||
}, ensure_ascii=False))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user