Tools & Capabilities

dsh-web-file-preview

wingsky-1/dsh-plugin-hub/packages/dsh-web-file-preview · ★ 32

wingsky-1

Preview conversation file links in the web UI (images / text / Markdown / highlighted code / git diff) — click a link to open a preview modal instead of the desktop opener; loopback-fenced routes with weak ETag/304 caching and DOMPurify sanitization.

License
MIT
Added
2026-08-21
Maintenance
active
Install kind
github

No manifest check is available; listing does not imply compatibility or security review.

安装

dsh plugin --profile web add github:wingsky-1/dsh-plugin-hub#path:/packages/dsh-web-file-preview

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. Maintenance status: limited maintenance
  2. Quick navigation
  3. Before you start
  4. Version support (rc only)
  5. Individual install vs. bundle: pick ONE
  6. Per-plugin security boundaries
  7. Quick start
  8. Install plugins (add)
  9. Access and verify
  10. Plugin list
  11. Configuration and maintenance
  12. Uninstall plugins (remove)
  13. Update plugins (update)
  14. Verification and troubleshooting
  15. Upgrade notice and repair: a historical session will not open (mcp-catalog)
  16. Detailed reference
  17. Capabilities in detail
  18. @wingsky-1/dsh-notifier
  19. @wingsky-1/dsh-provider-usage
  20. @wingsky-1/dsh-lan-proxy
  21. @wingsky-1/dsh-mcp-manager
  22. @wingsky-1/dsh-verify-isolated
  23. Pin a version (@version)
  24. Without a global dsh install
  25. Related projects
  26. Development and architecture
  27. Contributing
  28. License

npm CI License

简体中文 | English

Maintenance status: limited maintenance

I have temporarily stopped using DeepSeek Harness, and this project is entering limited maintenance. Maintenance will prioritize evaluating reproducible user-reported bugs, especially security, data integrity and core functionality issues. Support for newer upstream rc releases will be considered based on actual demand, the scope of changes and available time; there is no commitment to support every release or to a fixed response, fix or release schedule.

New features, major refactoring and the 1.0.0 rewrite plan are on hold. The repository and published packages remain available. Community fixes, forks and maintenance handover proposals are welcome; PRs will be reviewed as time permits, without a guarantee of prompt merging. Compatibility is defined by this README and the corresponding release notes; alpha compatibility is not promised.

See the maintenance announcement for the full statement and handover discussion.

A collection of plugins for the DSH (DeepSeek Harness) web GUI, distributed via npm: install them all at once as a single bundle, or pick individual plugins as needed.

  • Bundle package: @wingsky-1/dsh-plugins-all — install everything in one shot
  • Individual plugins: @wingsky-1/dsh-* — install only what you need

Quick navigation

Before you start · Quick start · Plugin list · Configuration and maintenance · Verification and troubleshooting · Detailed reference · Development and architecture

Before you start

Version support (rc only)

This plugin set only adapts to rc (release-candidate) releases of DeepSeek Harness — alpha versions are not supported.

  • The official type-layer catalog in pnpm-workspace.yaml is the single version source; each package's peerDependencies is an exact-version projection generated by pnpm catalog:sync-peers. All plugins are pinned to dsh 0.2.1-rc.2; the DSH CLI and every linked/registry plugin must match this exact target; other DSH versions are unsupported
  • npm/pnpm will surface a peer mismatch if your dsh version does not match. Publish/install plugins whose exact peer version matches the target DSH first, then switch the DSH CLI; do not use allow-version to bypass an incompatible runtime
  • Per-release adaptation baselines, breaking changes and upgrade guides live in Release Notes
  • Support for newer official rc releases is evaluated individually, without a commitment to follow every release. Alpha versions are unsupported; versions outside the stated compatibility baseline are not covered by a compatibility promise.

Individual install vs. bundle: pick ONE

Each individual package and the bundle share the same patch id (dsh-*). Install only one way — installing both dsh-plugins-all and any individual package such as @wingsky-1/dsh-lan-proxy results in duplicate same-name entries, and dsh web fails to start with a duplicate error (detectable, not corrupting). To adjust: uninstall the bundle, or uninstall the corresponding individual package, then restart.

