dsh-plugin-scaffold
English | 中文
A minimal, runnable DeepSeek Harness (dsh) plugin scaffold. It registers one model-facing tool (hello) on the shared ctx.tools service and proves the full load path — plugin resolution → Loader mount → tool registration → model call — with the smallest possible surface.
It is an external/community plugin: it does not live inside the deepseek-harness monorepo, and it is built against the published npm packages (@deepseek-ai/dsh-tools, @deepseek-ai/dsh-llm, @deepseek-ai/cordis). This is exactly the contribution model the project encourages — see CONTRIBUTING.md, which currently does not accept external PRs but welcomes ecosystem plugins tagged dsh-plugin.
What the tool does
The hello tool takes a name and returns structured JSON:
{ "greeting": "Hello, World!", "cwd": "/path/to/cwd" }
It exists to verify plumbing, not to do real work. Use it as the starting template for a real capability (file access, web fetch, shell, schedule, …).
What you can build from here
This scaffold is one plugin shape — a model-facing tool. DeepSeek Harness is built so that everything is a plugin, so the same load path unlocks many other extension points. Pick a direction and replace the hello tool with the real behavior:
| Direction | What it does | Example |
|---|---|---|
| Data lookup tool | Model calls a tool, you fetch an API and return JSON | weather, exchange rates, stocks, GitHub |
| Database tool | Run a validated query against your data | read-only SQL, internal dashboards |
| File / workspace tool | Read, write, summarize project files | custom grep, bulk rename, code stats |
| External service bridge | Wrap a REST/GraphQL/CLI API for the model | translate, OCR, send email, CI trigger |
| Event listener | Observe agent/* and tools/* events and react |
auto session titles, guardrails, usage logging |
| Context injection | Add durable context to every model request | agent.inject() with project/time/environment facts |
| Model provider | Register a new adapter on ctx.llm |
local Ollama, OpenAI-compatible endpoints |
| Human command | A /command that runs without a model turn |
ctx.commands, e.g. /deploy |
| Background work | Long-running or scheduled tasks | ctx.jobs, polling, reminders |
| Policy / sandbox | Restrict fs/shell/subprocess access | approval gates, allowlists |
| UI card | Customize how a tool renders in the Web UI | presentCall / presentResult, diff/terminal cards |
| Self-modification | Let the agent inspect and mount its own plugins | official web-cordis example |
For working references, see the official examples/: web-schedule (durable reminders), mcp-memory (external memory via MCP), web-cordis (the agent edits its own plugin tree), headless-agent (one-shot tasks). The extension map lives in docs/architecture.md.
Each shape still follows the same pattern this scaffold demonstrates: a name/inject/Config/apply module whose registrations are effects that unwind on unload.
Project layout
src/index.ts # the plugin: name / inject / Config / apply (function plugin, no default export)
scripts/verify.ts # load-path verification via ctx.plugin() (real dsh-tools runtime)
scripts/verify-loader.ts # load-path verification via Cordis Loader + cordis.yml (the real dsh boot path)
cordis.yml # opt-in overlay that inserts the plugin row into a dsh composition
verify.cordis.yml # self-contained Loader composition used by verify-loader.ts
Requirements
- Node.js
^22.19.0 || >=24.0.0 - A
dshinstallation that can resolve the published@deepseek-ai/*packages - pnpm (for development)
Develop
pnpm install
pnpm build # tsc -> lib/index.js + lib/types
pnpm test # vitest: export shape, registration, call, unload rollback
pnpm verify # ctx.plugin() path: mounts real dsh-tools + plugin, calls `hello`
pnpm verify:loader # Loader path: boots verify.cordis.yml through Cordis Loader, calls `hello`
Both verify scripts assert a non-error result and exit non-zero on failure. The vitest suite covers the plugin export shape, tool registration and canonical value, invalid-argument rejection, and effect rollback on unload. CI runs all four on Node 22 and 24.
Load it into dsh
Pass the overlay to dsh web (or dsh headless):
dsh web --patch "$PWD/cordis.yml"
The overlay inserts one row. Use a relative path to the built entry so the Loader resolves it against the config directory, independent of package installation:
- insert:
- id: dsh-plugin-scaffold
name: './path/to/lib/index.js'
cordis.yml in this repo ships that relative form. In the Web UI, ask the model to "call the hello tool with my name" to see it work.
Bare name resolution (what "publish a plugin" really means)
The Cordis Loader resolves bare specifiers (dsh-plugin-scaffold, @deepseek-ai/*) from its own module location, not from the launch directory. So a bare name: dsh-plugin-scaffold only resolves if the package is installed into the dsh installation tree's node_modules (e.g. npm install -g dsh-plugin-scaffold so it sits beside the Loader, or into the profile's node_modules). Two reliable options:
- Publish to npm, install globally — then the bare name resolves from the Loader's location.
- Use a relative/absolute path to the built
lib/index.js— always resolves against the config file location.
For a persistent install, add the same insert block to $DSH_HOME/profiles/<name>/cordis.patch.yml (one profile) or $DSH_HOME/cordis.patch.yml (every profile), per the web-schedule example. Do not copy over an existing file — it may already contain unrelated patches.
Notes on the published @deepseek-ai/* packages
This scaffold depends on the npm-released versions (0.1.0-rc.6), not the monorepo workspace versions. If a future release changes the defineTool / ToolRuntime contracts, update peerDependencies/devDependencies here to match. The plugin is intentionally dependency-light: only @deepseek-ai/cordis (types + Context), @deepseek-ai/dsh-tools (defineTool + ctx.tools), @deepseek-ai/dsh-llm (ContentBlock, type-only), and @deepseek-ai/schemastery (Config schema).
Verifying inside the monorepo
If you clone deepseek-harness to inspect the real runtime, note that installing the full workspace pulls large optional provider binaries (Claude Codex SDK, mermaid for the website) that can time out on slow networks. This scaffold's verification does not need them: the published @deepseek-ai/dsh-tools package is self-contained.
No comments yet. Be the first to write one.