OfficeCLI 插件开发完整指南:从装好第一个格式扩展到打开 .hwpx
【免费下载链接】OfficeCLIOfficeCLI is the first and best Office suite purpose-built for AI agents to read, edit, and automate Word, Excel, and PowerPoint files. Free, open-source, single binary, no Office installation required.项目地址: https://gitcode.com/GitHub_Trending/of/OfficeCLI
让 AI 代理打开一个 .doc 合同,它只会报错——OfficeCLI 核心只认 docx、xlsx、pptx 三种格式。OfficeCLI 是专为 AI 代理打造的办公套件,能通过 OfficeCLI 插件把 .doc、.hwpx、.pdf 这类格式纳入同一套命令行工作流,核心代码一行不用改。本文讲清机制、安装方式和三类插件的实现路径。
🧭 一张表看懂三类 OfficeCLI 插件:转换、导出、接管
插件是独立的外部进程(sidecar),主程序按需拉起。协议 v1 定义了三类,职责边界清晰:
| 角色 | 典型场景 | 生命周期 | 文件归属 | 通信方式 |
|---|---|---|---|---|
转换型dump-reader | 把 .doc 迁移成 .docx | 短命,跑完即退 | 插件只读源文件;主程序写出结果 | 无 IPC,向 stdout 流式吐 JSONL 命令后退出 |
导出型exporter | 导出 .pdf | 短命,跑完即退 | 插件只读源文件、写目标文件 | 无 IPC,普通命令行调用 |
接管型format-handler | .hwpx 完整读写编辑 | 长驻,覆盖整个会话 | 插件全程持有文件读写 | stdin/stdout 请求-响应 |
三个要点先记住:
- 转换型产出的是原生格式,
target只能是 docx/xlsx/pptx,后续编辑都发生在生成的兄弟文件上,源文件不动。 - 导出型是单向渲染,不参与任何编辑。
- 接管型的"词汇表"由插件自定义:manifest 里声明可加类型、可设属性、路径语法,会话开始时再快照一次,主机以快照为准。
另有两个预留类型engine、transformer,v1 禁止声明,留给未来的子系统后端与原生格式互转。
📦 插件装在哪:四级发现机制与一行安装命令
主程序按(kind, ext)找插件时,按固定顺序搜索,先命中先生效:
- 环境变量
$OFFICECLI_PLUGIN_<KIND>_<EXT>(如OFFICECLI_PLUGIN_DUMP_READER_DOC),值为可执行文件绝对路径; - 用户插件目录
~/.officecli/plugins/<kind>/<ext>/plugin(.exe); - 主程序同级的捆绑目录
<主程序目录>/plugins/<kind>/<ext>/plugin(.exe); - PATH 查找,名字为
officecli-<kind>-<ext>或officecli-<ext>。
约定:<kind>用 kebab-case(dump-reader、format-handler),<ext>不带点;Windows 自动补.exe;符号链接会被跟随。发现结果按进程缓存,下次调用自动拾取新插件。
安装协议本身不强制渠道:手动解压、发布包捆绑、包管理器都行。推荐用内置安装器officecli plugins install <name>,它从插件注册表拉取清单并校验 SHA-256,支持配置私有镜像(企业内网场景)。装完用officecli plugins list看发现结果,officecli plugins info看完整 manifest,officecli plugins lint做持久化校验。完整规则见 plugins/plugin-protocol.md 第 3、8 节。
🛠 写一个插件:从浅到深的三个项目
先说语言:协议是 stdin/stdout 上的 JSONL,任何能读写标准流的语言都行——.NET、Go、Python、Rust 均可,.NET 侧还有OfficeCli.Contracts包提供类型安全的封装。所有插件的第一职责相同:响应--info,向 stdout 打印一个 JSON manifest 并以 0 退出。
入门级 | Exporter:只读、一次性、最省事
以导出 PDF 为例(渲染库体积大、有许可证约束,所以拆出去)。用户执行officecli view report.docx pdf --out out.pdf,主程序把 view 模式映射成目标扩展名,解析出插件后按export <source> --out <target> [--options <json>]拉起它。
你的插件只需做三件事:用自带库读源文件(严禁写回源文件,主程序基于这条约定跳过快照,需要可写副本就自己建临时文件);写出目标;成功则退出 0。诊断信息走 stderr。渲染耗时较长时,定期向 stderr 打一行{"heartbeat":true},避免触发看门狗。
进阶级 | Dump-Reader:用 JSONL 命令流把 .doc 迁移成 .docx
打开 .doc 时,主程序先看旁边有没有比源文件更新的同名 .docx,有就直接打开;没有才以dump <source>启动插件。插件解析源文件,向 stdout 逐行输出 add/set/batch 命令,每行单独 flush,然后退出 0。主程序建一个空白骨架、逐行重放,再把成品移到源文件旁边。
两条硬约束:输出必须是 JSONL,顶层 JSON 数组会被拒收(corrupt_batch);必须流式输出——每行 flush 既是主机看门狗的活动信号,也限制了主程序处理大文件时的内存占用。缓存靠 mtime:源文件一改就自动失效,删掉兄弟文件可强制重转。
manifest 长这样(来自协议文档的officecli-doc示例):
{ "name": "officecli-doc", "version": "1.0.0", "protocol": 1, "kinds": ["dump-reader"], "extensions": [".doc"], "target": "docx", "runtime": "dotnet", "idle_timeout_seconds": { "default": 60, "verbs": { "dump": 30 } }, "supports": ["paragraphs", "runs", "tables", "images", "lists"] }高级 | Format-Handler:长驻进程全程接管 .hwpx
这是最重的一类:主程序以open <file>拉起插件后,双方在整个会话期间保持通信。先做 open 握手,之后严格一问一答地处理 add/set/get/query/save/close。最关键的通信片段如下:
{"protocol":1,"msg_type":"open","path":"report.hwpx","editable":true} {"protocol":1,"msg_type":"ok","result":{"capabilities":{"commands":["get","set","save"],"features":["extract-binary"]},"vocabulary":{"addable_types":["paragraph","table"],"settable_props":{},"path_segments":["/page[N]"]}}} {"protocol":1,"msg_type":"command","command":"add","args":{"parent_path":"/page[1]","type":"paragraph"},"props":{"text":"Hello"}}实现要点:stdout 只走协议帧,调试输出全去 stderr 或--log-file,污染 stdout 会被判protocol_mismatch、会话进入 broken;save必须真正刷盘后才能回 ok,这是主程序崩溃恢复的前提,plugins lint会在重开文件后验证持久化;broken 会话不会自动重启,由调用方重开。
📋 协议要点速查:manifest、JSONL、超时与退出码
| 项 | 要点 |
|---|---|
| manifest 必填字段 | name(kebab-case)、version(SemVer)、protocol(=1,不匹配拒收退出 5)、kinds、extensions(带点)、idle_timeout_seconds、runtime;dump-reader 另需target,format-handler 另需vocabulary;可选description、license、tier等 |
| JSONL 通信 | 每行一个 JSON 对象、\n结尾、UTF-8 无 BOM、键名 snake_case;format-handler 用 stdin 收请求、stdout 回响应、stderr 放诊断与心跳 |
| 空闲超时 | 看门狗盯"无活动"(stdout 字节、RPC 响应、stderr 心跳都算活动),不限总时长;manifest 里不允许写 0,用户侧可用OFFICECLI_PLUGIN_IDLE_TIMEOUT_SECONDS覆盖,0 表示彻底关闭看门狗 |
| 崩溃与恢复 | 非零退出会给出明确错误,内存中的半成品状态被丢弃,不落损坏文件;空闲超时杀整个进程树并报plugin_idle_timeout;broken 会话快速失败,不自动重启 |
| 退出代码 | 0 成功;2 输入损坏;3 该构建不支持此功能;4 许可证过期;5 协议不匹配;6 空闲超时(仅主机设置);64–78 保留(sysexits.h);其余按internal_error上报 |
错误码同理可查:corrupt_batch、protocol_mismatch、plugin_idle_timeout、license_expired等都在协议文档 6.6 节列了语义,主机把未知码一律归为internal_error。
❓ 常见问题:语言、崩溃、授权与调试
Q:插件可以随便选语言吗?可以。协议只约束标准流和 JSON 形态。C#、Go、Python、Rust 都行;.NET 插件可选用OfficeCli.Contracts包获得类型安全的消息体。
Q:插件崩了或卡死了会怎样?崩溃时主程序直接报清晰错误,丢弃内存中的部分状态,不会写出损坏文件。卡死时看门狗在 manifest 声明的空闲窗口内收不到任何活动就杀掉进程树并报告超时;长任务靠 stderr 心跳保活。
Q:闭源或商业插件被允许吗?允许。插件是独立可执行文件,许可证与主仓库(Apache-2.0)解耦;许可证校验失败按约定退出 4(license_expired)。
Q:调试插件从哪下手?先officecli plugins list确认插件被发现、路径对;再加--log-file把诊断落盘、--quiet压低噪音;怀疑是看门狗误杀时,用OFFICECLI_PLUGIN_IDLE_TIMEOUT_SECONDS临时放宽(该变量只在宿主环境生效,不会传入插件进程)。
Q:为什么不做总时长上限?大型 .doc 的 dump 合理耗时就是几分钟,总时长上限会误杀慢但正确的转换;空闲超时只抓真正的挂起,没有误报。
🎯 收尾:谁该给 OfficeCLI 做格式扩展
对个人用户:偶尔碰到 .doc 遗留文件或区域性的 .hwpx,装一个成熟插件即可,本文不必全读。对企业:私有注册表加 IT 分发,可以把内部文档流水线做成自研插件,和核心版本彻底解耦。值得留意的延伸方向:协议预留的engine与transformer类型,意味着日后 docx→pptx 这类原生互转、以及 PDF 渲染后端,都能用同一套发现与通信机制接进来。主程序侧的实现集中在 src/officecli/Core/Plugins/,想读源码可以直接从这里入手。
【免费下载链接】OfficeCLIOfficeCLI is the first and best Office suite purpose-built for AI agents to read, edit, and automate Word, Excel, and PowerPoint files. Free, open-source, single binary, no Office installation required.项目地址: https://gitcode.com/GitHub_Trending/of/OfficeCLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考