Per-plugin security boundaries

  • After installing dsh-lan-proxy, HTTP/HTTPS ports are opened on 0.0.0.0 — every device on your LAN can access your dsh. Uninstall it when not needed.
  • The launch-token auto-injection of dsh-lan-proxy (injectToken) is on by default: any device on the LAN that can reach the port gets full dsh control without a token (equivalent to trusting the entire LAN — bash passthrough to the host). Enable it only on a trusted intranet; turn it off in the settings card on untrusted segments.
  • The stdio subprocesses of dsh-mcp-manager inherit host privileges; only configure MCP servers you trust.
  • Plugin management routes are loopback-fenced (non-loopback → 403, wrong method → 405); requests forwarded through dsh-lan-proxy are trusted by design, not isolated from LAN clients.
  • dsh-notifier owns its configuration files; settings responses mask channel credentials, but notification text and outbound error details are not redacted and may reach logs, history and push services.
  • dsh-provider-usage keeps API keys on the host, never in the browser.
  • dsh-verify-isolated uses a temporary DSH_HOME, independent profile, port and browser instance; this is a verification boundary, not a global security guarantee.

See each plugin README for its threat model and hardening details.

Quick start

Prerequisite: DeepSeek Harness installed and dsh web running normally (for running dsh without a global install, see "Without a global dsh install" below).

Install plugins (add)

# Install everything (recommended)
dsh plugin --profile web add @wingsky-1/dsh-plugins-all

# Or install individual plugins (as needed)
dsh plugin --profile web add @wingsky-1/dsh-notifier
dsh plugin --profile web add @wingsky-1/dsh-lan-proxy

After install / uninstall / update, restart dsh web once (bundle layers are only composed at startup) for the sidebar / settings page to reflect the change.

Access and verify

Restart dsh web, open its startup URL, and check the installed plugin cards under Settings → Plugins. For notifier, send a test notification; for LAN access, follow the LAN proxy access and health checks.

Plugin list

Package What it does Docs Status
@wingsky-1/dsh-notifier Task-event notifications via browser, host toast, Bark and Webhook. README · Architecture Published
@wingsky-1/dsh-provider-usage Multi-provider usage statistics, trends and reports with custom adapters. README · Adapter guide · Architecture Published
@wingsky-1/dsh-lan-proxy LAN HTTP/HTTPS/WebSocket forwarding with TLS, compression and keep-alive. README · Architecture Published
@wingsky-1/dsh-mcp-manager Per-workspace MCP configuration and middleware-based tool access. README · Architecture · Upgrade repair Published
@wingsky-1/dsh-verify-isolated Isolated browser verification for DSH plugin development. README · Architecture Published

Configuration and maintenance

Use the plugin cards under Settings → Plugins; configuration and storage boundaries differ by plugin, so follow its README.

Uninstall plugins (remove)

dsh plugin --profile web remove @wingsky-1/dsh-notifier

Update plugins (update)

# Update a single plugin to latest
dsh plugin --profile web update @wingsky-1/dsh-notifier

# Update the bundle (aggregate + the sub-packages it pulls in) to latest
dsh plugin --profile web update @wingsky-1/dsh-plugins-all

# Update all plugins under the current profile
dsh plugin --profile web update

After install / uninstall / update, restart dsh web once (bundle layers are only composed at startup) for the sidebar / settings page to reflect the change.

Verification and troubleshooting

If a plugin is missing after installation, first restart dsh web. For duplicate entry errors, check that bundle and individual packages are not installed together.

Upgraded DSH from a pre-0.1.5 version and a historical session will not open? Sessions failing with cannot safely transform unclassified message source were hit by the host migration gate on the capability-catalog messages injected by early dsh-mcp-manager builds (the artifact is intact — it simply cannot be read). One command recovers them:

# stop dsh web before applying; logs being written cannot be safely rewritten
node scripts/maintenance/repair-mcp-catalog-sessions.mjs          # dry run: list affected sessions
node scripts/maintenance/repair-mcp-catalog-sessions.mjs --apply  # apply (backup first), then restart dsh web

See the repair guide · issue #723

Upgrade notice and repair: a historical session will not open (mcp-catalog)

Symptom: after upgrading from a pre-0.1.5 DSH, some historical sessions report in the GUI:

