Draft polish for the DSH composer: one-click AI polish of the input draft (sparkles button next to send), with optional conversation context and a configurable model channel.
Install
# from npm (prebuilt)
dsh plugin --profile web add @max-null/dsh-draft-polish
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:Max-Null/dsh-draft-polish
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
A draft polish plugin for DeepSeek Harness: a ✨ button left of the send button that calls an LLM to polish your draft, then writes the result back into the composer.
Evolved from the Fractal (OC desktop shell) implementation: OC's serve concurrency bugs made polishing impossible while a session was still generating; DSH's
llmcapability is decoupled from session scheduling, so polishing works mid-generation — and it can carry the current conversation context to help the model understand your intent (the dsh-sidebar-qa ask-with-context mechanism).
Screenshots
The configuration card lives on this plugin's own detail page (DSH 0.1.7 onward, via the plugins.bundle.config slot keyed by package name; settings.plugin.item is occupied by the official settings pages):
Entry: Plugins → @max-null/dsh-draft-polish → the configuration card
| Configuration card |
|---|
![]() |
The shot shows the v0.2.3 form — the entry lived in the settings dialog's left rail then, and moved to the plugin detail page in 0.2.4. Fields and defaults are unchanged; the shot is pending a re-capture at the new entry.
Features
| Capability | Description |
|---|---|
| One-click polish | ✨ button left of the send button; result replaces the draft |
| Works mid-generation | Uses the DSH llm channel, decoupled from agent-session scheduling |
| Conversation context | By default the last 4 messages are attached as background context (configurable, can be disabled) |
| Reuses existing model channel | No separate API key; inherits the current session's channel, or set provider/model explicitly |
| Zero pollution | No session created, no history written — only the draft changes |
| Per-session isolation | Each session's composer is independent; switching sessions mid-polish still writes back to the originating one |
Install
dsh plugin --profile <name> add @max-null/dsh-draft-polish
Or add to the profile's package.json dependencies + dsh.profile.bundles:
- id: draft-polish
name: '@max-null/dsh-draft-polish'
Usage
- Write a draft in the composer;
- Click the ✨ button left of the send button (no-op when empty);
- The polished text replaces the draft automatically (spinner while working);
- Review and send as usual.
Settings
Plugins page → the @max-null/dsh-draft-polish detail page → the configuration card (DSH 0.1.7 onward, registered into the plugins.bundle.config slot keyed by package name). The form reads and writes the host draft-polish settings namespace through /draft-polish/api/config, and Save applies immediately: provider/model channel, contextEnabled, recentWindowMessages (verbatim recent window), backgroundEnabled/backgroundWindowMessages (optional fast-model background compression), temperature, timeoutMs.
Architecture
- Host half (
lib/index.js):/draft-polish/apiroutes (same trust fence as the /api gateway) —sessionQuery.readSurfacereads the session context →llm.streampolishes (DSH channel, independent of session scheduling) → returns the text; thedraft-polishsettings namespace. - Client half (
lib/client.js): registers in theconversation.input.rightslot (the official "before the send button" seat) — reads the draft (the session standard seatuseInput, falling back to owner props) → fetches the host → writes back via the standard-kitinputActions.setDraft; registers theplugins.bundle.configcard keyed by the package name. Channel inheritance reads the session standard seatuseProjection('modelSelection')(hostmodel-selection-projection,next = pending ?? lastUsed). - Context strategy inherits dsh-sidebar-qa: verbatim recent window (anchors the latest state) + optional compressed background (≤3 sentences), newest-first; any failure degrades to context-free polishing.
Permissions & Risks
- Network: the client half talks to the current DSH process only through same-origin relative
/draft-polish/api/*JSON routes (local, no cross-network traffic); the plugin never calls external URLs, never uploads data, and has no telemetry. - External services: polish calls go through the DSH
llmchannel to the model provider you already configured — the plugin holds no API keys and never talks to any model service directly. - Dependencies: zero runtime npm dependencies (the schema library is
@deepseek-ai/schemastery, listed only indevDependenciesand inlined intolib/index.jsat build time); peer deps are DSH official services and react, provided by the DSH runtime. - File system: reads/writes no files; the only persistent state is the
draft-polishsettings namespace (managed by the DSH settings service). - Failure bounds: host API unavailable → error notice, draft untouched; LLM failure → original draft preserved (default 30s timeout); context read failure → degrade to context-free polishing without interrupting.
Development
pnpm install
pnpm typecheck # strict tsc
pnpm test # vitest (host pure functions + component)
pnpm build # tsdown → lib/
SSID Family
This plugin belongs to the @max-null/* family — a set of plugins that together form the SSID (思灵 · Seek Soul in Darkness) desktop experience.
License
MIT
Links
More in this category
Tencent/WeKnora#dsh-weknora★ 32683
Four read-only tools over a WeKnora knowledge base: list knowledge bases, hybrid passage search, reassemble one document's chunks in order, and WeKnora's own cited RAG or ReAct-agent answer with a resumable session id.
superdesigndev/treg★ 4865
Tool catalog for agents: search ~2,600 external endpoints (SEO and SERP, backlinks, social, people and company enrichment, ad libraries, scraping) by the task you want done, read each one's parameters and per-call price, then call it with the credential injected server-side. Ships the skill plus an MCP row that stays disabled until TREG_TOKEN is set.
TencentCloudBase/CloudBase-AI-Toolkit#dsh-plugin★ 1134
Tencent CloudBase backend for DeepSeek Harness — scaffold and deploy full-stack apps from chat, render query results as table cards with paging, sorting and CSV export, preview a deployment on its domain, and call the CloudBase MCP toolset (`mcp__cloudbase__*`) with device-code login.
gitroomhq/postiz-agent#dsh-postiz★ 508
Connects DeepSeek Harness to Postiz over MCP: list connected social media channels, fetch per-platform posting rules, and schedule, draft, or publish posts to X, LinkedIn, Instagram, Facebook, Threads, TikTok, YouTube, Reddit, Bluesky, Mastodon, Discord, Slack, Telegram and more; adds a postiz workflow skill.
EthanYoQ/Invoice-Downloader#dsh-invoice-downloader★ 502
Local IMAP invoice download, OCR, archive, and Excel reimbursement summaries for DeepSeek Harness.
anysearch-team/anysearch-dsh★ 452
AnySearch-powered real-time web and vertical search provider for DeepSeek Harness.

Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.