Files
Reactive-Resume/packages/dsh-plugin
Amruth Pillai 65618a82a0 feat/dsh plugin (#3356)
* docs: remove .superpowers

* feat(dsh-plugin): bring the DeepSeek Harness plugin into the monorepo

Moves dsh-plugin-reactive-resume out of its own repository and into
packages/dsh-plugin. It stays a published, public npm package — the only
one here — but now builds, typechecks, tests, and lints under the same
turbo tasks as everything else.

The move pays for itself in the drift guard. Standalone, the plugin kept a
generated snapshot of the tool names scraped from the live server card at
https://rxresu.me, plus a weekly CI job to notice when that snapshot went
stale. Sitting next to packages/mcp, it reads MCP_TOOL_NAME directly, so a
tool rename breaks the prompt guide on the same pull request instead of
days later. The snapshot, the fetch script, and the scheduled job are gone.

packages/mcp gains a ./tool-names export so that import goes through the
public export map rather than another workspace's src.

Also flips autoInstallPeers off. The DeepSeek Harness rc packages declare
peers that are host-supplied and, in one case
(@deepseek-ai/dsh-type-meta), not published at all, so auto-install 404s
the whole workspace. Turning it off drops only optional peers elsewhere;
@neodrag/core was the single hard peer that had been arriving implicitly,
and it is now declared where it is used. Full typecheck and test suites
pass, and pnpm peers check reports nothing new beyond the pre-existing
drizzle-orm range mismatch.

Tests move from test/ to colocated src/*.test.ts and the build output from
lib/ to dist/ to match repository conventions.

* fix(dsh-plugin): ship a bundle manifest and target the current Harness

`dsh plugin add` warned that the package "declares no dsh.bundle — installed
as a plain dependency, not a profile layer", and it was right. Every other
Harness plugin, in-box and third-party, ships a cordis.patch.yml and points
dsh.bundle.patch at it; that declaration is what joins a package to a
profile's bundle stack. Without it the package installed and then sat inert,
and the README's hand-written insert row was a workaround for the gap rather
than the intended way in.

The peer ranges were also a generation behind. They asked for
@deepseek-ai/dsh-mcp-client and dsh-system-prompt at ^0.0.1-rc.1, which
cannot match the 0.1.0-rc.6 a current harness ships, so the plugin could
never have resolved against the thing it targets. Both APIs are unchanged
across the bump — StreamableHttpConfig still takes the same six fields and
PromptSection still takes name/order/text — so this is a range correction,
not a migration.

That bump pays for itself elsewhere. The old generation peer-depended on
@deepseek-ai/dsh-type-meta, which was never published, and working around
that 404 is why merging this package turned autoInstallPeers off for the
whole repository and pulled @neodrag/core in by hand. The new generation
dropped that peer and publishes every other one, so both changes are
reverted and pnpm-workspace.yaml is back to what it was.

Because a bundle patch mounts the plugin the moment it is installed, a
required apiKey would fail config validation and take the profile down
before the user ever had a chance to mint a key. It now defaults to empty
and apply() warns and mounts nothing, matching how dsh-honcho-memory
handles the same problem.

Verified by packing the tarball and installing it into a clean project with
default pnpm settings: it resolves, imports, and reports its exports.
2026-08-18 20:42:42 +02:00
..
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00
2026-08-18 20:42:42 +02:00

dsh-plugin-reactive-resume

Connect Reactive Resume to DeepSeek Harness. Read, create, and edit your resumes and job applications from a Harness session.

Install

dsh plugin --profile <name> add dsh-plugin-reactive-resume

This package declares dsh.bundle, so the profile picks it up as a layer and mounts it automatically. Until you configure a key it mounts nothing and logs a warning, so installing it never leaves a profile unbootable.

Configure

Mint an API key at https://rxresu.me/dashboard/settings/api-keys and export it as RXRESUME_API_KEY — the bundle patch reads that variable. To set it explicitly, or to change any other option, patch the row by id from your profile's cordis.patch.yml:

- id: reactive-resume
  config:
    apiKey: !!js process.env.RXRESUME_API_KEY

Options

Key Default Description
apiKey '' API key from <url>/dashboard/settings/api-keys. Empty mounts nothing.
url https://rxresu.me Origin of your instance. Set this if you self-host.
serverName resume Tool namespace. Tools reach the model as mcp__<serverName>__<rawName>.
toolCallTimeoutMs 60000 Per-tool-call timeout.

Every tool Reactive Resume publishes is exposed. Narrowing that set is not currently possible from a plugin: Harness's ctx.tools.restrict() requires an agent-scoped context, which a plugin context is not.

Self-hosted

- id: reactive-resume
  config:
    apiKey: !!js process.env.RXRESUME_API_KEY
    url: http://localhost:3000

What it does

Bridges Reactive Resume's MCP server into ctx.tools, and contributes a system-prompt section covering the things models get wrong about resume editing: reading before patching, RFC 6902 path construction against the published schema, UUID-keyed section entries, and locked resumes.

You could wire the bridge yourself with a raw @deepseek-ai/dsh-mcp-client row. What you cannot do that way is contribute the prompt section — that is what this package adds.

Development

This package lives in the Reactive Resume monorepo at packages/dsh-plugin, next to packages/mcp — the server it bridges. src/tool-names.test.ts checks every tool the prompt guide names against @reactive-resume/mcp/tool-names, so renaming a tool breaks this package in the same pull request.

pnpm --filter dsh-plugin-reactive-resume test
pnpm --filter dsh-plugin-reactive-resume build

License

MIT