🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

办公文档工具箱 17897693/dsh-wen

DeepSeek Harness
1789769325 天前有提交已提供中文文档扫描:含敏感能力

DSH 办公文档全能插件:docx/xlsx/pptx/pdf/odf/csv/html 读写改互转 + 内嵌离线…

30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/9 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add 17897693/dsh-wen
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · other
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 25 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-wen(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=18 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/15 04:21:12

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 451 处,展示前 68 条)
  • 读取本地文件
    index.js:231
    const info = await stat(file).catch(() => undefined)
  • 读取本地文件
    index.js:235
    return readFile(file)
  • 读取本地文件
    index.js:291
    const left = tmp && existsSync(tmp) ? `;临时文件未能清理:${tmp}` : ''
  • 写入本地文件
    index.js:307
    await rename(tmp, file)
  • 写入本地文件
    index.js:321
    renameSync(tmp, file)
  • 写入本地文件
    index.js:333
    await mkdir(dirname(file), { recursive: true })
  • 删除本地文件
    index.js:349
    try { await rm(tmp, { force: true }) } catch { }
  • 写入本地文件
    index.js:355
    mkdirSync(dirname(file), { recursive: true })
  • 删除本地文件
    index.js:369
    try { rmSync(tmp, { force: true }) } catch { }
  • 删除本地文件
    index.js:386
    try { await rm(tmp, { force: true }) } catch { }
  • 删除本地文件
    index.js:398
    try { rmSync(tmp, { force: true }) } catch { }
  • 写入本地文件
    index.js:542
    mkdirSync(stageDir, { recursive: true })
  • 写入本地文件
    index.js:543
    writeFileSync(stage, bytes)
  • 读取本地文件
    index.js:548
    if (!existsSync(png)) res = runRenderScript(stage, pngDir, ['1'])
  • 读取本地文件
    index.js:549
    if (!existsSync(png)) throw new Error(`${head}第 1 页渲染失败(${renderFailureDetail(res)}${renderLocationHint(stage)})${tail}`)
  • 读取本地文件
    index.js:550
    const firstPageBytes = statSync(png).size
  • 删除本地文件
    index.js:582
    if (tmp) rmSync(tmp, { force: true })
  • 删除本地文件递归
    index.js:585
    rmSync(pngDir, { recursive: true, force: true })
  • 执行外部命令固定命令
    index.js:3195
    let res = spawnSync('powershell.exe', args, opts)
  • 执行外部命令固定命令
    index.js:3197
    if (res.error && /EPERM|EACCES/.test(String(res.error.code))) res = spawnSync('powershell.exe', args, { ...opts, stdio: 'ignore' })
  • 读取本地文件
    skill.js:55
    content: await readFile(SKILL_BODY_URL, "utf8"),
  • 读取本地文件
    image.js:35
    return { buf: readFileSync(raw), from: 'path', path: raw }
  • 读取本地文件
    rapidocr.js:88
    if (!dir || !existsSync(dir)) return null
  • 读取本地文件
    rapidocr.js:89
    if (existsSync(join(dir, 'RapidOCR-json.exe'))) return dir
  • 读取本地文件
    rapidocr.js:93
    if (existsSync(join(dir, n, 'RapidOCR-json.exe'))) return join(dir, n)
  • 读取本地文件
    rapidocr.js:112
    const missing = Object.values(DEFAULT_MODELS).filter(f => !existsSync(join(models, f)))
  • 读取本地文件
    rapidocr.js:241
    try { ents = readdirSync(d, { withFileTypes: true }) } catch { continue }
  • 读取本地文件
    rapidocr.js:262
    if (!root || !existsSync(root)) continue
  • 删除本地文件递归
    rapidocr.js:282
    rmSync(full, { recursive: true, force: true })
  • 执行外部命令固定命令
    rapidocr.js:304
    const r = spawnSync('tasklist', ['/FI', `PID eq ${pid}`, '/NH'], { windowsHide: true, timeout: 8000 })
  • 执行外部命令固定命令
    rapidocr.js:312
    const r = spawnSync('tasklist', ['/FI', 'IMAGENAME eq RapidOCR-json.exe', '/NH'], { windowsHide: true, timeout: 8000 })
  • 执行外部命令固定命令
    rapidocr.js:331
    return spawnSync('taskkill', ['/PID', String(pid), '/T', '/F'], { windowsHide: true, timeout: 15000, stdio: 'ignore' })
  • 删除本地文件
    rapidocr.js:340
    rmSync(file, { force: true })
  • 删除本地文件
    rapidocr.js:351
    try { rmdirSync(dir); meta.workDirRemoved = true } catch { meta.workDirRemoved = false }
  • 写入本地文件
    rapidocr.js:382
    try { mkdirSync(dir, { recursive: true }) } catch { }
  • 写入本地文件
    rapidocr.js:389
    writeFileSync(inJ, body, { encoding: 'utf8' })
  • 执行外部命令来自配置/变量
    rapidocr.js:405
    child = spawn(engine.exe, flags, { cwd: engine.dir, stdio: [fdIn, fdOut, fdOut], windowsHide: true })
  • 读取本地文件
    pdffont.js:390
    try { font = new SfntFont(readFileSync(path), fallbackName) } catch { font = null }
  • 读取本地文件
    repro.mjs:180
    try { entries = readdirSync(dir, { withFileTypes: true }) } catch { return }
  • 读取本地文件
    repro.mjs:185
    try { found.push({ p, m: statSync(p).mtimeMs, s: statSync(p).size }) } catch { }
  • 写入本地文件
    repro.mjs:210
    await mkdir(TMP, { recursive: true })
  • 写入本地文件
    repro.mjs:212
    await copyFile(sample, local)
  • 读取本地文件
    repro.mjs:240
    const doc = readPdfText(await readFile(local))
  • 删除本地文件递归
    repro.mjs:278
    if (!process.env.DSH_OFFICE_REPRO_KEEP) await rm(TMP, { recursive: true, force: true })
  • 写入本地文件
    test.mjs:50
    try { await rm(dir, { recursive: true, force: true }); await mkdir(dir, { recursive: true }); OUT = dir; return OUT }
  • 删除本地文件递归
    test.mjs:50
    try { await rm(dir, { recursive: true, force: true }); await mkdir(dir, { recursive: true }); OUT = dir; return OUT }
  • 写入本地文件
    test.mjs:90
    mkdirSync(dirname(p), { recursive: true })
  • 读取本地文件
    test.mjs:91
    const id = registerSourceIdentity(pdfPath, readFileSync(pdfPath))
  • 写入本地文件
    test.mjs:93
    writeFileSync(p, `<!-- dsh-office OCR cache -->\n<!-- ${manifestLine} -->\n${identity}${body}`, 'utf8')
  • 执行外部命令来自配置/变量
    test.mjs:316
    const r = spawnSync(process.execPath, ['--input-type=module', '-e', code], {
  • 写入本地文件
    test.mjs:340
    mkdirSync(r, { recursive: true })
  • 写入本地文件
    test.mjs:342
    writeFileSync(probe, 'x')
  • 删除本地文件
    test.mjs:343
    rmSync(probe, { force: true })
  • 读取本地文件
    test.mjs:384
    ok('创建 docx', existsSync(docx) && r.bytes > 3000, `${r.bytes} bytes`)
  • 读取本地文件
    test.mjs:402
    ok('创建 xlsx 双表', existsSync(xlsx) && r.summary.includes('成绩'), r.summary)
  • 读取本地文件
    test.mjs:439
    ok('创建 pptx 三页', existsSync(pptx) && r.summary.includes('3 页'), r.summary)
  • 读取本地文件
    test.mjs:448
    ok('创建 pdf(含中文)', existsSync(pdf) && r.bytes > 2000, `${r.bytes} bytes`)
  • 读取本地文件
    test.mjs:502
    const healedFile = readFileSync(join(OUT, 'scan-like.ocr.md'), 'utf8')
  • 写入本地文件
    test.mjs:668
    await copyFile(scan, sample)
  • 删除本地文件递归
    test.mjs:716
    rmSync(fixDir, { recursive: true, force: true })
  • 执行外部命令固定命令
    test.mjs:718
    spawnSync('powershell.exe',
  • 删除本地文件递归
    test.mjs:744
    rmSync(out, { recursive: true, force: true })
  • 执行外部命令固定命令
    test.mjs:747
    spawnSync('powershell.exe',
  • 删除本地文件递归
    test.mjs:760
    rmSync(defOut, { recursive: true, force: true })
  • 执行外部命令固定命令
    test.mjs:764
    spawnSync('powershell.exe',
  • 删除本地文件
    test.mjs:841
    rmSync(pvSide, { force: true })
  • 执行外部命令固定命令
    test.mjs:1537
    const res = spawnSync('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', ps],
  • 执行外部命令固定命令
    test.mjs:1569
    const res = spawnSync('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command',
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 文档读写与修改
  • 多格式互转
  • 离线OCR识别

DSH 办公文档插件:docx/xlsx/pptx/pdf/odf/csv/html 读写改与互转 + 离线 OCR(自用为主,不承诺维护)

README

由 DeepSeek 最新模型翻译生成
dsh-wen — DSH 系统级 Office 全能插件 dshbase install-tested 一句话:零第三方依赖(仅 Node 内置模块)的 Office 全家桶 —— 让 DSH 多出 4 个全局工具,读写改转 docx / xlsx / pptx / pdf / odf / csv / html,附中文 PDF 乱码自愈与扫描件离线 OCR。 设计目标:装上不让 DSH 崩。详见 dshbase 实测页。 dsh-wen 在 DSH 会话中的实际运行:office_create 创建 docx、office_read 读回 English · A zero-dependency Office all-in-one plugin for DeepSeek Harness (DSH): read, create, edit and convert .docx / .xlsx / .pptx / .pdf (text layer) / .odf / .csv / .html with built-in offline OCR (Chinese). Install with dsh plugin --profile web add github:17897693/dsh-wen. Note: the full OCR and PDF rendering quali
展开完整文档(README 剩余 1 节)
dsh-wen — DSH 系统级 Office 全能插件

dshbase install-tested

一句话:零第三方依赖(仅 Node 内置模块)的 Office 全家桶 —— 让 DSH 多出 4 个全局工具,读写改转 docx / xlsx / pptx / pdf / odf / csv / html,附中文 PDF 乱码自愈与扫描件离线 OCR。
设计目标:装上不让 DSH 崩。详见 dshbase 实测页。

dsh-wen 在 DSH 会话中的实际运行:office_create 创建 docx、office_read 读回

English · A zero-dependency Office all-in-one plugin for DeepSeek Harness (DSH): read, create, edit and convert .docx / .xlsx / .pptx / .pdf (text layer) / .odf / .csv / .html with built-in offline OCR (Chinese). Install with dsh plugin --profile web add github:17897693/dsh-wen. Note: the full OCR and PDF rendering quality gate are Windows x64–only; on other platforms it degrades to the pure-JS feature set. UI and documentation are primarily in Chinese.

关于这个项目

考公考编闲暇之余写的 DSH 办公文档插件,自用为主,顺手开源。
项目原名 dsh-office,后更名为 dsh-wen。

稳定性设计目标

本项目最初的动机是确保 DSH 在安装任何插件后都不会崩溃:因此采用零第三方依赖(仅使用 Node 内置模块)、只注册全局工具、不触碰 GUI 服务的设计,稳定性为第一优先级。已实测的环境:DSH 0.1.7-alpha.2(Windows x64)安装与加载通过;其他平台按上文「平台」一节自动降级运行。本仓库不保证在任何未实测环境(含历史版本 DSH)下同样稳定,请以实际验证为准。

平台

Windows x64 为完整能力平台。OCR(内嵌 RapidOCR-json.exe)与 PDF 产出的渲染级质量门(PowerShell + WinRT)依赖 Windows;其他平台自动降级为纯 JS 能力(docx / xlsx / pptx / pdf 文本层 / odf / csv / html / md 的读写与互转)。

安装

推荐作为 DSH 组合包安装(profile 内一条命令):

dsh plugin --profile web add ./dsh-wen # 本地目录
或从 git:dsh plugin --profile web add github:17897693/dsh-wen

包内的 cordis.patch.yml 会随 dsh.bundle 声明自动作为一个配置层生效。
若你不安装为包、而是手动挂载,请把该文件里两行的 name 改成 index.js / skill.js 的绝对路径(home 级 ${DSH_HOME}/cordis.patch.yml 同样可用)。

dsh --profile web --dump-config # 应能看到 "# == dsh-wen" 层

兼容性说明

- 工具名仍是 office_read / office_create / office_edit / office_convert,环境变量仍是 DSH_OFFICE_:这些是既有调用契约,更名时刻意未动。
- 仅插件标识更名(包名、skill 名、cordis 插件名)。
- 内部缓存目录名与批间标记仍沿用 dsh-office,以保证既有缓存与输出格式不变。

文档

- SKILL.md —— 面向调用方的操作手册(工具选择 / 参数 / 已知边界)
- CHANGELOG.md —— 逐轮修复史与实测数据
- DEVELOPMENT.md —— 内部实现细节与诊断过程(上述两份文档写于更名前,故内文仍记作 dsh-office;其中样本文件名与环境路径已代号化)

第三方组件

vendor/ 内的 OCR 引擎与模型属于第三方作品,各自遵循其许可 —— 见 THIRD-PARTY-NOTICES.md。不需要 OCR 时可以不打包 vendor/。

免责

本软件按「原样」提供,不附带任何形式的担保。

能力与挂载

零第三方依赖(仅 Node 内置模块)的办公文档读写/编辑/转换能力,注册为 DSH 全局工具, 所有 profile 的所有新会话自动可用,无需手动启用或配置路径。

- 安装位置:${DSH_HOME}/plugins/dsh-wen/(本机为 ${DSH_HOME}/plugins/dsh-wen\)
- 挂载方式:${DSH_HOME}/cordis.patch.yml(DSH_HOME 级 patch 层,对所有 profile 生效)
- 插件行(绝对路径,两行):id: tool-office 与 id: skill-office,name: 分别是
${DSH_HOME}/plugins/dsh-wen/index.js 与 ${DSH_HOME}/plugins/dsh-wen/skill.js
(裸包名 dsh-wen 在 desktop profile 下解析失败,patch 文件里已注明)

本文档只装:快速入门 / 格式能力矩阵 / 常见用法 / 指向下面两份文档的入口。
「工具怎么选、按什么顺序操作、参数怎么传、哪些边界仍然生效、失败后下一步做什么」的完整口径在 SKILL.md(面向调用方的唯一权威操作手册);逐轮修复史、内部实现细节、诊断过程与当轮实测数据在 DEVELOPMENT.md。

提供的工具

| 工具 | 作用 |
| office_read | 读取办公文档 → Markdown / 纯文本 / JSON / 元数据。支持 sheet(工作表)、pages(PDF 页码范围)、pageFrom/pageTo(PDF 页级续读)、offset/limit(超长续读)、paths(批量盘点:一次返回逐文件轻量 stats)、boundary(分批读取的批间衔接内联开关)。⚠ as="json" / as="meta" 的 content 是 JSON 文本字符串(不是对象,调用方需自行 JSON.parse) |
| office_create | 按扩展名创建文件。内容来源任选其一:markdown、document、slides、workbook、table、from(转换式创建);encoding 控制文本类目标写出 BOM |
| office_edit | 原地修改已有文件(zip/XML 级,保留其余内容;CSV/文本编辑保留原 BOM) |
| office_convert | 读取 source,按统一内容模型写出 target(扩展名决定目标格式);encoding 控制文本类目标写出 BOM |

格式支持

| 类别 | 读取 | 创建 | 编辑 |
| Word | .docx .docm .dotx、.doc(OLE2 97-2003)、.wps(OLE2 变体) | .docx | replace_text / append_markdown / set_meta / insert_image / append_image(插图:{path 或 base64, alt?, width?(磅;省略则按原图像素 × 72/96,上限 A4 可用宽 451.3pt 等比缩), after?(文本锚点)},PNG/JPEG/GIF/BMP,内容 SHA-256 去重;zip 级新增 word/media/ + image 关系 + w:drawing) |
| Excel | .xlsx .xlsm .xltx、.xls(BIFF8)、.et(OLE2 变体)、.csv .tsv | .xlsx .csv .tsv | set_cell / append_rows / replace_value / add_sheet / rename_sheet / delete_sheet |
| PowerPoint | .pptx .pptm .potx、.ppt .dps .pps .pot(PPT97 记录流) | .pptx | replace_text / add_slide / update_slide / delete_slide |
| PDF | .pdf(文本层提取,含 CID/ToUnicode 中文、对象流、PNG/TIFF 预测器;含 AES-256(R5/R6)空口令加密) | .pdf(拉丁用 base-14;中文/emoji 内嵌系统字体子集:Identity-H + FontFile2 + 完整 ToUnicode,simsun.ttc→simhei→msyh 字体链,写盘前过产出质量门;markdown 里的图片 → /XObject:JPEG 走 DCTDecode 原样内嵌、PNG 走 FlateDecode+/SMask) | 不支持原地编辑(先 office_convert) |
| 网页 | .html .htm(零依赖 DOM 解析:h1-h6/嵌套列表/表格/引用/代码块/外链保留,style/script/隐藏子树剥离,实体解码; → image 块) | .html(语义化 HTML5:h1-h6/表格/嵌套列表/引用/代码块/行内强调/,UTF-8 + ,中文不转实体。⚠ .htm 只能读/编辑,不能作为创建或转换目标) | replace_text / append_text / prepend_text(文件级文本替换,不改结构、不重新排版) |
| OpenDocument | .odt .ods .odp | .odt .ods .odp | replace_text / append_markdown(.odt) |
| 文本类 | .md .txt .json .jsonl .rtf | .md .txt .json | replace_text / append_text / prepend_text |

转换矩阵:任意可读格式 → 任意可创建格式(经统一内容模型,如 docx→pdf、xlsx→csv、pptx→md、md→docx/pdf/pptx/html)。

使用示例

office_read path="D:\报告.docx" # 读 Word 为 Markdown office_read path="D:\台账.xlsx" sheet="明细" # 只读某个工作表 office_read path="D:\讲义.pdf" pages="1-5" # 只读 PDF 前 5 页 office_read path="D:\讲义.pdf" pageFrom=6 pageTo=20 # 页级续读(含端点,等价 pages="6-20") office_read path="D:\数据.xlsx" as="meta" # 只看工作表/行列统计 office_read paths=["<corpus>/真题"] # 批量盘点:一次返回目录内逐文件轻量 stats office_read path="D:\笔记.html" as="markdown" # 读网页笔记(style/script 剥离、表格/嵌套列表保留) office_read path="D:\台账.xlsx" recalc=true # 重算公式:公式格给计算值 + stats.recalc(不支持的函数标 unsupported,绝不猜)

office_create path="D:\汇总.docx" markdown="# 标题\n- 要点\n\n| A | B |\n| --- | --- |\n| 1 | 2 |" office_create path="D:\成绩.xlsx" workbook={sheets:[{name:"S1",rows:[["姓名","分数"],["张三",95]]}]} office_create path="D:\汇报.pptx" slides={slides:[{layout:"title",title:"标题",subtitle:"副标题"},{title:"要点",bullets:[{text:"一",level:0}]}]} office_create path="D:\报告.pdf" markdown="# 中文标题\n\n正文(中文默认内嵌系统字体子集;WinRT/Edge/Chrome 渲染正常、提取不丢字符)" office_create path="D:\交付.csv" table={rows:[["城市","备注"],["唐山","含,逗号"]]} # 默认 UTF-8 with BOM,Excel 双击不乱码 office_create path="D:\申论.docx" markdown="# 作答" grid="20x25" # 申论稿纸:Word 文档网格(每行 20 字 × 每页 25 行;也接受数字 grid=20) office_create path="D:\图文.pdf" markdown="# 标题\n\n示意图" # 含图 markdown → PDF 真内嵌图片(JPEG DCTDecode / PNG FlateDecode+SMask)

office_edit path="D:\报告.docx" operations=[{op:"replace_text",find:"旧",replace:"新"},{op:"append_markdown",markdown:"## 补充"}] office_edit path="D:\台账.xlsx" operations=[{op:"set_cell",sheet:"明细",cell:"B3",value:100},{op:"add_sheet",name:"新增"}] office_edit path="D:\汇报.pptx" operations=[{op:"add_slide",slide:{title:"答疑",bullets:["Q&A"]}}] office_edit path="D:\报告.docx" operations=[{op:"append_image",path:"D:\图.png",alt:"示意图",width:400}] office_edit path="D:\报告.docx" operations=[{op:"insert_image",base64:"data:image/png;base64,iVBOR…",alt:"插图",after:"第二章"}]

office_convert source="D:\台账.xlsx" target="D:\台账.csv" office_convert source="D:\报告.docx" target="D:\报告.pdf" office_convert source="D:\笔记.html" target="D:\笔记.md" # 网页 → Markdown

常见用法

扫描件 / 图片型 PDF

office_read 内置扫描页处理,无需截图、无需分步操作:ocr="auto"(默认)在页面没有文本层时自动识别(未指定 pages 时先做前 3 页预览;指定 pages 时单次上限 20 页),默认走本地 RapidOCR-json(离线),只有它判为可疑的页才升级视觉模型复核。
text
office_read path="D:\扫描件.pdf" # 自动 OCR 首页若干张 office_read path="D:\扫描件.pdf" as="meta" # 先看哪些页是扫描页(stats.scannedPages) office_read path="D:\扫描件.pdf" pages="3-8" # 只 OCR 第 3–8 页 office_read path="D:\扫描件.pdf" pages="1-20" ocrEngine="local" # 批量识别且不花视觉额度

参数语义(ocr / ocrEngine / ocrEngine="vision" 的适用场景)、降级链与 sidecar(.ocr.md)、来源标注、换倍率重试、失败后怎么续读、以及全部 OCR 相关环境变量 → SKILL.md「读取的正确顺序」与「调优环境变量」。
栅格化与引擎发现的实现细节、缓存位置的历史坑 → DEVELOPMENT.md。

加密 / 权限受限 PDF

只设了权限密码(禁止复制/打印)而打开密码为空的文件(考试资料、电子书很常见)会透明解密后正常读取,无需额外操作,也不改写原文件。真正需要打开密码的文件不会被猜测或绕过,会明确提示"需要密码,请在阅读器中输入密码后另存为未加密版本"。

覆盖范围:RC4-40 / RC4-128 / AES-128 / AES-256(R5/R6)。
算法细节、判别实验结论与"与第三方逐字节一致仍未取得"这条自证风险 → SKILL.md「已知边界」。

批量盘点大目录 text office_read paths=["<corpus>/真题"] # 一次调用返回逐文件轻量 stats:format/pages/characters/

textLayerUsable/scannedPages/garbledPages/blocks/sheets/slides

+ suggestedBatches(建议分批数),绝不返回正文

20+ 个 PDF 的盘点从 20 次 as="meta" 调用变成 1 次;目录里的插件缓存(.ocr.md / .read.md / .ocr.json)自动排除。单文件失败进该行 error,不连累整批。
suggestedBatches 的口径与单文件 meta.suggestion 一致:乱码 PDF 按 20 页/批;干净 PDF 只有超过 12 页才按 15 页/批(≤12 页算 1 批);其他格式按内联上限估算(不超上限就是 1)。

中文 PDF 产出

office_create / office_convert 写到 .pdf 时默认内嵌系统字体子集(Identity-H + FontFile2 + 完整 ToUnicode,/BaseFont 带 XXXXXX+ 前缀),WinRT / Edge / Chrome 渲染正常、office_read 提取不丢字符。
写盘前还会过产出质量门(字节级 + 第 1 页渲染级抽检):判定为「渲染为空白」时拒绝落盘并抛四要素错误。
返回值带 stats.pdfQuality = { embedded, renderCheck, firstPageBytes, images, imagesSkipped?, notice? }。

⚠ 中文 PDF 在非 %TEMP% 目录里也能正常产出(R18 修好了渲染副本的落点)—— 若你自定义了 DSH_OFFICE_PDF_GATE_DIR,请把它指向 %TEMP% 内的目录:本机 WinRT 的 PDF 渲染器只读得到 %TEMP% 下的文件(详见 SKILL.md「调优环境变量」)。

已知边界(速查)

每条都有一句话结论;完整口径、判别方法与失败后的下一步在 SKILL.md「已知边界」。

- 扫描件无文本层不会报错(默认自动 OCR);只有显式 ocr="never" 且整本无文本层才抛错。
- 过门 ≠ 可直接引用:质量门只说明「质量门放过」,数字/正负号密集的表格页务必回原 PDF 核对(典型症状是负号被丢,视觉复核升级治不了这类版面级噪声)。
- 中文 PDF 乱码有两种成因(自家解析器错位已修 / 文档真缺 ToUnicode),修法不同,靠 stats.textLayerUsable + qualityGate.reasons 的措辞区分。
- .wps / .et / .dps 的金山新版专有二进制解析不了,请先另存为 OOXML;OLE2 变体可直接读。
- PDF 不支持原地改文本;要改就 office_convert 重出一份。
- pptx 的 update_slide 会重写该页(该页原有图片/复杂图形会丢),其他页不受影响。
- 图片写出端:docx / pdf / html 真内嵌;.odt / .pptx / .md 等显式降级为字面 alt 文本 + stats.imageFallback + notice(绝不静默丢图)。
- .html 编辑是文件级文本替换,不改结构、不重排版。
- 写盘一律原子(目标同目录唯一临时件 → 成功后替换);失败时原文件逐字节不变 + 「写盘失败|四要素」。
- ZIP 解压有护栏(单条目 256 MiB / 累计 512 MiB / CRC32 默认校验),越界与说谎的长度给可读中文错误。
- ZIP 写出端支持真实 ZIP64(≥65535 条目、尺寸或偏移 ≥4 GiB 时按规范写扩展字段 + EOCD64);「≥4 GiB 数据尺寸」这条分支只有布局级 + 声明级证据(端到端峰值内存 ≈8.0 GB,本机跑不了)——但声明格式已被 .NET ZipArchive 正确接受(Entry.Length 读成 4 GiB+)。详见 DEVELOPMENT.md R19 §A。
- 工具参数错误带 operations[N] 下标定位(缺 op / op 不认识 / 字段类型不对都在参数层报错)。
- 未实现能力的清单与重开条件(PDF 合并拆分、OMML 公式写入、.html 结构化编辑)见 DEVELOPMENT.md。

开发与修复史

逐轮修复注记、内部实现细节与诊断过程全部在 DEVELOPMENT.md:那里有「历史上修过什么、为什么这么修」的全量资料与逐轮实测数据(含 R16 / R18 的交付报告)。

验证

node test.mjs 运行端到端检查(具体数量看最后一行的 N checks,不要在文档里写死):
创建/读回/编辑/转换全格式闭环、真实 docx/xlsx/pptx/pdf/csv 读取、独立 zip 与 CRC 校验、
包结构体检(checkOoxmlPackage():[Content_Types].xml 覆盖、关系可解析、全部 XML 可解析)、错误处理。

在任意目录都能跑:产物目录默认 ./test-out,不可写时自动回退到系统临时目录; DSH_OFFICE_TEST_OUT 可指定产物目录,DSH_OFFICE_TEST_SCAN_PDF 可钉住 OCR 样本(默认取 ~/.dsh/attachments 中最近一个 >5 MiB 的 PDF,并拷进产物目录使用,不会改动用户附件与其 sidecar)。

慢 / 可选的三条用例(默认跳过,发版前手工跑一次):DSH_OFFICE_TEST_EXPAND_ARCHIVE=1 (真·Expand-Archive 解 65536 条目,约 20 分钟)、DSH_OFFICE_TEST_REAL_4GIB=1 (真实 >4 GiB 合法 ZIP64 条目,约 15 秒)、DSH_OFFICE_TEST_NET_DIR=<网络盘目录> (网络盘上的原子替换)。全部测试变量见 SKILL.md「排查」。

原生 Office 冒烟:node test.mjs 会调本机的 Word / PowerPoint / Excel COM 做真实开箱验证 ——产出的 .docx(含含图、稿纸网格)、.html 能被 Word 16.0 打开并导出 PDF;产出的 .pptx 能被 PowerPoint 16.0 打开(并带「把 notesMaster 主题改回共用 theme1 必须仍 FAIL」的负向控制)。
这些冒烟在本机 Office 不可用时会明确 skip 并打印原因(不静默当通过);真实 AES-256 样本的回归槽位见 DSH_OFFICE_TEST_AES256_PDF。

卸载

删除 ${DSH_HOME}/cordis.patch.yml 中的 tool-office 与 skill-office 两行(或整个文件),再删除 ${DSH_HOME}/plugins/dsh-wen/ 目录即可;也可只把这两行 disabled: true 临时停用。

维护状态:不承诺维护

- 不保证跟进 DSH 的版本变更;作者可能随时停止更新或归档本仓库
- 不承诺回复 issue / PR
- 欢迎 fork 自行维护、修改、再分发(见 LICENSE)
预览分享卡片长什么样 ↓17897693/dsh-wen
分享 · DeepSeek Harness Hub
17897693/dsh-wen

DSH 办公文档全能插件:docx/xlsx/pptx/pdf/odf/csv/html 读写改互转 + 内嵌离线…

这是你的仓库?认领条目

回到顶部