liuke101/dsh-PdfCraft

dsh-PdfCraft

PdfCraft x DeepSeek Harness

待分类dsh-plugin-marketdsh-plugins

dsh-PdfCraft

English · 简体中文

A DeepSeek Harness bundle that puts PdfCraft in DSH's right sidebar and gives the conversation's agent the upstream PdfCraft MCP tools, confined by default to that conversation's workspace.

The workspace file is where the person and the agent meet. The Panel edits the real PDF on disk; the agent edits the same file through pdfcraft-cli; a save made in the Panel is written back under a revision guard, so a change the agent made in the meantime is never overwritten silently.

The bundle installs once and activates as two components: the Web Component serves the Panel, and the CLI Component runs one PdfCraft engine per live agent. They share no runtime state and have separate configuration.

The Embedded App is the unmodified upstream PdfCraft web build. It is served from the profile's own origin, not from a separate server and not from a copy checked into this repository.

What you get

  • A real PdfCraft Panel. The right-sidebar page is an iframe of the upstream web application, with PdfCraft's own menus, toolbars and preferences. This plugin adds no native toolbar of its own.
  • PdfCraft tools for the agent. Each live agent gets the upstream pdfcraft-cli mcp server mounted on its own scoped context, rooted at its conversation's workspace. The default surface is compact; the full catalogue is one switch away.
  • One Workspace Document. The Panel reads a Workspace Document from the conversation's workspace and writes saves back to it. By default, the agent's tools read and write the same directory.
  • Containment. The Panel's Workspace Document routes resolve every requested path to its real path and refuse anything outside the conversation's workspace. By default, the agent's engine runs with the same directory as its --root.
  • No extra service. There is no plugin-owned port, the plugin makes no outbound network requests, and there is no MCP row to configure by hand. The Panel's assets, Workspace Document routes and open channel all live on the DSH profile's own origin.

Components and rows

The bundle patch inserts two Loader rows, and both are active at once:

Row · Module · Owns pdfcraft-web · dsh-pdfcraft (the bare package name) · The Embedded App assets and readiness report, the Workspace Document read and Write-back routes, the binding registry and Push Channel services, the /pdfcraft command, and the pdfcraft_open tool. pdfcraft-cli · dsh-pdfcraft/cli · The per-agent PdfCraft engines and their lifecycle.

