
Eigent DOCX Skill 深度解析基于 SKILL.md 实现 Word 文档的创建、编辑与修订【免费下载链接】eigentEigent: The Open Source Cowork Desktop - Local and Free Alternative to Claude Cowork and Codex项目地址: https://gitcode.com/GitHub_Trending/ei/eigent本篇技术文章以 Eigent 仓库内置的docx示例技能resources/example-skills/docx/SKILL.md为主体完整讲解该技能如何指导 Agent 创建、编辑和分析 Word 文档.docx涵盖 docx-js 生成新文档的关键参数页幅、样式、列表、表格、图片、目录、解包 → 改 XML → 重打包的编辑流程、修订tracked changes与批注的 OOXML 写法并结合 Eigent 后端的技能同步机制说明该技能是如何被加载、分发和初始化的读完即可掌握在 Eigent 中为 Agent 装配文档处理能力的全链路实践。1. 技能定位SKILL.md 的 frontmatter 与触发规则Eigent 的技能Skill本质是一个目录目录内的SKILL.md是技能说明书供 Agent 在对话中判断什么时候该用这套能力。docx 技能的 frontmatter 定义如下--- name: docx description: Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of \Word doc\, \word document\, \.docx\, or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a \report\, \memo\, \letter\, \template\, or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation. license: Proprietary. LICENSE.txt has complete terms ---从 frontmatter 可以看到三个设计要点name技能唯一标识docxEigent 后端解析 frontmatter 时正是提取name与description两个字段见 skill_service.py 的 _parse_skill_frontmatter。description 即触发器用自然语言列明触发条件Word doc、.docx、report/memo/letter/template 等交付物同时也明确排除场景PDF、表格、Google Docs、与文档生成无关的编码任务——这是让 Agent 精准路由到该技能的关键。license声明专有许可完整条款在同目录的 LICENSE.txt 中。该技能目录的完整结构如下resources/example-skills/docx/ ├── LICENSE.txt ├── SKILL.md # 技能说明书本文主体 └── scripts/ ├── accept_changes.py # 接受全部修订输出干净文档 ├── comment.py # 跨多个 XML 文件写入批注样板 └── office/ ├── pack.py # 重新打包 DOCX含自动修复与校验 ├── unpack.py # 解包 XML 美化 run 合并 ├── validate.py # XSD Schema 校验 ├── soffice.py # LibreOffice 封装沙箱环境自适应 ├── helpers/ # merge_runs / simplify_redlines ├── schemas/ # ISO-IEC29500-4 等 XSD Schema └── validators/ # docx/pptx/redlining 校验器2. 技能的分发与初始化从 example-skills 到 ~/.eigent/skillsSKILL.md 中的命令都以scripts/...相对路径书写这些脚本在技能被同步到用户目录后随之可用。Eigent 后端负责这一同步过程skill_service.py 定义了SKILLS_ROOT ~/.eigent/skills并维护一个.eigent-example-skill标记文件EXAMPLE_SKILL_MARKER用于识别受管理的示例技能。sync_example_skills()skill_service.py#L159-L209会遍历示例技能根目录优先环境变量EIGENT_EXAMPLE_SKILLS_DIR其次打包应用的Resources/example-skills或开发仓库的 resources/example-skills对每个含SKILL.md的目录不存在则整目录复制到~/.eigent/skills/name/并写入标记文件已存在且仍为受管理状态且内容不一致则删除后重新复制。若用户已本地修改过同名技能则会跳过并记录日志避免覆盖用户改动。初始化配置脚本 backend/scripts/init_skills_config.py 会扫描~/.eigent/skills/用正则^---\s*\nname:\s*(.?)\s*\n从 frontmatter 提取技能名并生成形如{version: 1, skills: {name: {enabled: true, scope: global, ...}}}的skills-config.json全局或按用户/项目维度。仓库根部的 resources/example-skills/default-config.json 即该配置模板。适用前提技能脚本在技能目录内相对执行因此运行 SKILL.md 中的命令时工作目录应为技能目录如~/.eigent/skills/docx/。3. 核心模型.docx 是 ZIP 包里的 XMLSKILL.md 的第一原则是A .docx file is a ZIP archive containing XML files。基于此技能给出三任务决策表任务方案读取/分析内容pandoc或直接解包看原始 XML创建新文档使用docx-js见第 4 节编辑现有文档解包 → 编辑 XML → 重新打包见第 5 节3.1 旧版 .doc 的转换Legacy.doc文件必须先转换才能编辑python scripts/office/soffice.py --headless --convert-to docx document.docsoffice.py 是对 LibreOffice 的封装按 SKILL.md 依赖说明它针对沙箱环境做了自动配置。3.2 内容读取# 带修订记录tracked changes的文本提取 pandoc --track-changesall document.docx -o output.md # 直接获取原始 XML python scripts/office/unpack.py document.docx unpacked/unpack.py 的实际行为比解包更丰富解压 ZIP 后对所有*.xml/*.rels文件做美化输出对.docx额外执行简化同一作者的相邻修订simplify_redlines和合并相邻格式相同的 runmerge_runs便于后续用字符串替换直接编辑。它支持--merge-runs false跳过 run 合并且仅接受.docx/.pptx/.xlsx三种后缀。3.3 转图片可视化验证python scripts/office/soffice.py --headless --convert-to pdf document.docx pdftoppm -jpeg -r 150 document.pdf page先转 PDF再用 Poppler 的pdftoppm以 150 DPI 渲染每页 JPEG用于肉眼验证排版。3.4 接受全部修订python scripts/accept_changes.py input.docx output.docx依赖 LibreOffice产出一份所有修订均被接受的干净文档。4. 创建新文档docx-js 全参数实战创建流程为JavaScript 生成 → 校验依赖安装npm install -g docx。4.1 基本骨架const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun, Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink, TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType, VerticalAlign, PageNumber, PageBreak } require(docx); const doc new Document({ sections: [{ children: [/* content */] }] }); Packer.toBuffer(doc).then(buffer fs.writeFileSync(doc.docx, buffer));生成后必须校验失败则走解包 → 修 XML → 重打包路径python scripts/office/validate.py doc.docxvalidate.py 支持直接传入打包好的.docx内部先解压到临时目录也支持传入已解包的目录--auto-repair可自动修复两类问题paraId/durableId超出 OOXML 上限如 0x7FFFFFFF以及带空白字符的w:t缺失xml:spacepreserveSchema 依据来自 schemas/ 下的 ISO-IEC29500-4_2016、ECMA、Microsoft 扩展等 XSD 文件。4.2 页幅与边距DXA 单位体系docx-js 默认 A4 而非 US Letter必须显式设置页幅sections: [{ properties: { page: { size: { width: 12240, // 8.5 inches in DXA height: 15840 // 11 inches in DXA }, margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1 inch margins } }, children: [/* content */] }]常用纸张1440 DXA 1 英寸纸张宽高内容宽1 英寸边距US Letter12,24015,8409,360A4默认值11,90616,8389,026横向Landscape方向docx-js 内部会交换宽高因此始终传纵向尺寸、短边作width再声明方向即可由库在 XML 层完成交换size: { width: 12240, // Pass SHORT edge as width height: 15840, // Pass LONG edge as height orientation: PageOrientation.LANDSCAPE // docx-js swaps them in the XML }, // 内容宽 15840 - 左边距 - 右边距用的是长边4.3 样式覆盖内建标题样式建议默认字体用 Arial通用性最好、标题保持黑色以保证可读性。关键点是用精确的样式 IDHeading1而非Heading 1覆盖内建样式且必须带outlineLevel才能被目录收录const doc new Document({ styles: { default: { document: { run: { font: Arial, size: 24 } } }, // 12pt default paragraphStyles: [ // IMPORTANT: Use exact IDs to override built-in styles { id: Heading1, name: Heading 1, basedOn: Normal, next: Normal, quickFormat: true, run: { size: 32, bold: true, font: Arial }, paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // outlineLevel required for TOC { id: Heading2, name: Heading 2, basedOn: Normal, next: Normal, quickFormat: true, run: { size: 28, bold: true, font: Arial }, paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } }, ] }, sections: [{ children: [ new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun(Title)] }), ] }] });4.4 列表严禁手写 Unicode 项目符号// ❌ WRONG - never manually insert bullet characters new Paragraph({ children: [new TextRun(• Item)] }) // BAD new Paragraph({ children: [new TextRun(\u2022 Item)] }) // BAD // ✅ CORRECT - use numbering config with LevelFormat.BULLET const doc new Document({ numbering: { config: [ { reference: bullets, levels: [{ level: 0, format: LevelFormat.BULLET, text: •, alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }, { reference: numbers, levels: [{ level: 0, format: LevelFormat.DECIMAL, text: %1., alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }, ] }, sections: [{ children: [ new Paragraph({ numbering: { reference: bullets, level: 0 }, children: [new TextRun(Bullet item)] }), new Paragraph({ numbering: { reference: numbers, level: 0 }, children: [new TextRun(Numbered item)] }), ] }] });reference决定编号独立性同一 reference 编号延续1,2,3 之后接 4,5,6不同 reference 编号重启1,2,3 之后又 1,2,3。4.5 表格双宽度规则表格必须双宽度——表格级columnWidths与每个单元格的width都要设置且一致否则在部分平台上渲染错乱。同时ShadingType必须用CLEAR而非SOLID后者会产生黑底// CRITICAL: Always set table width for consistent rendering // CRITICAL: Use ShadingType.CLEAR (not SOLID) to prevent black backgrounds const border { style: BorderStyle.SINGLE, size: 1, color: CCCCCC }; const borders { top: border, bottom: border, left: border, right: border }; new Table({ width: { size: 9360, type: WidthType.DXA }, // Always use DXA (percentages break in Google Docs) columnWidths: [4680, 4680], // Must sum to table width (DXA: 1440 1 inch) rows: [ new TableRow({ children: [ new TableCell({ borders, width: { size: 4680, type: WidthType.DXA }, // Also set on each cell shading: { fill: D5E8F0, type: ShadingType.CLEAR }, // CLEAR not SOLID margins: { top: 80, bottom: 80, left: 120, right: 120 }, // Cell padding (internal, not added to width) children: [new Paragraph({ children: [new TextRun(Cell)] })] }) ] }) ] })宽度计算规则US Letter 1 英寸边距12240 - 2880 9360// Table width sum of columnWidths content width width: { size: 9360, type: WidthType.DXA }, columnWidths: [7000, 2360] // Must sum to table width宽度铁律永远用WidthType.DXA不用WidthType.PERCENTAGE后者在 Google Docs 中会坏表格宽必须等于columnWidths之和单元格的width必须与对应columnWidth一致单元格margins是内部填充——只缩小内容区不增加单元格宽全宽表格使用页宽减左右边距的内容宽。4.6 图片、分页符与目录// CRITICAL: type parameter is REQUIRED new Paragraph({ children: [new ImageRun({ type: png, // Required: png, jpg, jpeg, gif, bmp, svg data: fs.readFileSync(image.png), transformation: { width: 200, height: 150 }, altText: { title: Title, description: Desc, name: Name } // All three required })] }) // CRITICAL: PageBreak must be inside a Paragraph new Paragraph({ children: [new PageBreak()] }) // Or use pageBreakBefore new Paragraph({ pageBreakBefore: true, children: [new TextRun(New page)] }) // CRITICAL: Headings must use HeadingLevel ONLY - no custom styles new TableOfContents(Table of Contents, { hyperlink: true, headingStyleRange: 1-3 })4.7 页眉/页脚sections: [{ properties: { page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } // 1440 1 inch }, headers: { default: new Header({ children: [new Paragraph({ children: [new TextRun(Header)] })] }) }, footers: { default: new Footer({ children: [new Paragraph({ children: [new TextRun(Page ), new TextRun({ children: [PageNumber.CURRENT] })] })] }) }, children: [/* content */] }]4.8 docx-js 关键规则汇总显式设置页幅——docx-js 默认 A4US 文档用 12240 × 15840 DXA横向传纵向尺寸——短边作width、长边作height设orientation: PageOrientation.LANDSCAPE禁用\n——换行用独立 Paragraph禁用 Unicode 项目符号——用LevelFormat.BULLET numbering 配置PageBreak 必须在 Paragraph 内——孤立使用会生成非法 XMLImageRun 必须带type——显式 png/jpg 等表格宽一律 DXA——不用WidthType.PERCENTAGEGoogle Docs 不兼容表格双宽度——columnWidths数组与单元格width都要设且相等表宽 columnWidths 之和——DXA 下必须精确相加单元格必须加 margins——推荐margins: { top: 80, bottom: 80, left: 120, right: 120 }底纹用ShadingType.CLEAR——永不用 SOLID目录只认 HeadingLevel——标题段落不能套自定义样式覆盖内建样式用精确 ID——Heading1、Heading2必须带outlineLevel——目录收录的前提H1 为 0H2 为 1依此类推。5. 编辑现有文档解包 → 改 XML → 重打包三步顺序执行不可跳过。Step 1解包python scripts/office/unpack.py document.docx unpacked/除解压外unpack 会美化 XML、合并相邻 run并把 smart quotes 转成 XML 实体#x201C;等使其在编辑中存活--merge-runs false可跳过 run 合并。从 unpack.py 源码 可以看到smart quote 替换表恰含四种实体#x201C;/#x201D;/#x2018;/#x2019;与下文的实体表一一对应。Step 2编辑 XML在unpacked/word/下编辑模式参照第 6 节 XML Reference。SKILL.md 给出三条纪律修订与批注的作者默认用 Claude除非用户明确要求其他名字直接用字符串替换工具改字符串不要写 Python 脚本——脚本引入不必要的复杂度而直接替换能精确展示被替换的内容新内容必须用 smart quotes——带撇号/引号的文本要写成 XML 实体保证排版专业!-- Use these entities for professional typography -- w:tHere#x2019;s a quote: #x201C;Hello#x201D;/w:t实体字符#x2018;左单引号#x2019;右单引号 / 撇号#x201C;左双引号#x201D;右双引号添加批注用 comment.py 处理跨多个 XML 文件的样板代码传入文本须是已转义的 XML批注模板存于 templates/python scripts/comment.py unpacked/ 0 Comment text with amp; and #x2019; python scripts/comment.py unpacked/ 1 Reply text --parent 0 # reply to comment 0 python scripts/comment.py unpacked/ 0 Text --author Custom Author # custom author name之后还需在document.xml中插入标记见第 6 节 Comments 部分。Step 3重打包python scripts/office/pack.py unpacked/ output.docx --original document.docx打包时执行自动修复 校验 XML 压缩 生成 DOCX--validate false可跳过校验。自动修复能处理durableId 0x7FFFFFFF重新生成合法 ID、带空白w:t缺失xml:spacepreserve不能处理非法 XML、错误嵌套、缺失 relationships、Schema 违规。常见坑整体替换w:r元素添加修订时要把整个w:r.../w:r块替换为并列的w:del...w:ins...不要往 run 内部注入修订标签保留w:rPr格式把原 run 的w:rPr块复制进新的修订 run以维持粗体、字号等格式。6. XML Reference修订、批注与图片的 OOXML 写法6.1 Schema 合规三要点w:pPr内元素顺序w:pStyle、w:numPr、w:spacing、w:ind、w:jcw:rPr必须最后空白处理前后带空格的w:t要加xml:spacepreserveRSID 必须是 8 位十六进制如00AB1234。6.2 Tracked Changes修订插入w:ins w:id1 w:authorClaude w:date2025-01-01T00:00:00Z w:rw:tinserted text/w:t/w:r /w:ins删除w:del w:id2 w:authorClaude w:date2025-01-01T00:00:00Z w:rw:delTextdeleted text/w:delText/w:r /w:del在w:del内部w:t换成w:delTextw:instrText换成w:delInstrText。最小化编辑——只标记真正变化的部分把 30 days 改成 60 days!-- Change 30 days to 60 days -- w:rw:tThe term is /w:t/w:r w:del w:id1 w:authorClaude w:date... w:rw:delText30/w:delText/w:r /w:del w:ins w:id2 w:authorClaude w:date... w:rw:t60/w:t/w:r /w:ins w:rw:t days./w:t/w:r整段/整列表项删除——删光段落内容时还要把段落标记本身标记为删除让它与下一段合并。做法是在w:pPrw:rPr里加w:del/w:p w:pPr w:numPr.../w:numPr !-- list numbering if present -- w:rPr w:del w:id1 w:authorClaude w:date2025-01-01T00:00:00Z/ /w:rPr /w:pPr w:del w:id2 w:authorClaude w:date2025-01-01T00:00:00Z w:rw:delTextEntire paragraph content being deleted.../w:delText/w:r /w:del /w:p漏掉w:pPrw:rPr里的w:del/接受修订后会留下空段落/空列表项。拒绝他人插入——把删除嵌套进对方的插入中w:ins w:authorJane w:id5 w:del w:authorClaude w:id10 w:rw:delTexttheir inserted text/w:delText/w:r /w:del /w:ins恢复他人删除——在其删除之后新增插入不要改动对方的删除w:del w:authorJane w:id5 w:rw:delTextdeleted text/w:delText/w:r /w:del w:ins w:authorClaude w:id10 w:rw:tdeleted text/w:t/w:r /w:ins6.3 批注Comments运行comment.py后在document.xml中加标记回复用--parent标记嵌套在父批注标记内。关键w:commentRangeStart和w:commentRangeEnd是w:r的兄弟节点绝不能放进w:r内部!-- Comment markers are direct children of w:p, never inside w:r -- w:commentRangeStart w:id0/ w:del w:id1 w:authorClaude w:date2025-01-01T00:00:00Z w:rw:delTextdeleted/w:delText/w:r /w:del w:rw:t more text/w:t/w:r w:commentRangeEnd w:id0/ w:rw:rPrw:rStyle w:valCommentReference//w:rPrw:commentReference w:id0//w:r !-- Comment 0 with reply 1 nested inside -- w:commentRangeStart w:id0/ w:commentRangeStart w:id1/ w:rw:ttext/w:t/w:r w:commentRangeEnd w:id1/ w:commentRangeEnd w:id0/ w:rw:rPrw:rStyle w:valCommentReference//w:rPrw:commentReference w:id0//w:r w:rw:rPrw:rStyle w:valCommentReference//w:rPrw:commentReference w:id1//w:r6.4 手工插图直接改 XML 路径图片文件放入word/media/在word/_rels/document.xml.rels加关系Relationship IdrId5 Type.../image Targetmedia/image1.png/在[Content_Types].xml加内容类型Default Extensionpng ContentTypeimage/png/在document.xml中引用w:drawing wp:inline wp:extent cx914400 cy914400/ !-- EMUs: 914400 1 inch -- a:graphic a:graphicData uri.../picture pic:pic pic:blipFilla:blip r:embedrId5//pic:blipFill /pic:pic /a:graphicData /a:graphic /wp:inline /w:drawing7. 依赖与运行环境依赖用途pandoc文本提取docxnpm install -g docx创建新文档LibreOfficePDF 转换经 scripts/office/soffice.py 为沙箱环境自动配置Popplerpdftoppm图片渲染8. 小结与延伸这份 SKILL.md 的价值在于把Word 文档自动化的全部易错点沉淀成了可执行规则docx 侧的 DXA 单位体系、双宽度表格、numbering 列表、样式 ID 精确覆盖XML 侧的 smart quote 实体、w:del/w:ins兄弟替换、批注标记位置以及自动修复能修什么、不能修什么的明确边界。配合 unpack.py、pack.py、validate.py 三个脚本构成的解包-编辑-校验闭环Agent 可以在无人工干预下交付跨 Word/Google Docs 表现一致的 .docx。同目录下还有同系列的 pdf、pptx、xlsx 技能均复用同一套scripts/office工具链与 XSD Schema该工具链甚至支持 pptx/xlsx 的校验器扩展以及 skill-creator用于创建新技能与 skill-security-auditor用于技能安全审计——阅读 docx 技能掌握的模式可以直接迁移到这些兄弟技能上。【免费下载链接】eigentEigent: The Open Source Cowork Desktop - Local and Free Alternative to Claude Cowork and Codex项目地址: https://gitcode.com/GitHub_Trending/ei/eigent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考