历史加载失败:failed to observe session "session-…":
cannot safely transform unclassified message source;
source v0 artifact remains unchanged (raw log: …/session.jsonl.zstd)(gateway/internal)

and session.v3.jsonl.zstd never appears next to the original log — every attempt fails the same way.

Cause (the session is not corrupt): dsh-mcp-manager 0.2.x and earlier wrote the catalog injection message as source.kind = "mcp-catalog", while DSH 0.1.5's session-format v2-to-v3 migration validates surface source.kind against a closed whitelist; a self-invented value is refused and the artifact is (by host design) preserved unchanged. The v3 read path itself does not validate that field, so only sessions written before the upgrade by a host that ran this plugin with catalog injection are affected; new sessions after the upgrade are fine.

Repair: current plugin versions use the host-registered generic source shape (no such message is produced any more). Artifacts already on disk are repaired in place by a one-off script that touches only source metadata, never the body or the event sequence:

# stop dsh web first: a log being written is not guaranteed safe to rewrite
node scripts/maintenance/repair-mcp-catalog-sessions.mjs          # dry run: list affected sessions
node scripts/maintenance/repair-mcp-catalog-sessions.mjs --apply  # apply: .bak-<timestamp> first, atomic write
# restart dsh web and open the session
  • Reads <DSH_HOME> by default (--home <dir> / DSH_HOME overrides it); --session <id> limits it to one session
  • Idempotent; self-checked writes (frame structure + per-line JSON + zero leftover legacy kinds); rollback = restore the .bak-<timestamp>
  • v3 sessions are repaired by default too: a v3 session can carry both kinds (created before the upgrade, written incrementally after it), and a future v3-to-v4 migration with a similar gate would repeat this outage; the rewrite only swaps source metadata, leaving v3 semantics unchanged. --legacy-only limits the run to v0/v1/v2
  • Never writes a v3 artifact: DSH still performs the migration itself for v0/v1/v2
  • Details and evidence: dsh-mcp-manager README and issue #723

Detailed reference

Capabilities in detail

  • Task-event notification center: six task-event kinds (ask / approval / completion / subagent completion / error / turn end) with dual-channel delivery — browser notifications
    • host system toasts — plus Bark / Webhook push to your phone; quiet hours with urgent exceptions, per-channel popup/sound switches (4 tones), and a host capability self-check (/diagnostics)
  • Context-cost-controlled MCP management: project-level MCP is collapsed into the four atomic tools ws_mcp_list / ws_mcp_detail / ws_mcp_search / ws_mcp_call by default, so project-level scale never balloons the context (middleware: all folds global servers into the middleware too, hot-switchable from the settings page); per-working-directory project/global config tiers let each repo carry its own MCP servers without cross-project interference
  • Extensible usage-stats framework: supports multi-provider usage stats and custom data-source adapters; covers daily usage derivation, usage trends, peak/valley countdown, and daily/weekly/monthly reports
  • Engineering-quality backing: every plugin ships smoke assertions (route fences / client contracts), plus build contract + pack checks + full gates run in CI

@wingsky-1/dsh-notifier

Task-event notification center: 6 event kinds (ask / approval / completion / subagent completion / error / turn end), dual channels (browser Notification + host system toast) plus Bark/Webhook push channels (ntfy, Gotify, self-hosted gateways); quiet hours with urgent exceptions, per-channel popup/sound switches (4 tones), and a host capability self-check (/diagnostics with availability and remediation hints)

@wingsky-1/dsh-provider-usage

Multi-provider usage stats framework (v2 adapter contract): persistent capsule + detail panel; DeepSeek official (interval-bookkeeping daily usage derivation + peak/valley countdown badge — works even without an official usage endpoint) and OpenCode Go built in; plug in any data source with a single mjs file, hot-swappable from the settings page; daily/weekly/monthly usage reports (generated via the host llm, including directory and time-of-day observations); API keys stay on the host, never reach the browser

@wingsky-1/dsh-lan-proxy

Access the dsh web UI over LAN: HTTP/HTTPS/WS forwarding + TLS (self-signed / custom certs); dual compression for HTTP (Brotli/gzip adaptive) and WebSocket (permessage-deflate); WS half-open probing keeps mobile backgrounding from going stale; launch-token auto-injection lets LAN devices connect without fetching the token; DNS-rebinding protection + loopback target allowlist

