@4399ywkf/editor-mcp 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -7
- package/bin/hub.mjs +10 -5
- package/dist/chunk-DBNN3NAP.js +748 -0
- package/dist/chunk-DBNN3NAP.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/tools.d.ts +5 -1
- package/dist/tools.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-V3M4D5XE.js +0 -318
- package/dist/chunk-V3M4D5XE.js.map +0 -1
package/README.md
CHANGED
|
@@ -51,8 +51,19 @@ const runtime = new SheetRuntime()
|
|
|
51
51
|
// <DocumentView format="sheet" onReady={(univerAPI) => runtime.setUniverAPI(univerAPI)} />
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
演示文稿换成 `SLIDE_TOOLS` + `SlideRuntime`(`useSlideDocument` 把字节、runtime、撤销串在一起):
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import { PptxView, useSlideDocument } from "@4399ywkf/editor/pptx"
|
|
58
|
+
import { attachBridge, composeRuntimes } from "@4399ywkf/editor-mcp/bridge"
|
|
59
|
+
|
|
60
|
+
const { bytes, runtime, undo, canUndo } = useSlideDocument(initialBytes, { onChange: (next) => save(next) })
|
|
61
|
+
useEffect(() => attachBridge({ runtime: composeRuntimes({ slide: runtime }) }), [runtime])
|
|
62
|
+
return <PptxView content={bytes} />
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
三个都挂就喂 `ALL_TOOLS`(= `DOC_TOOLS` + `SHEET_TOOLS` + `SLIDE_TOOLS`),
|
|
66
|
+
执行侧用 `composeRuntimes({ doc, sheet, slide })` 按前缀分发(见下)。
|
|
56
67
|
|
|
57
68
|
## 用法二:走 MCP
|
|
58
69
|
|
|
@@ -110,7 +121,8 @@ npx ywkf-editor-hub --port 4399 --token $(openssl rand -hex 16)
|
|
|
110
121
|
默认只听 `127.0.0.1`。`--token` 可选但建议开:这个口的权限是「以用户身份重写他正在
|
|
111
122
|
编辑的文档」,不开的话本机任何进程都能调。`--static <dir>` 可以顺便托管一个页面,
|
|
112
123
|
本地调试方便。`--out-dir <dir>` 指定文档的读写目录(默认 hub 的工作目录),
|
|
113
|
-
`doc_export_docx` / `doc_import_docx` / `sheet_export_xlsx`
|
|
124
|
+
`doc_export_docx` / `doc_import_docx` / `sheet_export_xlsx` / `slide_import_pptx` /
|
|
125
|
+
`slide_export_pptx` / `slide_add_element`(插图片)只能碰这个目录里的文件。
|
|
114
126
|
|
|
115
127
|
**3. 注册 MCP**
|
|
116
128
|
|
|
@@ -129,7 +141,7 @@ npx ywkf-editor-hub --port 4399 --token $(openssl rand -hex 16)
|
|
|
129
141
|
> codex `exec` 下需要 `--dangerously-bypass-approvals-and-sandbox`:`approval: never`
|
|
130
142
|
> 会把 MCP 调用直接判成 "user cancelled"。交互式 `codex` 里可以逐次批准。
|
|
131
143
|
|
|
132
|
-
## 工具(doc 10 个 + sheet
|
|
144
|
+
## 工具(doc 10 个 + sheet 12 个)
|
|
133
145
|
|
|
134
146
|
### 文档(tiptap)
|
|
135
147
|
|
|
@@ -157,11 +169,17 @@ npx ywkf-editor-hub --port 4399 --token $(openssl rand -hex 16)
|
|
|
157
169
|
|
|
158
170
|
| 工具 | 用途 |
|
|
159
171
|
|---|---|
|
|
160
|
-
| `sheet_read` | 工作簿概览 + 一张表的 CSV 视图与公式清单。写之前必须先调它。日期是序列号,1904 日期系统的工作簿会多返回 `dateSystem` |
|
|
172
|
+
| `sheet_read` | 工作簿概览 + 一张表的 CSV 视图与公式清单。写之前必须先调它。日期是序列号,1904 日期系统的工作簿会多返回 `dateSystem`;`include` 可附带样式 / 合并 / 冻结 / 筛选 / 条件格式 |
|
|
161
173
|
| `sheet_find` | 全簿检索(值和公式都搜),返回可直接回填的 `sheet` + A1 `ref` |
|
|
162
174
|
| `sheet_set_values` | 从某格起写一块二维值,`"=…"` 是公式、`null` 清空 |
|
|
163
175
|
| `sheet_edit_rows_cols` | 插入 / 删除整行整列(0-based) |
|
|
164
176
|
| `sheet_manage_sheets` | 工作表 add / rename / delete / activate |
|
|
177
|
+
| `sheet_format_range` | 字体 / 颜色 / 填充 / 对齐 / 换行 / 数字格式 / 边框;`clear` 先清后设 |
|
|
178
|
+
| `sheet_merge` | 合并 / 按行合并 / 拆分;会丢值时默认报错,`discard_values` 确认 |
|
|
179
|
+
| `sheet_sort` | 多列排序,`has_header` 时首行不动;区域含合并报错 |
|
|
180
|
+
| `sheet_filter` | 按值筛选 set / clear / remove(按显示文本匹配) |
|
|
181
|
+
| `sheet_freeze` | 冻结顶部几行、左侧几列,`0, 0` 取消 |
|
|
182
|
+
| `sheet_conditional_format` | 条件格式 add / update / delete:数值比较、文本、重复 / 唯一、前后 N、色阶、数据条 |
|
|
165
183
|
| `sheet_export_xlsx` | 导出成 .xlsx 落盘,返回路径 + 统计 + 警告 |
|
|
166
184
|
|
|
167
185
|
定位一律用 A1 引用,不用 node id —— 表格的坐标系本来就是稳定的,不需要 doc 那套
|
|
@@ -174,9 +192,40 @@ npx ywkf-editor-hub --port 4399 --token $(openssl rand -hex 16)
|
|
|
174
192
|
|
|
175
193
|
`sheet_manage_sheets` 的 `delete` 不允许省略 `sheet` —— 「默认删活动表」是脚枪。
|
|
176
194
|
|
|
195
|
+
**撤销步数**:每次写调用落成 Univer 的 1~2 条命令,Ctrl+Z 按命令一步步撤 ——
|
|
196
|
+
`sheet_format_range` 同时设样式和边框是两步,`sheet_filter` 新建筛选再设条件是两步、清全部条件每列一步,
|
|
197
|
+
其余都是一步;结果里的 `undo_steps` 就是这次占了几步。Univer 的门面没有把多条命令并成一步的接口
|
|
198
|
+
(`beginUndoRedoGroup` 只在它的 DI 容器里),所以这里如实报步数,不做合并。
|
|
199
|
+
|
|
200
|
+
**文本与边框**:`sheet_format_range` 遇到区域里(设边框时还包括区域外紧邻的一圈)看起来像数字或
|
|
201
|
+
`TRUE` / `FALSE` 的文本格且不是文本格式时会报错并点名,避免 Univer 改样式时把它们转成数字,
|
|
202
|
+
丢失前导 0 或第 16 位起的数字;先只对点名格设 `numberFormat: "@"` 再重试。`numberFormat: "@"`
|
|
203
|
+
会把区域内已有的数字、日期、布尔转成文本(123 变 `"123"`),SUM / 排序随之按文本处理,
|
|
204
|
+
只对需要保持文本的格用。设边框还会改变界面「边框」按钮记住的样式与颜色(Univer 的全局边框设置)。
|
|
205
|
+
|
|
206
|
+
### 演示文稿(pptx)
|
|
207
|
+
|
|
208
|
+
| 工具 | 用途 |
|
|
209
|
+
|---|---|
|
|
210
|
+
| `slide_read` | 读演示文稿的结构化视图(只读 XML):每页版式、形状 id / 名称 / 位置尺寸。改之前必须先调;`include_format` 看现有文字格式 |
|
|
211
|
+
| `slide_find` | 全文检索形状文本与表格单元格,返回可直接回填的 `slide` + `shape_id` |
|
|
212
|
+
| `slide_replace_text` | 整体替换一个文本形状,或全文查找替换(跨格式片段的命中会列在 `unreplaced`) |
|
|
213
|
+
| `slide_format_text` | 设文字格式(加粗 / 斜体 / 下划线 / 删除线 / 字号 / 颜色含主题色 / 字体 / 高亮)、段落对齐、网址或跳页超链接;按 `shape_id`(表格加 `cells`)+ 可选 `paragraphs` / `match` 定位 |
|
|
214
|
+
| `slide_manage_slides` | 页 add / delete / duplicate / move,分节同步调整 |
|
|
215
|
+
| `slide_add_element` | 新增文本框 / 图片(`path`)/ 预设形状,返回新 `shape_id` |
|
|
216
|
+
| `slide_modify_shapes` | 批量改位置尺寸、旋转、填充、边框或删除;任一 `shape_id` 无效则整次不生效;文本形状可设 `wrap` / `autofit` |
|
|
217
|
+
| `slide_table_edit` | 表格改单元格、插删行列(1-based,合并区域只读) |
|
|
218
|
+
| `slide_set_notes` | 写某页的演讲者备注 |
|
|
219
|
+
| `slide_undo` | 撤销最近一次 AI 编辑,可连续调用 |
|
|
220
|
+
| `slide_import_pptx` | 用 `--out-dir` 里的 .pptx 替换当前演示文稿(撤销记录清空) |
|
|
221
|
+
| `slide_export_pptx` | 导出成 .pptx 落盘,未改动的部件与原文件逐字节一致 |
|
|
222
|
+
|
|
223
|
+
页码从 1 开始,长度单位 pt,颜色 `#RRGGBB`。每次 `call()` 原子:抛错不提交、不进撤销栈;没有改动任何部件时不提交;同样内容的重复写入会记一步撤销。
|
|
224
|
+
|
|
177
225
|
### 文档字节不进模型上下文
|
|
178
226
|
|
|
179
|
-
`doc_export_docx` / `doc_import_docx` / `sheet_export_xlsx`
|
|
227
|
+
`doc_export_docx` / `doc_import_docx` / `sheet_export_xlsx` / `slide_import_pptx` /
|
|
228
|
+
`slide_export_pptx` / `slide_add_element`(插图片)的参数和返回值里**没有文件内容**,
|
|
180
229
|
只有路径:
|
|
181
230
|
|
|
182
231
|
```
|
|
@@ -195,7 +244,7 @@ npx ywkf-editor-hub --port 4399 --token $(openssl rand -hex 16)
|
|
|
195
244
|
`@4399ywkf/editor/docx` 引入,通过 `<NotionEditor extensions={[...]}>` 注入)。
|
|
196
245
|
没注册时工具会报错并说明怎么装,而不是静默失败。表格侧没有这道手续 ——
|
|
197
246
|
`sheet_export_xlsx` 直接读 Univer 快照拼 OOXML,但它返回的 `warnings` 是
|
|
198
|
-
|
|
247
|
+
**导出时丢了什么**(图片、数据校验等插件数据,以及工具不支持的条件格式 / 筛选类型),非空就得如实转述,别当成功报。
|
|
199
248
|
|
|
200
249
|
表格**导入**不在工具面里:`.xlsx / .csv / .tsv` 走 `<DocumentView source={file}>`
|
|
201
250
|
(实现在 `@4399ywkf/editor/xlsx` 的 `importSheetSource`)—— 那是用户打开文件的动作,
|
|
@@ -225,6 +274,11 @@ LiteXML 对 ProseMirror JSON 是**有损压缩**(省 1.55x 以上 token),
|
|
|
225
274
|
steps 做 `doc_revert_turn`,目前没做 —— 想兜底的话用 `attachBridge` 的 `onCall`
|
|
226
275
|
钩子自己存快照。表格侧写操作都走 Univer 的 command 体系,用户按 Ctrl+Z 撤得掉,
|
|
227
276
|
但同样没有「这一轮 AI 改了哪些格子」的审计记录。
|
|
277
|
+
4. **pptx 只做按部件补丁。** 图表、SmartArt、分组内形状、合并单元格的结构只读;
|
|
278
|
+
渲染仍是 pptx-preview 的预览档,和 PowerPoint 的排版会有出入。
|
|
279
|
+
5. **撤销最多保留 20 份完整 pptx 快照在内存里**(媒体多的大文件占用成比例增加);
|
|
280
|
+
本期拒绝删除带动画的形状(含组内子形状带动画的分组)—— 删了会留下悬空的动画引用,
|
|
281
|
+
PowerPoint 打开会要求修复(实测确认)。
|
|
228
282
|
|
|
229
283
|
## 开发
|
|
230
284
|
|
package/bin/hub.mjs
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* ywkf-editor-hub [--port 4399] [--host 127.0.0.1] [--static ./dist] [--token xxx]
|
|
14
14
|
* [--out-dir .]
|
|
15
15
|
*
|
|
16
|
-
* 唯一一处不"纯"
|
|
17
|
-
* sheet_export_xlsx
|
|
16
|
+
* 唯一一处不"纯"的地方:导入导出与插图片(doc_export_docx / doc_import_docx /
|
|
17
|
+
* sheet_export_xlsx / slide_import_pptx / slide_export_pptx / slide_add_element 的图片)的文件内容由 hub 落盘 / 读盘,模型两头只看到路径。
|
|
18
18
|
* 文档是二进制,base64 进上下文会把窗口撑爆。
|
|
19
19
|
*/
|
|
20
20
|
import { createServer } from "node:http"
|
|
@@ -113,10 +113,14 @@ function insideOutDir(name) {
|
|
|
113
113
|
return join(OUT_DIR, rel)
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
/**
|
|
116
|
+
/** 调用前:这些工具的 path 由 hub 读成 base64,浏览器那头只认字节 */
|
|
117
|
+
const PATH_TOOLS = new Set(["doc_import_docx", "slide_import_pptx", "slide_add_element"])
|
|
118
|
+
|
|
117
119
|
async function beforeCall(tool, args) {
|
|
118
|
-
if (tool
|
|
119
|
-
|
|
120
|
+
if (!PATH_TOOLS.has(tool)) return args
|
|
121
|
+
// slide_add_element 只有插图片时才带 path,文本框 / 形状原样转发
|
|
122
|
+
if (tool === "slide_add_element" && !args?.path) return args
|
|
123
|
+
if (!args?.path) throw new Error(`${tool} 缺少 path`)
|
|
120
124
|
const file = insideOutDir(args.path)
|
|
121
125
|
let buf
|
|
122
126
|
try {
|
|
@@ -132,6 +136,7 @@ async function beforeCall(tool, args) {
|
|
|
132
136
|
const EXPORT_TOOLS = new Map([
|
|
133
137
|
["doc_export_docx", "document.docx"],
|
|
134
138
|
["sheet_export_xlsx", "工作簿.xlsx"],
|
|
139
|
+
["slide_export_pptx", "演示文稿.pptx"],
|
|
135
140
|
])
|
|
136
141
|
|
|
137
142
|
async function afterCall(tool, result) {
|