模块 72: AI 文档创作模板 (ai-doc-creator)
版本: v5.0.2.1 状态: ✅ 完成 测试: 168 个测试(70 单元 + 47 集成 + 51 E2E)
背景与目标
问题陈述
用户需要一种简单的方式来:
- 利用 AI 自动生成结构化文档(报告、方案、说明书、README)
- 将 LibreOffice 纳入 AI 工作流(格式转换)
- 理解 cli-anything 与 LibreOffice 的适用边界
设计边界评估
| 维度 | cli-anything 注册 soffice | workspace 层技能(handler.js) |
|---|---|---|
| 工具接口 | 完整 soffice CLI(宏/模板/批量脚本) | 常用转换用例封装 |
| 适合场景 | 高级功能(宏执行、样式管理、自动化脚本) | 日常 AI 文档生成和格式转换 |
| 维护成本 | 低(注册即用) | 低(handler.js 直接调用 soffice) |
| AI 友好性 | 高(Agent 可直接调用 LibreOffice 任意子命令) | 高(结构化参数,错误处理完善) |
结论:LibreOffice 具有完整的 CLI 接口,同时适合两种方式:
libre-convertworkspace 技能:适合日常 AI 文档生成时的格式转换,提供结构化参数和优雅的错误处理cli-anything register soffice:适合高级场景(宏、模板样式、批量脚本)
这与 ai-media-creator 的 ComfyUI 决策不同:ComfyUI 以 REST API 为主,不适合 cli-anything;而 LibreOffice 的 CLI 接口成熟,两种方式可以并存。
实现架构
触发机制
cc init --template ai-doc-creator --yes
│
└── TEMPLATES["ai-doc-creator"].generateSkills = ["doc-generate", "libre-convert", "doc-edit"]
└── TEMPLATES["ai-doc-creator"].generateDir = "templates"
└── TEMPLATES["ai-doc-creator"].generateDirReadme = "DOC_TEMPLATES_README"生成的目录结构
<project-root>/
├── .chainlesschain/
│ ├── config.json # template: "ai-doc-creator", persona: { name: "AI文档助手", ... }
│ ├── rules.md # LibreOffice + pandoc + cli-anything 集成规则
│ └── skills/
│ ├── ai-doc-creator-persona/ # activation: auto, category: persona
│ │ └── SKILL.md
│ ├── doc-generate/ # AI 文档生成技能
│ │ ├── SKILL.md # category: document, execution-mode: direct
│ │ └── handler.js # 见下方详细说明
│ ├── libre-convert/ # LibreOffice 格式转换技能
│ │ ├── SKILL.md # category: document, execution-mode: direct
│ │ └── handler.js # 见下方详细说明
│ └── doc-edit/ # AI 修改现有文档(公式/图表/样式不丢失)
│ ├── SKILL.md # category: document, execution-mode: direct
│ └── handler.js # 见下方详细说明
└── templates/
└── README.md # DOC_TEMPLATES_README 内容技能 1: doc-generate
SKILL.md 关键字段
yaml
name: doc-generate
category: document
execution-mode: direct
parameters:
- name: topic # 必填,文档主题
- name: format # 可选,默认 "md",支持 md/html/docx/pdf
- name: outline # 可选,大纲字符串
- name: style # 可选,默认 "report",支持 report/proposal/manual/readme
- name: output # 可选,输出文件名(不含扩展名)handler.js 执行流程
docGenerateHandler(params)
│
├── 1. 参数验证:topic 必填,format 必须是 md/html/docx/pdf
│
├── 2. LLM 内容生成(generateContent)
│ └── spawnSync(process.execPath, [process.argv[1], "ask", prompt])
│ ├── 成功:返回 LLM 生成的 Markdown 内容
│ └── 失败:返回结构化模板(用户可手动填写)
│
├── 3. 写入 .md 文件(始终)
│
├── 4. 格式输出
│ ├── md: 直接返回,含 wordCount
│ ├── html: 内置 mdToHtml() 转换,返回 .html + .md companion
│ ├── docx: 优先 pandoc → 回退 soffice(html→docx) → 回退 md(含安装提示)
│ └── pdf: 优先 soffice(html→pdf) → 回退 pandoc+wkhtmltopdf → 回退 md(含安装提示)
│
└── 5. 返回结构化结果 { success, format, output, mdOutput?, wordCount?, message, hint? }工具检测
javascript
function commandExists(cmd) { execSync(`${cmd} --version`, { stdio: "ignore" }) }
function detectSoffice() {
// 1. soffice 或 libreoffice 命令
// 2. Windows 默认安装路径: C:\Program Files\LibreOffice\program\soffice.exe
}文档风格
| 风格 | 说明 | 典型章节 |
|---|---|---|
report | 分析报告 | 执行摘要、背景、详细分析、结论和建议 |
proposal | 项目方案 | 项目背景、目标、实施方案、资源需求、风险分析 |
manual | 说明书/手册 | 概述、安装/配置、功能说明、常见问题 |
readme | README 文档 | 项目简介、快速开始、功能特性、安装使用 |
技能 2: libre-convert
SKILL.md 关键字段
yaml
name: libre-convert
category: document
execution-mode: direct
parameters:
- name: input_file # 必填,源文件路径
- name: format # 可选,默认 "pdf",支持 pdf/docx/html/odt/pptx/xlsx/csv/txt/png
- name: outdir # 可选,输出目录(默认与源文件相同)handler.js 执行流程
libreConvertHandler(params)
│
├── 1. 参数验证:input_file 必填,format 必须在 SUPPORTED_FORMATS 中
│
├── 2. 文件存在性检查(existsSync)
│
├── 3. LibreOffice 检测(findSoffice)
│ ├── soffice / libreoffice 命令
│ └── Windows 默认路径检测(Program Files / Program Files (x86))
│ └── 未找到:返回 error + hint(含 cli-anything register soffice 提示)
│
├── 4. 创建输出目录(mkdirSync { recursive: true })
│
├── 5. spawnSync soffice --headless --convert-to <format> <input> --outdir <dir>
│ └── encoding: "utf-8", shell: win32
│
├── 6. 输出文件查找
│ ├── 精确路径:<baseName>.<format>
│ └── 模糊扫描:readdirSync().filter(startsWith + endsWith)
│
└── 7. 返回 { success, input, output, format, message }支持的转换格式
pdf, docx, html, odt, pptx, xlsx, csv, txt, png技能 3: doc-edit
SKILL.md 关键字段
yaml
name: doc-edit
category: document
execution-mode: direct
parameters:
- name: input_file # 必填,要修改的文档路径
- name: instruction # 必填,修改指令(如"将摘要优化为学术风格")
- name: action # 可选,默认 "edit",支持 edit/summarize/translate
- name: output # 可选,输出文件路径(默认 {baseName}_edited.{ext})handler.js 执行流程
docEditHandler(params)
│
├── 1. 参数验证:input_file 和 instruction 必填
│
├── 2. 文件存在性检查(existsSync)
│
├── 3. 按扩展名路由处理
│ ├── .md / .txt / .html → 直接读取文本,LLM 修改,写入 _edited 文件
│ ├── .docx → pandoc 转 md → LLM 修改 → pandoc 转回 docx(回退:soffice)
│ ├── .xlsx → Python + openpyxl(data_only=False,保留公式)→ LLM 修改 → 回写
│ └── .pptx → Python + python-pptx → 仅修改 text run,跳过图表/图形 shape
│
├── 4. LLM 调用(spawnSync cc ask)
│
├── 5. 写入输出文件({baseName}_edited.{ext},不覆盖原文件)
│
└── 6. 返回 { success, input, output, format, message }格式路由表
| 格式 | 处理方式 | 结构保留 |
|---|---|---|
.md / .txt / .html | 直接 LLM | N/A(纯文本) |
.docx | pandoc→LLM→pandoc,回退 soffice | 样式通过 pandoc 往返保留 |
.xlsx | Python + openpyxl data_only=False | 公式、图表、格式完整保留 |
.pptx | Python + python-pptx,仅修改 text run | 图形/图表 shape 跳过不修改 |
输出命名规则
input: report.md → output: report_edited.md
input: data.xlsx → output: data_edited.xlsx
input: slides.pptx → output: slides_edited.pptxPersona 配置
json
{
"name": "AI文档助手",
"role": "你是一个专业的AI文档创作助手,擅长生成各类结构化文档(报告、方案、说明书、README等),熟悉 LibreOffice 文档格式转换和 pandoc 文档处理。你能根据用户需求自动规划文档结构,生成专业、清晰的内容。",
"behaviors": [
"根据用户描述自动选择合适的文档风格(报告/方案/说明书/README)",
"主动询问文档目标读者和使用场景以优化内容",
"批量任务前确认 LibreOffice 已安装或告知安装方式",
"对长文档建议分章节生成以确保质量"
],
"toolsPriority": ["run_shell", "write_file", "read_file"],
"toolsDisabled": []
}测试覆盖
单元测试 (70 个) — __tests__/unit/init-ai-doc-creator.test.js
测试通过 VM 沙箱提取 init.js 中的常量,无需文件系统操作:
| 测试类别 | 数量 | 覆盖内容 |
|---|---|---|
| SKILL_TEMPLATES: doc-generate SKILL.md | 8 | YAML frontmatter、参数定义、格式列表、cli-anything 说明 |
| SKILL_TEMPLATES: doc-generate handler.js | 11 | JS 语法、参数验证、风格支持、转换流程、Windows 路径检测 |
| SKILL_TEMPLATES: libre-convert SKILL.md | 6 | YAML frontmatter、格式列表、安装说明、cli-anything 注册 |
| SKILL_TEMPLATES: libre-convert handler.js | 10 | JS 语法、参数验证、SUPPORTED_FORMATS、文件检查、soffice 路径 |
| DOC_TEMPLATES_README | 5 | 内容完整性、cli-anything 集成说明、设计边界 |
| SKILL_TEMPLATES: doc-edit SKILL.md | 7 | YAML frontmatter、参数定义、输出命名约定、格式路由 |
| SKILL_TEMPLATES: doc-edit handler.js | 13 | JS 语法、参数验证、格式路由、openpyxl/python-pptx 引用、_edited 命名 |
| TEMPLATES: ai-doc-creator entry | 7 | 必填字段、generateSkills(含 doc-edit)、generateDir、persona、rules.md |
集成测试 (47 个) — __tests__/integration/ai-doc-creator-handlers.test.js
运行 cc init --template ai-doc-creator --yes,通过 createRequire 加载生成的 handler.js:
| 测试类别 | 数量 | 覆盖内容 |
|---|---|---|
| 文件系统结构 | 11 | .chainlesschain 目录、配置文件、技能目录、templates/ 目录 |
| doc-generate 参数验证 | 3 | topic 必填、空 topic、不支持的格式 |
| doc-generate md 格式 | 4 | 文件生成、wordCount、文件名特殊字符、custom output |
| doc-generate html 格式 | 2 | html 文件生成、.md companion 文件 |
| doc-generate docx/pdf 回退 | 2 | 无 pandoc/soffice 时优雅回退到 md |
| libre-convert 参数验证 | 4 | input_file 必填、空参数、不支持格式、文件不存在 |
| libre-convert LibreOffice 未找到 | 2 | 错误提示、cli-anything 安装提示 |
| doc-edit 文件系统 | 4 | SKILL.md 存在、handler.js 存在、openpyxl 引用、_edited 命名 |
| doc-edit 参数验证 | 5 | input_file 必填、instruction 必填、文件不存在、不支持格式 |
| doc-edit md 修改 | 2 | Markdown 修改、LLM 调用路径 |
| doc-edit Python 依赖 | 2 | xlsx openpyxl 引用、pptx python-pptx 引用 |
| UTF-8 完整性 | 3 | handler.js 和 README.md 无 U+FFFD 替换字符 |
E2E 测试 (51 个) — __tests__/e2e/init-and-cowork-commands.test.js
通过 execSync 真实运行 CLI 命令:
| 测试类别 | 数量 |
|---|---|
| init --help | 1 |
| init --bare | 3 |
| init --template (code-project/data-science/devops) | 4 |
| init 防止重复初始化 | 1 |
| init Persona 模板 (medical-triage/agriculture-expert/general-assistant) | 6 |
| init ai-media-creator | 6 |
| init ai-doc-creator | 14 |
| persona 命令 | 8 |
| skill new 子命令 | 9 |
cli-anything 集成设计
为什么 LibreOffice 适合 cli-anything
| 特征 | LibreOffice / soffice | ComfyUI |
|---|---|---|
| CLI 接口 | 完整(soffice --headless --convert-to ...) | 无(REST API 为主) |
| 命令预测性 | 高(固定子命令格式) | 低(需自定义工作流 JSON) |
| cli-anything 适合度 | ✅ 高 | ❌ 低 |
| 推荐方式 | workspace 技能 + cli-anything 并存 | 仅 workspace 技能 |
推荐使用场景
bash
# 日常 AI 文档生成和格式转换 → 使用内置 workspace 技能
chainlesschain skill run doc-generate "技术报告"
chainlesschain skill run libre-convert "report.docx"
# 高级功能(宏/模板/批量)→ 通过 cli-anything 注册
chainlesschain cli-anything register soffice
chainlesschain skill run cli-anything-soffice "convert report.docx --macro RunMacro"关键文件
| 文件 | 说明 |
|---|---|
packages/cli/src/commands/init.js | 模板定义 + 生成逻辑(SKILL_TEMPLATES、DOC_TEMPLATES_README、TEMPLATES["ai-doc-creator"]) |
packages/cli/__tests__/unit/init-ai-doc-creator.test.js | 70 个单元测试 |
packages/cli/__tests__/integration/ai-doc-creator-handlers.test.js | 47 个集成测试 |
packages/cli/__tests__/e2e/init-and-cowork-commands.test.js | 51 个 E2E 测试(含 14 个 ai-doc-creator 专项) |