@wingsky-1/dsh-mcp-manager

MCP server manager (stdio / streamable-http): per-working-directory project/global config tiers; all MCP collapsed into 4 atomic tools via the middleware (no model-visible mcp__ direct-call tools); workspace isolation prevents cross-project interference; configs store ${ENV} references only — no plaintext secrets on disk; runtime registration API for other plugins to inject MCP servers; optional MCP call statistics and debug mode (metadata-only, off by default)

@wingsky-1/dsh-verify-isolated

Isolated-environment browser verification skill for DSH plugin development: temp DSH_HOME + independent profile + independent port + independent browser instance (four-way isolation), one-command launch with automatic cleanup; bundled zero-dependency raw-CDP browser driver (snapshot / click / screenshot / eval, with device-viewport emulation), optional isolation audit, first-run dialogs skipped by default

Pin a version (@version)

Omitting @version installs the default latest (recommended). Only when the registry has not synced the latest yet, or the latest has issues in your environment, append @version to the package name — works for both add and update:

# Install a specific version (instead of latest)
dsh plugin --profile web add @wingsky-1/dsh-notifier@<version>

# Update to a specific version
dsh plugin --profile web update @wingsky-1/dsh-notifier@<version>

Without a global dsh install

If there is no global dsh command on the machine, use npx to run it on the fly (dsh plugin calls pnpm under the hood, so pnpm and Node.js must still be installed locally):

# Install the bundle
npx @deepseek-ai/dsh plugin --profile web add @wingsky-1/dsh-plugins-all

# Install an individual plugin (with a version pin)
npx @deepseek-ai/dsh plugin --profile web add @wingsky-1/dsh-notifier@<version>

# Uninstall / update (same shape — swap add for remove / update)
npx @deepseek-ai/dsh plugin --profile web remove @wingsky-1/dsh-notifier
npx @deepseek-ai/dsh plugin --profile web update @wingsky-1/dsh-plugins-all

npx fetches @deepseek-ai/dsh on each run. To pin it, run pnpm add -g @deepseek-ai/dsh (or npm i -g @deepseek-ai/dsh) and then use dsh directly.

