DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Widget — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
W

dsh-widget

Widget

Inline visualization widgets for DeepSeek Harness: render model-authored SVG/HTML fragments as isolated visual cards inside the conversation.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:anneqaq/dsh-widget#126a176044e7e3a01aff7538b43d1adae2317674
READMECompatibilityVersions

Compatibility and provenance

Widget is published as dsh-widget and currently resolves to version 0.1.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/30/2026

Versions

0.1.0stable
9/30/2026

Related plugins

Loading related plugins…

Latest
0.1.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/30/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in ui-customization.

Web App@deepseek-ai/dsh-web-appThe dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)Experimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profileExperimental Web profile layer for Agent Teams Remote and UI pluginsAb Chartdsh-ab-chartChart rendering tool with the browser card that draws its calls, in one publishable plugin packageWhale Widgetdsh-whale-widgetDeepSeek balance whale widget in the bottom-right corner of the DSH Web interface: balance/today’s usage/peak-off-peak pricing, customizable bubble click sequence (text/balance/today/peak-off-peak/image/random phrases and parallel weighted selection), per-line styles and fonts, floating quick editin

README

dsh-widget

English | 中文

Inline visualization for DeepSeek Harness. The model calls one tool with a self-contained SVG or HTML fragment, and the fragment renders as a card in the conversation — diagrams, charts, timelines, comparison tables, annotated layouts — instead of being described in prose.

Install

From GitHub:

dsh plugin --profile web add github:anneqaq/dsh-widget

Or from a local checkout:

dsh plugin --profile web add /absolute/path/to/dsh-widget

Then restart dsh web. The plugin mounts at startup and has no hot reload.

Verify the row landed in the config tree:

dsh --profile web --dump-config | grep -A2 dsh-widget

If pnpm refuses with ERR_PNPM_ADDING_TO_ROOT — the shipped web profile is a single-package workspace, so its root check fires — allow the root write:

npm_config_ignore_workspace_root_check=true dsh plugin --profile web add github:anneqaq/dsh-widget

Remove with:

dsh plugin --profile web remove dsh-widget

This package has no build step — lib/ is committed, so a git install needs no prepare script and no pnpm allowBuilds grant. Installing it runs no build code on your machine.

Use

The model does the work; there is nothing to configure. Ask for something visual and it calls render_widget:

Draw me the request lifecycle for this service as a timeline.

render_widget takes four arguments:

ArgumentRequiredMeaning
htmlyesOne self-contained SVG or HTML fragment.
titlenoCaption above the card; also the frame title.
heightnoFrame height in CSS pixels. Default 420, clamped to 80–2000.
allowScriptsnoEnable scripts inside the fragment. Off by default.

The tool returns only a short acknowledgement. The fragment is not echoed back into the model context — the card reads it from the logged call arguments, so a large diagram costs one copy in the transcript, not two.

How it works

Two halves, one name:

dsh-widget/
├── package.json        dsh.bundle.patch + dsh.client, no dependencies
├── cordis.patch.yml    inserts this plugin's node-half row
├── icon.svg            plugin icon (display metadata)
├── locale/             display metadata: en.json / zh.json
├── lib/
│   ├── index.js        node half  → registers the tool + one prompt section
│   └── client.js       browser half → renders the tool's calls
└── test/               36 tests, no browser and no harness required

Node half registers a plain ToolDefinition and a system-prompt section stating the authoring contract. It holds no state and draws nothing.

Browser half claims the wire name render_widget in the keyed tool.call.toolview slot. Because the slot is keyed by wire tool name, this is additive: it never touches the shipped tool cards.

No build step. The browser half is hand-authored in the window.__ModuleLoader__.load({ id, factory }) lazy-CJS format the shell expects, so the package ships lib/client.js directly — no tsdown, no TypeScript, no bundler. react is the only module it requires, and react is a member of the shell's frozen platform module table.

No dependencies at all. A bundle is loaded through its real path under the profile, so a bare specifier such as @deepseek-ai/dsh-tools resolves only if the package carries its own node_modules. This package imports nothing, which is what lets it install from any directory — including a symlinked development checkout. The input checks the defineTool helper would have generated are written out in lib/index.js instead.

Isolation

The fragment is model-authored, so it is treated as untrusted content. It renders through a sandboxed srcdoc frame, never through dangerouslySetInnerHTML in the app's own DOM.

  • sandbox="" — no scripts, opaque origin. sandbox="allow-scripts" only when the caller asked with allowScripts: true, and never together with allow-same-origin (that pair would let the fragment reach the host document).
  • The frame's CSP is default-src 'none' with img-src data: blob:, style-src 'unsafe-inline', and connect-src 'none'. A stray CDN import or a fetch fails closed rather than silently exfiltrating.
  • Widgets carry no theme state of their own. The frame injects the palette the app is currently painting with, tracked via body[data-ds-dark-theme] so a live theme switch re-renders the frame.

Limits worth knowing

  • The card appears when the fragment argument closes, not while it streams. Reading a half-arrived fragment would render broken markup, so the view shows a placeholder until html is complete — which is usually before the tool result lands.
  • 512 KB per fragment. The markup is stored in the session log, so the ceiling bounds the transcript as well as the wire request.
  • No network in the frame, by design. Inline everything.
  • The card is a tool row, not prose. It renders where the call sits in the turn. Inline-in-the-middle-of-a-paragraph rendering is not available through a public extension point; the tool.call.toolview slot is the sanctioned seam.

Compatibility

package.json declares engines.dsh as >=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0.

The multi-clause || form is required by semver's prerelease rule: a prerelease version only satisfies a comparator set when a comparator in the same [major, minor, patch] tuple carries a prerelease, so a bare >=0.1.2-rc.1 <0.2.0 does not admit 0.1.5-rc.1. Every new upstream prerelease tuple needs its own clause.

Developed and verified against 0.1.7-rc.2. This package deliberately declares no peerDependencies on @deepseek-ai/dsh-*: it imports no host package, and peerDependencies is an enforced install gate (evaluatePluginCompatibility, fail-closed), so declaring one would add a gate without adding truth. engines.dsh is declarative and is what the plugin market reads for its compatibility display.

Development

npm test

36 tests, no browser and no harness required. They run the real projections: the streaming-JSON recovery that decides whether a card renders, the frame's CSP, and the tool contract.

Two checks are deliberate regression guards rather than behavior tests — the module must import nothing, and output.schema must stay closed. Both encode mistakes that fail loudly at harness boot rather than at unit-test time.

License

MIT