PDF document editing plugin for precise text editing in PDF files.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-pdf-edit
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:Whatsmore-nf/dsh-pdf-edit
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
🚨 Temporary Maintenance Pause
This project will be placed on a maintenance pause for an extended period. No updates will be made during this time. The plugin may continue to function for a while, but please use it at your own risk. A resumption date has not been set. We appreciate your understanding. English | 中文
🧩 dsh-std ecosystem ready (Community v0.15): ships a
dsh-plugin.jsonstatic manifest and a standard FacetModule entry (dist/std/host.js), loadable by dsh-std hosts such as@dsh-std/adapter-dsh— no@deepseek-ai/*packages required; the legacy cordis entry is kept as-is. Both entries share the exact same tool implementations, so editing behavior is identical.
DeepSeek Harness plugin — AI edits PDF text, automatically preserving the original layout.
What Is This
An AI-powered PDF editing plugin. Tell it what to change in natural language, and it will:
- Edit text only, keep layout intact — Fonts, sizes, colors, and positions are all locked. The result looks identical to the original
- Handle overflow automatically — When replacement text is longer, font size shrinks or text truncates. Layout never breaks
- Support CJK — Auto-detects and embeds system CJK fonts (SimHei / MS Gothic / Noto Sans CJK)
Use Cases
| Scenario | Example |
|---|---|
| Terminology standardization | Replace 「帐号」with 「账号」, 「数据中台」with 「数据平台」document-wide |
| Typo correction | Let AI scan and fix spelling and grammar errors |
| Contract/report batch editing | Replace names, amounts, dates across multi-page documents |
| Format conversion | Reflow messy PDFs into academic 2-column, mobile single-column, or briefing layouts |
Install
Node
>= 22. Compatible with dsh0.1.1-rc.2(cordis-direct) and dsh-std Community v0.15 hosts.
# Via Harness plugin CLI (same as official plugins)
dsh plugin --profile web add dsh-pdf-edit@latest
# Or via npm
npm install dsh-pdf-edit
# Inside a dsh-std host (adapter scans profile dependencies for dsh-plugin.json)
dsh plugin --profile web add @dsh-std/adapter-dsh
dsh plugin --profile web add dsh-pdf-edit
dsh-std Ecosystem Adaptation (v0.4.0+)
This plugin is also a dsh-std Community v0.15 standard plugin: hosts read the static dsh-plugin.json at the package root to decide compatibility without executing plugin code, and all runtime traffic goes through an adapter layer — future upstream breaking changes are absorbed by the adapter, so this plugin stays maintenance-free.
| Loading mode | Host | Entry | Extra deps |
|---|---|---|---|
| dsh-std (recommended) | std-capable hosts (e.g. via @dsh-std/adapter-dsh) |
dsh-plugin.json → facets.host.entry (dist/std/host.js) |
none — zero @deepseek-ai/* packages |
| cordis-direct (legacy) | native DeepSeek Harness profiles | cordis.patch.yml + apply(ctx, config) |
@deepseek-ai/dsh-tools (optional peerDep) |
Under std hosts (no cordis config injection), configuration comes from environment variables:
| Variable | Meaning |
|---|---|
DEEPSEEK_API_KEY |
LLM key; required for AI editing (preview/insert work without it). DSH_PDF_EDIT_API_KEY overrides |
DSH_PDF_EDIT_ALLOWED_ROOTS |
Path whitelist, joined with the platform path delimiter (defaults to cwd) |
DSH_PDF_EDIT_PROVIDER / _MODEL / _BASE_URL |
Model routing for direct API calls |
DSH_PDF_EDIT_RENDER_MODE |
native (default) or browser |
Note: the dsh-std tool/model protocols (v1alpha1) do not yet expose host LLM inference to plugins, so AI editing under std hosts uses direct DeepSeek API calls; tool registration, lifecycle, and cleanup semantics are fully standard.
Seeing "Cannot read properties of undefined (reading 'prepare')"?
This is a known dsh-host issue from the rc stage: when @deepseek-ai/dsh-tools
is loaded more than once in the same process, the tool-scheduler Symbol misses.
Since v0.1.7 this plugin pins it via peerDependencies to prevent that at the
source — but a leftover copy can still trigger if you ever ran pnpm install
manually inside the profile directory.
Troubleshoot in order:
# 1. Check for a materialized local copy (real dir, not a symlink)
ls -l ~/.dsh/profiles/web/node_modules/@deepseek-ai/
# 2. If present, remove the core-package copies
cd ~/.dsh/profiles/web
pnpm remove @deepseek-ai/dsh-tools @deepseek-ai/cordis
# 3. Restart dsh and verify in a NEW session (old crashed sessions are unrecoverable)
The plugin also probes for this at load time: if detected, it throws an error containing these exact recovery commands instead of crashing silently.
Changelog
v0.4.0
- dsh-std Community v0.15 adaptation: static
dsh-plugin.jsonmanifest at the package root + standard FacetModule entry (src/std/host.ts→dist/std/host.js). Under std hosts (e.g.@dsh-std/adapter-dsh), the 5 tools are published astools.dsh/v1alpha1 Toolextensions with localToolHandlers; lifecycle/cleanup follow the standard activation scope - No hard dependency on official packages:
@deepseek-ai/dsh-toolspeerDependency is now optional — zero@deepseek-ai/*dependencies under std hosts; future upstream breaking changes are absorbed by the adapter layer. The cordis-direct entry is preserved unchanged and reports clear guidance when the package is missing - std-host configuration switches to environment variables (
DSH_PDF_EDIT_*/DEEPSEEK_API_KEY) - Tool parameter schemas upgraded to standard JSON Schema; tool implementations (
pdfEditPreview, etc.) are exported for both entries to share
v0.2.1
- Dynamically read DSH default model: use
ctx.agentDefaultModel.currentSelection()to get the user's current provider/model, replacing hardcoded agnes - Priority chain: user config (
config.provider/config.model) > DSH default model > agnes fallback - Whether the user is on deepseek, kimi, glm, minimax, openpangu, mino, claude, grok, gpt, etc., the plugin follows automatically — zero config needed
v0.1.8
- Reuse DSH built-in LLM service (
ctx.llm), no manual API Key configuration needed injectadds"llm"dependency, plugin calls DSH LLM viactx.llm.stream()- DeepSeek API direct connection kept as fallback (when
ctx.llmis unavailable)
v0.1.7
- Dependency restructure:
@deepseek-ai/dsh-toolsmoved from dependencies into peerDependencies, pinned exactly to0.1.1-rc.2, preventing pnpm from materializing a second copy inside profiles (dual copies break the tool-scheduler Symbol and crash every tool) - Load-time guard:
apply()probes for the scheduler before touchingctx.tools; on failure it throws a clear error with recovery commands instead of crashing silently - README install section now documents the "Cannot read properties of undefined (reading 'prepare')" troubleshooting flow; engines field declares Node >= 22
v0.1.6
- Adapt to the dsh v0.1.1-rc.2 plugin contract: export
name/inject/apply(ctx, config), register all four tools viactx.tools.register(defineTool(...)), configuration passed through the cordis patch row'sconfig:field - Add path whitelist guard:
pdfPath/outputPathvalidated against allowedRoots with symlink resolution and extension/size checks, preventing injection-driven arbitrary file read/write - Prompt injection defense: PDF text wrapped in a data container, hardened system prompt, second-stage injection scan on AI output with fallback to original text
- Browser rendering hardening: JavaScript disabled, outbound requests intercepted, CSP and CSS sanitizer, background dataUrl and font name whitelists
- Engineering robustness: API key env-first, request timeout, chunked concurrency limit, 429-aware backoff, AI output length caps
- New test suite (120 cases) and editing benchmark (10 cases,
npm run bench)
v0.1.5
- Rename package from
@whatsmore-nf/dsh-plugin-pdf-edittodsh-pdf-edit, display plugin name directly in the marketplace
v0.1.4
- Fix
embedCustompassing fontkit object todoc.embedFont, now passesUint8Arraydirectly - Fix
loadBytesnot supporting string paths (e.g.fonts.cjk: '/path/to/font.ttf') - Fix CFF-format TTC font compatibility, auto-detect and skip unsupported CFF fonts
- Add Android system font paths (MiSansRoundedSC, NotoSansSC, etc.)
- Simplify
cordis.patch.ymlto community plugin standard format
v0.1.3
- Fix missing
output: { schema, render }field inctx.tools.register()causing registration failure - Fix
executesignature mismatch (should be(args, exec)two-parameter)
v0.1.2
- Add cordis plugin format
name/inject/applyexports, fix "invalid plugin" error
v0.1.1
- Fix plugin name mismatch in
cordis.patch.ymlthat caused load failure
v0.1.0
- Initial release
- Style-locked editing: AI modifies text while preserving original layout
- Native render mode: pdf-lib direct draw, zero browser dependency
- CJK font auto-detection and embedding
- Overflow handling: shrink / clip / wrap / reject
- Glossary global substitution
- Three relayout templates: academic / mobile / briefing
How It Works
Original PDF ──▶ Extract text + styles ──▶ AI generates edits ──▶ Overlay draw back to PDF
- Extract: pdfjs reads text content from each page, recording position, font, size, and color for every word
- AI edit: The extracted text is sent to DeepSeek. AI returns only the text fragments that need changing
- Overlay draw: pdf-lib covers old text with a white rectangle at the original position, then draws new text at the same spot with the same font
No browser needed. No Chromium download. Pure JavaScript.
License
Links
More in this category
tt-a1i/archify#integrations/deepseek-harness★ 77520
Generate validated, self-contained interactive architecture, workflow, sequence, data-flow, and lifecycle diagrams from repositories or system descriptions.
dream-num/dsh-univer-office★ 466
Give DeepSeek Harness a real office environment. Univer Office Plugin brings spreadsheets, docs, slides, canvases, relational tables, and more into one runtime — with connected data, validation, versioned changes, and isolated worktrees for multi-agent collaboration.
PerryLink/dsh-industry-research★ 209
Deterministic industry research reports for DeepSeek Harness — company and industry research flows produce structured, verifiable reports from staged evidence.
HuanLinOTO/dsh-plugin-mineru★ 46
Expose MineRU document parsing tools to the model.
PolinniZhong/dsh-knit★ 46
Lists the Markdown documents, images and video that already exist anywhere in the session workspace in the DSH sidebar, ranked by relevance to the current conversation: recent messages are matched locally against document title, summary and body with IDF weighting, with no model calls and no network. Because the list is scanned from the workspace instead of remembered, restarting DSH or starting a new session does not empty it. Images and video preview in place, with relative-path images resolved and video streamed over HTTP Range. A references bar under the preview header shows which documents cite the one being previewed and which it cites, with one click to jump between them. The same ranking is exposed to the agent as a knit_docs tool, which returns the most relevant documents along with the passage that matched in each, where one is found.
kw78/dsh-office-tools★ 26
Workspace-safe Office tools for agents: create/read Word, create/read/update Excel, and create/read PowerPoint decks with PNG/JPG/GIF image placement.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.