Discontinued (do not install; deprecated on npm):

  • @wingsky-1/dsh-skill-explorer (skill-center / skill management) is discontinued; both the plugin package and the bundle package have been removed. A better implementation now ships on the web UI side, @linxin666/dsh-client-ui-skill-explorer (dsh-web-ui repository packages/dsh-skill-explorer), which supports symlink detection, safe handling of linked skills, and more. Use the built-in skill center in the web UI instead.
  • @wingsky-1/dsh-idle-archive (idle-conversation archiving prompt) is discontinued because the community offers more mature session lifecycle-management / archiving implementations (e.g. dsh-session-pruner).
  • @wingsky-1/dsh-subagent-model-inherit (child agents inherit parent-session model and reasoning effort) is discontinued because official dsh-subagent 0.1.2-alpha.2 natively implements resolveChildAgentOptions (child agents inherit the parent session's model / reasoning effort / output-token limit).
  • @wingsky-1/dsh-codegraph (codegraph local code-graph MCP + worktree development discipline) is discontinued: the wrapper tools are tightly coupled to the codegraph CLI version, so the maintenance cost exceeds the benefit.
  • @wingsky-1/dsh-mem0 (mem0 long-term memory system) is discontinued: environment-isolation and related defects were never resolved (#644 / #612), so it no longer meets the bar for continued maintenance.
  • @wingsky-1/dsh-web-file-preview (rewrites "open with the default application" into the built-in right-Sidebar preview) is discontinued: official dsh 0.1.6 routes delivered-file mention clicks to the built-in Sidebar preview, leaving only the card menu's explicit "open in default app" entry, which the plugin rewrote against the user's explicit intent (#840).
  • @wingsky-1/dsh-worktree-sidebar (binds a git worktree to the current session's right-Sidebar file tree) is discontinued: DSH 0.2.1-rc.2 ships a native alternative with different semantics; migration and retirement notes are in docs/migrations/worktree-sidebar.md.
  • @wingsky-1/dsh-decision-gateway (a general advisory decision gateway with JEV as its first provider) is discontinued: there is no direct replacement. The retirement notes cover archival information and leftover cleanup.

Uninstall these packages if you installed them before:

dsh plugin --profile web remove @wingsky-1/dsh-skill-explorer
dsh plugin --profile web remove @wingsky-1/dsh-idle-archive
dsh plugin --profile web remove @wingsky-1/dsh-subagent-model-inherit
dsh plugin --profile web remove @wingsky-1/dsh-codegraph
dsh plugin --profile web remove @wingsky-1/dsh-mem0
dsh plugin --profile web remove @wingsky-1/dsh-web-file-preview
dsh plugin --profile web remove @wingsky-1/dsh-worktree-sidebar
dsh plugin --profile web remove @wingsky-1/dsh-decision-gateway

dsh-memory (project long-term memory) is not included yet; it is planned.

Legacy packages (published historically, no longer distributed):

@wingsky-1/dsh-gzip → merged into @wingsky-1/dsh-lan-proxy (since 0.1.9)

HTTP response compression moved wholesale into lan-proxy (on by default, Brotli/gzip negotiated via Accept-Encoding, SSE streaming exempt, configurable). Uninstall dsh-gzip and install dsh-lan-proxy to get the equivalent:

dsh plugin --profile web remove @wingsky-1/dsh-gzip
dsh plugin --profile web add @wingsky-1/dsh-lan-proxy

@wingsky-1/dsh-opencode-usage → renamed/refactored to @wingsky-1/dsh-provider-usage

Refactored into a multi-provider adapter framework (built-in OpenCode Go, custom data-source adapters supported). The patch id changed from ui-dsh-opencode-usage to ui-dsh-provider-usage and config keys were adjusted — nothing migrates automatically. Reinstall, then re-check your settings in the settings panel (e.g. apiKey, baseUrl):

dsh plugin --profile web remove @wingsky-1/dsh-opencode-usage
dsh plugin --profile web add @wingsky-1/dsh-provider-usage

Both legacy packages are marked deprecated on npm (installing them prints a migration hint).

Plugin row ID migration (v0.2.5 → the next release)

The next release uses dsh-* row IDs. Existing profiles are not rewritten automatically; stop dsh web before migrating.

From a source checkout (maintainers):

pnpm migrate:plugin-rows -- --home "$DSH_HOME"
# Review the dry-run report, then:
pnpm migrate:plugin-rows -- --home "$DSH_HOME" --apply

The tool changes only patch id fields, preserves name, disabled, config and row order, and writes a backup. Users who installed from npm without a source checkout must not run the repository script directly; follow the one-time procedure in the matching release notes. As a manual fallback, back up the profile patch first, change only id: ui-dsh-* to id: dsh-*, leave name and config untouched, and start DSH afterwards.

  • dsh-web-mobile (npm: @dsh-external/dsh-mobile-nav) — DSH web mobile adaptation: auto-collapses the sidebar on narrow screens, opens TOC as a drawer. A lot of this project's development and debugging was done by using it remotely from a phone / tablet.
  • dsh-web-ui — A collection of DSH web UI skins. Learned many good practices from it; it is also the inspiration for DSH plugin development.
  • dsh-routing-suite / dsh-router-standard — Provides the Router Standard agent preset (task-aware reasoning-mode routing: spec / mixed / react) for selecting presets in a session.

Development and architecture

Requirements: Node ≥ 23.6 (tests run TS directly with native type stripping), pnpm ≥ 11.

Build / contract / test / pack commands, directory layout, and host- & client-side coding conventions all live in DEVELOPMENT.md (start at §0); contributing workflow in CONTRIBUTING.md; issue workflow in ISSUE-WORKFLOW.md. Plugin capabilities, architecture, and runtime mechanisms (SVG architecture diagrams and Mermaid sequences) are covered in the architecture documentation (in Chinese).

Plugins were reviewed before being moved into this repository (self-contained build, privacy cleanup, security hardening, complete metadata).

Contributing

See CONTRIBUTING.md: Conventional Commits, feature branch + PR workflow, pre-commit checks (sensitive info / artifact boundaries).

License

MIT