The package exposes both entries: exports["."], with exports["./web"] as its alias, resolves to the Web Component (dist/web/index.js); exports["./cli"] resolves to the CLI Component (dist/cli/index.js). Display text is resolved per specifier: locale/*.json titles the bundle and the pdfcraft-web row dsh-pdfcraft, and locale/cli/*.json, exported as ./cli/locale/*.json, titles the pdfcraft-cli row dsh-pdfcraft-cli, each with its own description. The Panel page keeps its own title, PdfCraft.

The Web row keeps the bare package name because the shell's dsh-client-modules reads a package's dsh.client declaration only from a bare Loader row. The Panel's browser half is part of that package, so it activates with the Web row: disabling pdfcraft-web withdraws the Panel page and its routes as well as the command and the open tool. Disabling pdfcraft-cli withdraws only the agent's engines; the Panel keeps opening, reading and writing back. Disabling pdfcraft-web leaves the MCP tools working, because they live in the CLI Component.

Person ── right-sidebar Panel ── iframe ──▶ PdfCraft web build (/pdfcraft/)
                  │                                │
                  │ Host Bridge (postMessage)      │ Save / Open
                  ▼                                ▼
             DSH host  ── /pdfcraft/document ──▶ Workspace Document
                  ▲                                ▲
Agent ── MCP client ── stdio ──▶ pdfcraft-cli mcp ──┘
                                --root <workspace>

Verified environment

This repository is developed and verified on Linux x86_64 with DSH `0.2.1-rc.1` and PdfCraft `0.9.0`. Other platforms are not verified as part of this work.

You need:

  • A DSH web profile (dsh web).
  • pnpm on PATH, because dsh plugin uses it. The install steps below also use git, curl, tar, and either python3 or unzip.
  • Node.js as required by your DSH installation. No build step and no Rust toolchain are needed for this plugin.
  • About 150 MB of disk for the two upstream artifacts.
  • A browser with WebGPU or WebGL2, which the PdfCraft web application itself requires.

1. Download the two pinned upstream artifacts

The plugin ships no PdfCraft code or binaries. Both artifacts come from the PdfCraft v0.9.0 release, not from this repository:

Artifact · Release asset · SHA-256 Command-line engine, Linux x86_64 · pdfcraft-cli-0.9.0-linux-x86_64.tar.gz · cdba2bec4d502d016dd78101a402d07845b708c49d77bc85e0ab640aca65372b Command-line engine, Linux aarch64 · pdfcraft-cli-0.9.0-linux-aarch64.tar.gz · 6a5316da69300fc30cd7355cba1c5a9c307ceb741bcce91ba0c5c835350ca0a2 Command-line engine, macOS universal · pdfcraft-cli-0.9.0-macos-universal.zip · c20b8ced630417d47042ee37282fdb8362a29ebbc0b0bec3f4f635d0e28545f0 Web build, all platforms · pdfcraft-web-0.9.0.zip · eb465508b0623be27b07ef5145c0670c71ddd7791b4541721358b59c7e0a722e

Only the Linux x86_64 command-line engine is verified here; the other rows name the same release's assets for reference. The web build is platform-independent.

Download the two assets for your platform plus the release's checksum file into one directory:

mkdir -p "$HOME/pdfcraft-download"
cd "$HOME/pdfcraft-download"

BASE=https://github.com/storytold/pdfcraft/releases/download/v0.9.0
curl -fLO "$BASE/pdfcraft-cli-0.9.0-linux-x86_64.tar.gz"
curl -fLO "$BASE/pdfcraft-web-0.9.0.zip"
curl -fLO "$BASE/SHA256SUMS.txt"

Verify what you downloaded

SHA256SUMS.txt is the release's own checksum file, downloaded from the same BASE URL above; it is not a file in this repository. Verify exactly the two artifacts you downloaded, so a missing one fails instead of being skipped:

cd "$HOME/pdfcraft-download"
CLI=pdfcraft-cli-0.9.0-linux-x86_64.tar.gz
WEB=pdfcraft-web-0.9.0.zip

grep -E "  (${CLI}|${WEB})\$" SHA256SUMS.txt | sha256sum --check

If you downloaded a different command-line asset, set CLI to that filename from the table above. On macOS, use the system tool for the check half:

grep -E "  (${CLI}|${WEB})\$" SHA256SUMS.txt | shasum -a 256 -c

You should see both downloaded artifacts named with OK:

pdfcraft-cli-0.9.0-linux-x86_64.tar.gz: OK
pdfcraft-web-0.9.0.zip: OK

A missing file says FAILED open or read; a corrupt file says FAILED. Either one stops the command with a non-zero exit status. Delete the bad file and download it again; do not install it.

The SHA-256 values in the table above are the same values in SHA256SUMS.txt from v0.9.0, repeated here so the pin is visible without a network request.

2. Install the command-line engine and the web build

If you already have a pdfcraft-cli you trust, skip the CLI extraction below and point cliPath at it; the web build has no substitute. Otherwise, put pdfcraft-cli on PATH:

cd "$HOME/pdfcraft-download"
tar xzf pdfcraft-cli-0.9.0-linux-x86_64.tar.gz
mkdir -p "$HOME/.local/bin"
install -m 755 pdfcraft-cli-0.9.0-linux-x86_64/pdfcraft-cli "$HOME/.local/bin/pdfcraft-cli"
"$HOME/.local/bin/pdfcraft-cli" --version

The last command starts with pdfcraft-cli 0.9.0. If $HOME/.local/bin is not on your PATH, note the absolute path; you will set cliPath to it below.

Put the web build where the bundle expects it by default:

cd "$HOME/pdfcraft-download"
export DSH_HOME="${DSH_HOME:-$HOME/.dsh}"
mkdir -p "$DSH_HOME/pdfcraft"
python3 -m zipfile -e pdfcraft-web-0.9.0.zip "$DSH_HOME/pdfcraft/"
mv "$DSH_HOME/pdfcraft/pdfcraft-web-0.9.0" "$DSH_HOME/pdfcraft/web"
test -f "$DSH_HOME/pdfcraft/web/index.html" && echo "web build in place"

python3 -m zipfile is used so the command does not depend on unzip; unzip pdfcraft-web-0.9.0.zip -d "$DSH_HOME/pdfcraft/" works too if you have it. The bundle patch defaults webBuildDir to $DSH_HOME/pdfcraft/web (that is ~/.dsh/pdfcraft/web when DSH_HOME is unset), so this location needs no configuration.

If you would rather keep the extracted folder under its release name, skip the mv and set webBuildDir to $DSH_HOME/pdfcraft/pdfcraft-web-0.9.0 in the configuration step.

3. Install the bundle

Install this package into the web profile:

git clone https://github.com/liuke101/dsh-PdfCraft.git
cd dsh-PdfCraft
dsh plugin --profile web add "$PWD"

Run this while DSH is not running, or restart dsh web afterwards. dsh plugin initializes the profile if it does not exist yet, adds the package, and selects the bundle.

The command installs the package as a profile dependency. The repository is the distribution; this package is not published to npm.

Start DSH and check the result:

dsh web
  • The plugin list shows the bundle and the pdfcraft-web row as dsh-pdfcraft, and the pdfcraft-cli row as dsh-pdfcraft-cli. Both rows must be active for the Panel and the agent's tools together; each works without the other.
  • The right sidebar has exactly one PdfCraft entry: through DSH-better-sidebar when that plugin is active, otherwise through DSH's own right sidebar. The plugin never registers both.
  • Typing /pdfcraft in a conversation opens the Panel in Standalone Mode.
  • The agent's tool list contains tools named mcp__pdfcraft-__; the hash is derived from the workspace and stays stable for it.
  • If the web build is missing, the Panel says so with the file to fetch and the directory currently configured. This is covered in When something is missing.

4. Configure it

The defaults work when the web build is at $DSH_HOME/pdfcraft/web and pdfcraft-cli is on PATH. To change anything, add an override for the row you are changing in the profile patch:

$DSH_HOME/profiles/web/cordis.patch.yml

- id: pdfcraft-web
  name: dsh-pdfcraft
  config:
    webBuildDir: !!js dshHomePath('pdfcraft', 'web')
    openTool: true
    maxDocumentBytes: 33554432
- id: pdfcraft-cli
  name: dsh-pdfcraft/cli
  config:
    cliPath: /home/me/.local/bin/pdfcraft-cli
    staticRoot: ''
    compactSurface: true

A profile patch replaces the row's whole `config` object, so include every field you want to keep on that row. The example shows every field of both rows. All values except cliPath are the shipped defaults; cliPath points at the path installed above. Change only the values you need, but keep webBuildDir (or set it explicitly) on the Web row rather than dropping it by accident. Configuration changes apply when the profile reloads; restart DSH if your profile does not use HMR.

Migrating from the old single row

Before 0.2.0 the bundle inserted one row, pdfcraft, with all six fields. The split moves each field to the component that owns it:

Old field on pdfcraft · New row · New field webBuildDir · pdfcraft-web · webBuildDir openTool · pdfcraft-web · openTool maxDocumentBytes · pdfcraft-web · maxDocumentBytes cliPath · pdfcraft-cli · cliPath staticRoot · pdfcraft-cli · staticRoot compactSurface · pdfcraft-cli · compactSurface

A profile patch that still targets - id: pdfcraft matches no row after the upgrade. The Loader warns patch: entry "pdfcraft" not found and skips that patch, so the bundle runs with its defaults until you move the overrides to the two rows above. The old row's values do not carry over automatically.

Every configuration field

Each row validates only its own fields; a field placed on the other row is not read by it.

Web Component (`pdfcraft-web`)

Field · Type · Default · What it does webBuildDir · string · $DSH_HOME/pdfcraft/web via the bundle patch; the schema default is an empty string · Directory containing the extracted web build's index.html. An empty or wrong value leaves the component mounted and makes the Panel show the missing-build card naming what to fetch. The web build is never downloaded by the plugin. openTool · boolean · true · Register the person's /pdfcraft command and the agent's pdfcraft_open tool. Set to false to withdraw both and drop any open request that has not reached the browser yet; an already-open Panel is untouched. maxDocumentBytes · integer · 33554432 (32 MiB) · Largest Workspace Document the Panel will open or save, in bytes. A larger read or Write-back is refused with a message naming this limit. This does not limit the agent's tools, which use the upstream engine directly.

CLI Component (`pdfcraft-cli`)

Field · Type · Default · What it does cliPath · string · pdfcraft-cli, resolved through PATH · The pdfcraft-cli executable the agent's engine runs. Use an absolute path to pin a specific release. An empty value falls back to pdfcraft-cli. staticRoot · string · "", meaning each conversation's own workspace · Pin every agent's engine to this absolute directory instead of its conversation's workspace. It must exist; otherwise no engine starts and the warning names the root. This gives up per-conversation isolation; the Panel stays confined to the conversation workspace either way. compactSurface · boolean · true · Offer the compact agent surface: a small core set of tools plus tool_search and tool_call, which reach every remaining tool. Set to false to expose the full catalogue, at a much higher context cost.

The three fields on each row are that row's whole configuration surface. The bundle patch points the Web row's webBuildDir at the Harness home; if you install the package by some other route, set it explicitly.

5. Use it

The person

Open the Panel from a conversation:

/pdfcraft                          open in Standalone Mode
/pdfcraft reports/quarterly.pdf    open a Workspace Document

The command runs without the model, so it costs no model round trip. A path may be relative to the conversation's workspace or absolute inside it. Paths are resolved with symlinks followed and refused when the real file is outside the workspace.

The Panel is one page titled PdfCraft, not one page per Workspace Document. A later open for the same conversation replaces the Workspace Document that conversation is bound to; it does not add a second page. Opening the Panel brings the right column forward, because DSH offers no quiet open.

A bound Panel uses the Host Bridge, so PdfCraft's own Save writes back to the Workspace Document. The host replaces the file atomically. This includes Save As: while a Workspace Document is bound, a save in the Panel is a Write-back to that bound file, not a new workspace file. Before writing, the Revision Guard compares the revision the Panel loaded with the revision the read route recorded and with the file's current SHA-256. If the file changed underneath the Panel, the save is refused and the Panel offers two explicit choices:

  • Reload shows the current file and discards the Panel's pending save.
  • Overwrite anyway writes the Panel's bytes over the current file.

There is no silent last-writer-wins. The agent is not locked out, though: its tools write the file directly, so the guard protects a Panel save and does not stop the agent from changing the file after the Panel loaded it. The Panel reads a Workspace Document when it loads it; a change made by the agent afterwards is not pushed into the open frame. It becomes visible when the Panel loads the Workspace Document again, for example after reopening it, or when a save reports the conflict.

Standalone Mode is the Panel with no Workspace Document bound. The Host Bridge is off, so the plugin receives nothing from the Embedded App. Saves from that state go through the browser's normal download path and never reach the workspace. See the limitations below.

The agent

The agent opens the Panel with the pdfcraft_open tool:

{ "path": "reports/quarterly.pdf" }

The path is optional; omitting it opens Standalone Mode. A later open for the same conversation replaces the bound Workspace Document. If the conversation is not on screen, the open waits and is delivered when it is; the result reads Opened … when the browser received it immediately and Queued … when it waits for the conversation to come on screen.

The agent's PDF tools are the upstream PdfCraft MCP tools under the namespace for the workspace. They belong to the CLI Component: disabling pdfcraft-cli withdraws them, and the Panel keeps working.