DeepSeek Harness Plugin

magian1127/deepseek-harness-zh_pro

Stars ★ 36 Downloads (30d) 5,093 Category UI Enhancements Added 2026-08-15 npm deepseek-harness-zh_pro

UI enhancement suite for the DSH web client: Chinese locale completion, one-row stats, auto-expanded thinking, chat width, session archiving and delete, plus an optional prompt-injection switch (off by default).

Install

# from npm (prebuilt)

dsh plugin --profile web add deepseek-harness-zh_pro

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:magian1127/deepseek-harness-zh_pro

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 comprehensive enhancement plugin for DeepSeek Harness

语言 / Language: 中文 · English

A comprehensive enhancement plugin for Chinese UI completion, thinking display, session-list controls, service monitoring, and optional model-request localization. Chinese completion applies only to the Chinese interface; all other UI and session enhancements work in both interface languages. Every feature that modifies model requests is an independent explicit toggle and is off by default.

Features

The tables below follow the real top-to-bottom order of DSH Settings → Enhancements, and keep the in-page order inside each group. A sticky action bar holds every change as a draft: press Save to apply and persist everything at once (host fields go out as one atomic commit, which removes most of the per-keystroke stutter), or Revert to drop the drafts.

Chinese completion and model-request localization

Feature Default Description
Chinese completion On Chinese UI only: fixes confirmed leftover English and normalizes terminology, count, and duration formats
Agent-role prompt localization Off Swaps the built-in roles' system prompts for Chinese; locked on a new session's first request, never retrofitted
Tool-description localization Off Localizes official tool descriptions; tool names, parameters, and third-party tools stay unchanged; new sessions only
Injected-context localization Off Turns DSH-injected official context into Chinese, consistent in the GUI and the model request; new sessions only. Covers the runtime-context snapshot (header and body), time readings, workspace-instruction frames, the skill catalog frame, and approval/plan-mode notices
Prompt injection Off Injects the "Injected text" into subsequent requests. The default text is "始终用中文进行推理,并用中文输出你的思考过程。" — always reason in Chinese and write the thinking process in Chinese.

Chat display (collapsible group)

Feature Default Description
Auto-expand latest thinking On Expands the newest streaming thinking block and collapses the one the plugin expanded before
Default expanded lines 20 lines, latest N Shows only N lines before folding, to keep long thinking smooth; range 0–200, 0 for no limit, direction can start from the earliest lines
Expand mode Button mode Button mode reveals lines in batches; scroll mode uses a fixed-height scrolling viewport

Session list (collapsible group)

Feature Default Description
Auto-archive old sessions 7 days Archives sessions idle longer than N days when the New Session view opens (hidden only, logs kept); range 0–365, 0 disables it
Archived-session view On Adds an archive entry on each workspace row: archived sessions show inside the official list's own group, and the row menu can rename, fork, unarchive, or delete
Session delete button On Adds "Delete session" to session menus for both live and archived rows; the log goes to the OS recycle bin with no list restore slot
Session multi-select On Idle rows can be selected for batch delete or archive; running, pending-interaction, and unread-completion rows are not selectable. Batch entries follow the selection, and each workspace row also offers select-all

Web search (collapsible group; search rows first, reader rows after)

Feature Default Description
Smart search button On Shows "Smart search" under the composer; turning it off hides the button and keeps its code from loading. When on, it remembers its state per session, and an off session stops receiving web tools and guidance
Enable multi-engine search On Takes over the web_search backend using the priority list below; off keeps the backend the deployment configured
Results per query 0 (no takeover) 0 keeps the official behavior (8 sources, round-robin merge); N groups results per query and drops cross-query duplicates. The effective count is also capped by the official "Results per search"
Search backend priority DeepSeek Search API → Zhipu → keyless multi-engine Reorder with ▲/▼. Backends are tried in order: not installed, unavailable, or failed falls through, only a total failure reports an error, and a user cancellation never retries. Keyless multi-engine covers DuckDuckGo, Yandex, Bing, and Wikipedia, with Tavily first when TAVILY_API_KEY is set
Tavily API key Empty Enter or clear the key here; saved and effective immediately, no restart

Reader rows (same card, right after the search rows):

Feature Default Description
Enable keyless web reader On Takes over the web_fetch backend using the priority list below; off keeps the backend the deployment configured
Fetch backend priority DeepSeek cloud reader → Zhipu webReader → keyless ring → local fetch Reorder with ▲/▼, same fall-through rules as search. The keyless ring tries Exa → Parallel → Keenable public endpoints; fetching sends the URL to the selected vendor's cloud service and wraps the body in an "external web content (untrusted)" marker. Safety gate: public http(s) only, credentials in the URL and local/private addresses are refused

Plugin sync (collapsible group)

