中文EN

dsh-pdf-edit

docs装不上npmMIT

面向 PDF 文档的编辑插件,精确编辑PDF文字

下载量 / Downloads
910
测试时间 / Tested
2026-11-07
DSH 版本 / Version
0.2.2-rc.1

安装

dsh plugin --profile web add dsh-pdf-edit

沙箱测试结果

阶段结果
1 安装✗
2 列装—
3 挂载—
4 启动—
第一条错误
dsh: initialized profile web at /home/node/.dsh/profiles/web

四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。

README

dsh-pdf-edit

[English](./README.en.md) | 中文

![npm version](https://www.npmjs.com/package/dsh-pdf-edit)

![dsh-std Community v0.15](https://github.com/Whatsmore-nf/dsh-pdf-edit/blob/main/dsh-plugin.json)

![License: MIT](./LICENSE)

🧩 已接入 dsh-std 生态(Community v0.15):本插件随包提供 dsh-plugin.json 静态清单与标准 FacetModule 入口(dist/std/host.js),可被 @dsh-std/adapter-dsh 等 dsh-std 标准宿主直接装载,**不依赖任何 @deepseek-ai/* 官方包**;同时保留 cordis 直连入口。两条入口共用同一套工具实现,编辑行为完全一致。

版本:v0.4.5(当前) | 需要 Node >= 22;兼容 dsh >= 0.1.1-rc.2(cordis 直连)与 dsh-std Community v0.15 宿主

DeepSeek Harness 插件 —— AI 修改 PDF 文字,自动保持原版式不变。

这是什么

一个面向 PDF 文档的 AI 编辑插件。你用自然语言告诉它要改什么,它就会:

  • 只改文字,不动排版 —— 字体、字号、颜色、位置全部锁定,改完和原文看起来一模一样
  • 自动处理溢出 —— 新文字比原来长时,自动缩小字号或截断,不会撑破版面
  • 支持中文 —— 自动识别并嵌入系统中文字体(SimHei / 微软雅黑 / Noto Sans CJK)

适合什么场景

场景 · 举例

术语统一 · 全文把「帐号」改成「账号」、「数据中台」改成「数据平台」

错别字修正 · 让 AI 扫一遍,自动修正拼写和语法错误

合同/报告批量修改 · 多页文档统一替换人名、金额、日期等

格式转换 · 把散乱的 PDF 重新排版成学术论文双栏、手机阅读单栏、商务简报等版式

往 PDF 里补内容 · 把 md/笔记作为新页插到指定页之后(pdf-edit-insert,无需 LLM):自动排版横幅标题/正文/公式框、跨页断页、化学式上下标缺字自动回退

安装

# 通过 Harness 插件 CLI(与官方插件一致)
dsh plugin --profile web add dsh-pdf-edit@latest

# 或直接通过 npm
npm install dsh-pdf-edit
当前版本:v0.4.5(2026-08-25 发布)。主要更新:彩色背景不再留白块(native 直绘按内容流采样实际背景色作补丁底色)、tid 合并阈值自适应排版密度、大文档内存 LRU 淘汰、字体解析结果缓存提速批量编辑。v0.4.3:parsePatchObject 按 JSON 解析错误位置截断,彻底处理模型尾部任意说明文字。

dsh-std 标准生态适配(v0.4.0 新增)

本插件同时是 dsh-std Community v0.15 标准插件(dsh-std / dsh-ecosystem-spec):宿主通过静态 dsh-plugin.json 在不执行插件代码的前提下完成兼容性判定,运行期经 adapter 层与 dsh 本体通信——上游接口变更被 adapter 单点吸收,插件免维护。

两种装载方式

方式 · 宿主 · 入口 · 依赖

标准生态(推荐) · 支持 dsh-std 的宿主(如经 @dsh-std/adapter-dsh / dsh-TUI) · 包根 dsh-plugin.json → facets.host.entry(dist/std/host.js) · 无需任何 @deepseek-ai/* 包

cordis 直连(旧) · DeepSeek Harness 原生 profile · cordis.patch.yml + apply(ctx, config) · @deepseek-ai/dsh-tools(peerDep,现为 optional)

# 标准生态宿主内安装(adapter 会扫描 profile 依赖中的 dsh-plugin.json)
dsh plugin --profile web add @dsh-std/adapter-dsh
dsh plugin --profile web add dsh-pdf-edit

std 宿主下的配置(环境变量)

std 协议没有 cordis config 注入,配置改从环境变量读取:

环境变量 · 说明

DEEPSEEK_API_KEY · LLM Key;AI 精修必需(预览/插入不需要)。也可用 DSH_PDF_EDIT_API_KEY 覆盖

DSH_PDF_EDIT_ALLOWED_ROOTS · 路径白名单,按平台路径分隔符拼接(默认当前工作目录)

DSH_PDF_EDIT_PROVIDER / _MODEL / _BASE_URL · 模型路由(直连 API 时使用)

DSH_PDF_EDIT_RENDER_MODE · native(默认)或 browser

DSH_PDF_EDIT_BROWSER_EXECUTABLE / _BROWSER_CONCURRENCY · 浏览器模式选项

DSH_PDF_EDIT_PATCH_COLOR / _STRICT_TIDS / _MISSING_TIDS_USE_ORIGINAL / _RECOVER_COLOR / _STRICT_COLOR / _OVERFLOW_MODE / _MIN_FONT_SIZE_PT · 其余编辑行为开关

说明:dsh-std tool/model 协议 v1alpha1 尚未向插件开放宿主 LLM 推理通道,因此 std 宿主下 AI 精修暂走 DeepSeek API 直连(Key 必填);工具注册、生命周期、清理语义全部走标准协议。

清单要点

  • $schema: urn:dsh-std:community-draft:dsh-plugin:0.15,manifestVersion: 0.15
  • 组件 ID:io.github.whatsmore-nf.dsh-pdf-edit
  • 5 个工具以 contributes["x-tools"] 声明为 tools.dsh/v1alpha1 Tool 扩展,activation 时逐一发布本地 ToolHandler
  • 不声明任何 required 契约与权限 → 与任意 std 宿主协商即兼容

遇到 "Cannot read properties of undefined (reading 'prepare')"?

这是 dsh 宿主 rc 阶段的已知问题:当 @deepseek-ai/dsh-tools 在进程内被加载多份时,工具调度器 Symbol 失配。本插件从 v0.1.7 起通过 peerDependencies(精确版本钉死 0.1.1-rc.2)从源头规避;但若曾在 profile 目录下手动执行过 pnpm install,残留副本仍可能触发。

按以下顺序排查:

# 1. 检查是否真的有本地副本(实体目录而非 symlink)
ls -l ~/.dsh/profiles/web/node_modules/@deepseek-ai/

# 2. 若有,移除核心包的本地副本
cd ~/.dsh/profiles/web
pnpm remove @deepseek-ai/dsh-tools @deepseek-ai/cordis

# 3. 重启 dsh,并【新建会话】验证(崩溃过的旧会话日志已损坏,无法恢复)

插件装载时也会主动探测该问题:若命中会直接抛出带上述修复命令的明确报错,而不是静默崩溃。


AI Agent 操作手册(隐藏规则)

在使用本插件前,请先确认以下三个“隐藏规则”——它们在源码中存在,但不在工具接口文档中直接说明:

规则 · 位置 · 影响 · 绕过方式

路径白名单 allowedRoots · src/path-guard.ts · 工具调用 (pdf-edit-preview / pdf-edit-document) 直接失败(文件不存在或不在允许目录) · 编程接口 StyleLockedEditor.open() 仍需配置 allowedRoots;或直接 node -e 调用内部模块绕开工具守卫

sanitizeText 拒收空字符串 · src/validator.ts:26 (t.length === 0 → {ok:false}) · editDocument('去掉所有小标题...') 若 AI 返回 "" 会被拒收,missingTidsUseOriginal: true 回填原文 · 直接操作 unit.text = '',再手动调用 drawPatchedPages()(见示例)

依赖 ctx.llm / DEEPSEEK_API_KEY · src/index.ts:96-121 · 工具接口依赖 DSH LLM 服务或环境变量;无配置时抛错 · 编程接口可传入自定义 chatFn(如 setChatFn),完全脱离工具调度

编程接口简要示例

const { StyleLockedEditor, applyPatches, removeSubheadings } = require('dsh-pdf-edit');

// 1. 打开文档(需 Uint8Array)
const original = new Uint8Array(require('fs').readFileSync('doc.pdf'));
const editor = await StyleLockedEditor.open(original, chatFn, { allowedRoots: ['/workspace'] });

// 2. 预览某页可编辑单元(获取 tid 列表)
const units = await editor.previewPage(1);
console.log(units);  // [{ tid: 'p1-0', text: '...' }, ...]

// 3. 全文 AI 修改(标准流程,受 sanitizeText 限制)
const result = await editor.editDocument('修正错别字并统一术语');
require('fs').writeFileSync('doc.edited.pdf', result);

// 4. 手动删除文字(绕过 sanitizeText 空文本限制)—— 完整可运行示例
const fs = require('fs');

// 4a. 提取页面并找到要删除的 tid(getExtract 已开放为公共方法)
const ex = await editor.getExtract(1);
const targetText = '小标题文字';  // 替换为实际要删除的文字
const deleteTid = ex.units.find(u => u.text.includes(targetText))?.tid;

if (deleteTid) {
  // 4b. 直接修改 Unit 文本为空(绕过 sanitizeText)
  const unit = ex.units.find(u => u.tid === deleteTid);
  unit.text = '';

  // 4c. 打开原生文档、渲染修改
  const { doc, resolver } = await editor.openNativeDoc();
  await editor.drawPatchedPages(doc, resolver, [
    { ex, changedTids: new Set([deleteTid]) }
  ]);
  const result = await doc.save();
  fs.writeFileSync('deleted.pdf', result);
}

await editor.close();

简化删除包装(v0.2.2 新增)

const { removeSubheadings } = re

…(truncated)

以上内容来自 npm 上的 README,我们只做格式化,不改内容。

版本

npm 上共发布:12,最后更新 2026-08-25

链接

GitHub · Homepage · npm

同类插件