Feature Default Description
Plugin sync Direction follows the current environment Copies installed plugins from the other profile: desktop → web when running the web app, web → desktop in the desktop app. Only the highest version of a package is kept, never downgraded; upgrades uninstall first and reinstall, and a new version that fails to install is rolled back to the previous one. Runs through the official plugin manager with peer checks and rollback

Service monitor (own card, off by default)

Feature Default Description
Service monitor Off Shows local listening services started during the conversation; hover resolves the process and click reveals its location; the left panel shows at most 10 rows per screen and pages when there are more
Workspace panel On Keeps the monitor panel between the session list and Settings
Sidebar monitor tab On Adds a "Service monitor" tab in the right sidebar (entry on the guide page), with per-entry actions to exclude, always watch, or kill the process
Refresh interval 10 seconds Range 2–300 seconds; polling pauses while the page is hidden
Custom watch entries Empty Add, rename, or edit entries that stay visible as online/offline and resolve their process on hover; maximum 100

Chat display, Session list, Web search, and Plugin sync are collapsible groups that start collapsed and remember their open state independently; the Service monitor card folds too. See the behavior contract for full interaction, data, and safety boundaries (Chinese).

Requirements

  • DeepSeek Harness >=0.2.0-rc.2 <0.3.0 (declared as engines.dsh, covering the whole 0.2.x family; 0.1.x and earlier are rejected by DSH's plugin compatibility check); full UI uses web
  • Node.js ^22.19.0 || >=24.0.0

DSH 0.2.1 removed the built-in {{cwd}} prompt variable (the working directory is now supplied by the working-directory service). It rejects the request on any {{…}} reference it cannot resolve, and this plugin is adapted: if a custom deployment keeps Your working directory is {{cwd}}. in personaSuffix / a preset's suffix, the plugin clears that sentence instead of writing it back into the request; and if the prompt-injection text box contains an unresolvable placeholder such as {{cwd}}, that section is kept verbatim (not interpolated) instead of failing the request. See the behavior contract (Chinese).

Installation

# Web GUI
dsh plugin --profile web add deepseek-harness-zh_pro

# Headless mode
dsh plugin --profile headless add deepseek-harness-zh_pro

# Hot-install only into a running Web GUI
npx -y deepseek-harness-zh_pro install --profile web

Bundles are profile-scoped. The headless profile runs only the Host half, with no browser enhancements.

DSH Desktop (the Electron app): supported — same Web application and plugin machinery (desktop Host port 19387). The desktop profile (~/.dsh/profiles/desktop) is owned exclusively by the app; the dsh plugin CLI rejects it by name, and so does this plugin's dsh-zh CLI (--profile desktop). For a link dev install (while the desktop app is not running), edit ~/.dsh/profiles/desktop/package.json:

"dependencies": { "deepseek-harness-zh_pro": "link:<absolute path to this repo>" },
"dsh": { "profile": { "bundles": [ /* keep official bundles, append */ "deepseek-harness-zh_pro" ] } }

then run pnpm install inside the profile directory to materialize the link. Start the desktop app to mount; after source changes run npm run build and restart the app; to uninstall, remove both entries and run pnpm install again.

Syncing plugins between desktop and Web: you do not need to reinstall plugins one by one in both profiles — open Settings → Enhancements → Plugin sync on the side you want to fill in, click "Check differences" to see the list, then "Sync now". The direction follows the current environment automatically: running in the web app it is desktop → web, running in the desktop app it is web → desktop. For the same package only the higher version is kept — if this profile is already at or above the reference it is left alone (never downgraded), and no package is ever left uninstalled. Upgrades are a two-step operation (uninstall, then install) because the official installer refuses to install a package name that already exists in the profile; if the new version fails to install — typically because pnpm's 24-hour minimumReleaseAge holds back a fresh release — the previously recorded version is reinstalled and the row says so. The feature reuses the official DSH plugin manager, so it is equivalent to installing from the desktop app sidebar "Plugins" page, and it inherits the same peer checks and rollback.

Local source development:

pnpm install
node bin/dsh-zh.mjs install --profile web --link $PWD
dsh plugin --profile headless add "link:<project-path>"

TypeScript source build and checks:

pnpm install
npm run typecheck
npm test
npm pack --dry-run --json

src/ contains the only hand-written source; lib/, bin/, scripts/, and the root verification scripts are Git-ignored build artifacts. prepare, npm run build, or prepack generates them as needed, including the classic client script before publishing.

Check each profile independently:

npx -y deepseek-harness-zh_pro status --profile web
dsh plugin --profile headless list

Updating

Re-run the install command to update dependencies and the persistent bundle. Browser-side content (UI, settings page, cards) is hot-swapped by client-hmr, which polls every 500 ms — no page refresh needed after a build.

The host half (lib/*.js) takes effect as soon as the build finishes when developing with a local link:

  • The package watches its own build artifacts and performs a full swap on change: it clears its module-cache entries in both the ESM and CJS layers, re-imports the entry, then rebuilds the Fiber that owns the existing row. No restart, and no disable → enable round trip in the plugin list.
  • Upgrading to the first version that has this capability requires one dsh web restart: the swap code itself still lives in the old module. Builds after that restart get restart-free swapping.
  • Installed (npm, non-link) setups work the same way, though they rarely need it — upgrading goes through the install command.

One distinction worth keeping: disable → enable in the plugin list does not load a new build. It only rebuilds the Fiber and reuses the in-process module namespace; it never re-imports. Do not use it as an update mechanism.

Do not substitute repeated trial-and-error for diagnosis.

Uninstalling

dsh plugin --profile web remove deepseek-harness-zh_pro
dsh plugin --profile headless remove deepseek-harness-zh_pro
# A running Web GUI can also use:
npx -y deepseek-harness-zh_pro remove --profile web

Removal is profile-scoped; short-lived profiles stop loading it on their next invocation, without deleting sessions.

Settings and data

Data Storage
Chinese completion, thinking display, stats, archived-session view, session deletion, session multi-select, service monitor, and the three cards' open state Browser localStorage: deepseek-harness-zh_pro:enhancements
Agent-role localization, tool-description localization, injected-context localization, web search, search backend priority, results per query, keyless web reader, fetch backend priority, prompt toggle/text/target, and auto-archive days DSH settings.yaml, namespace dsh-zh
Optional Tavily API key (when present, search prefers Tavily) DSH credentials: key TAVILY_API_KEY under the refs: section of ${DSH_HOME:-~/.dsh}/.credentials.yaml, or an environment variable of the same name (read on every call, never cached); you can also add or clear it right in the "Web search" settings card (same location; the UI only ever sees a masked hint)

The plugin uploads no data; its only model-tool registration is the web_search tool shell of web search (installed and removed with the toggle, see the feature table). Except for web search and explicitly enabled prompt injection, agent-role localization, tool-description localization, and injected-context localization, no feature modifies model requests; injected-context localization replaces DSH-injected official English text before it enters session history (closing the toggle restores English for new injections, while already-written history stays as official behavior). When web search is on, search queries are sent to the backends in the priority list, tried top to bottom: a backend that is not installed or unavailable is skipped outright, and a failing backend records a fallback diagnostic and falls through to the next one, so one query reaches at most the first few entries. Taking over the selection also writes searchProvider: dsh-zh-web onto the web row through the official settings channel (persisted in the profile patch), and restores the previous value when the toggle turns off or the plugin unloads. Zhipu is hit when that plugin is installed and available (handled by that plugin), the Tavily API when TAVILY_API_KEY is present in credentials (the key travels only in the Authorization header), otherwise the public DuckDuckGo/Yandex/Bing/Wikipedia endpoints; this plugin stores no queries or results, and never writes the key into config, logs, or diagnostics snapshots. The keyless web reader analogously takes over the web row's fetchProvider (writes dsh-zh-web-fetch, restores on off/unload). In the default order, DeepSeek cloud reader and Zhipu webReader are skipped when not installed or lacking a key; the keyless ring walks Exa → Parallel → Keenable (30s per endpoint, a rate-limited endpoint is skipped for 60s); the fetch request's URL is sent to the selected backend (keyless endpoints are public cloud services), the body is wrapped in an "external web content (untrusted)" boundary marker, and this plugin stores neither URLs nor bodies. Chinese completion only applies to the Chinese interface; the other interface enhancements also apply to the English interface. Each model-request feature is controlled solely by its own toggle.

Headless mode has no browser settings page but shares ${DSH_HOME:-~/.dsh}/settings.yaml. Configure the four Host toggles in Web; headless reads the same namespace.

FAQ

Does the prompt turn on automatically? No, it is off by default. Editing the prompt text does not mean injection is enabled.

How do I route search through Tavily? Just type the key into the "Web search" settings card and save — it takes effect immediately, no restart needed. Note that the first install or update of this plugin needs one dsh web restart: the credentials endpoint is new on the host side, and without that restart the card reports "Host endpoint not ready" (the key itself is fine). You can also add a line TAVILY_API_KEY: "tvly-…" under the refs: section of ${DSH_HOME:-~/.dsh}/.credentials.yaml (or set an environment variable of the same name). Once found, search prefers the Tavily API (search_depth: basic; 1 of the 1000 free monthly credits per search) and, when the quota runs out, backs off for an hour and degrades to the keyless engines instead of failing. An environment variable takes precedence over the credentials file, in which case the card's "Clear" is disabled. To conserve credits and use Tavily only when every keyless engine fails, see the Tavily note in docs/behavior.md.

Why does search report DuckDuckGo 触发反爬限流 (HTTP 202)? That is normal for DDG from this IP; the plugin degrades to Yandex/Bing/Wikipedia and aggregates every engine's outcome into the error message. See docs/troubleshooting.md.

Development documentation

License

MIT

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →

Community comments

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