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.

Work Done Bell — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
W

dsh-work-done-bell

Work Done Bell

Rings a Windows system sound (and shows a bottom-right toast) when a DeepSeek Harness session has actually finished all of its work — idle plus no live background job and no running subagent.

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

npx -y @deepseek-ai/dsh plugin --profile web add github:FunctionHookTJU/dsh-work-done-bell#788a7740ccc7610f91dfa298847cfdd13377358b
READMECompatibilityVersions

Compatibility and provenance

Work Done Bell is published as dsh-work-done-bell 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/22/2026

Versions

0.1.0stable
9/22/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/22/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 integrations-communication.

Acp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseAb Publishdsh-ab-publishBrowser-automation publishing tool that logs into and posts to arbitrary websites, in one publishable plugin packageAb Wechat Scrapedsh-ab-wechat-scrape--- description: "The out-of-tree wechat_scrape tool: retrieves WeChat official-account articles, filters promotional blocks, and saves each as a Markdown file, for maintainers of this machine's dsh profiles." kind: "package-reference" ---Remote Web Ui@linxin666/dsh-remote-web-uiScan-to-pair remote access for the dsh web GUI that shares one official interface: a QR beside the settings button pairs phones and PCs into the same Web GUI (a portrait-touch adaptation layer for phones, full desktop on PCs) through one-time tokens and r

README

dsh-work-done-bell

English | 简体中文

A DeepSeek Harness plugin that rings a Windows system sound when a session has actually finished, and shows a bottom-right toast naming the session that finished. A persistent bottom-right switch turns both off, and that preference is stored in a real settings namespace, so it survives a restart.

Why "idle" is not "done"

agent/status -> idle means only that the agent's driver has nothing scheduled. Work routinely outlives it:

  • a run_in_background job keeps running and its settlement opens another turn, and
  • a delegated subagent keeps running while its parent sits idle.

Chiming on raw idle therefore rings two or three times per task. This plugin waits for quiescence: idle and no running/stopping job owned by the session and no running agent owned by it. A 90-second deadline bounds that wait, so a long build cannot swallow the notification; once the deadline has rung, the later true quiescence stays silent for the same episode.

What it sounds like

The reason comes from the durable session log (turn/end), not from a guess:

turn/end reasonSoundToast
completedAsterisk (default notification)yes
blocked (a plugin rejected the step)Asteriskyes
max-tokens (output ceiling hit)Asteriskyes
errorHand (critical stop)yes
aborted — including your own Esc/Stopsilentno
interrupted (crash-orphaned turn)silentno

Simultaneous completions within 2.5 s collapse into one sound, so five sessions finishing together do not stack five players.

Install

Clone the repository, then install it from the directory you cloned into:

git clone https://github.com/FunctionHookTJU/dsh-work-done-bell
dsh plugin --profile web add file:/absolute/path/to/dsh-work-done-bell

then add the package name to the profile's bundle list, in <DSH_HOME>/profiles/web/package.json:

{
  "dsh": {
    "profile": {
      "bundles": ["@deepseek-ai/dsh-base", "...", "dsh-work-done-bell"]
    }
  }
}

(dsh plugin add reconciles that list itself when the installed package declares dsh.bundle. Restart DSH afterwards; nothing else in the composition needs editing.)

Use file:, not link:. The plugin resolves @deepseek-ai/schemastery by walking up from its own directory into the profile's node_modules. A link: install keeps the real path outside the profile and the import fails at load.

Uninstall

dsh plugin --profile web remove dsh-work-done-bell

Remove it from dsh.profile.bundles (which dsh plugin remove also reconciles), then restart. The work-done-bell namespace in settings.yaml is inert once the plugin is gone and can be deleted by hand.

The switch

Bottom-right, always visible: 完成提示已开 / 完成提示已关. It writes work-done-bell.enabled through the settings service, and both halves read it — the host half stops the sound, the browser half stops the toast. The state lives in <DSH_HOME>/settings.yaml, so it survives a restart.

Introspection

There is no model-facing tool, on purpose: @deepseek-ai/dsh-tools is not present in the profile, and a plugin may only import what the profile already carries (ESM resolution ignores NODE_PATH). The state route carries the same information instead:

curl "http://127.0.0.1:3080/dsh-work-done-bell/state?verbose=1"

That returns tracked statuses, the last turn/end reason per session, open quiescence episodes with their deadlines, the last sound exit code, and any error the plugin swallowed. Without ?verbose=1 it returns only what the browser half needs.

Requirements and known limits

  • Windows only for the sound: it plays through [System.Media.SystemSounds], executed via the composed shell service. On other platforms the plugin loads and toasts, but stays silent. Porting it means changing the command in play() to afplay / paplay.
  • The sound command carries a resolved sandbox policy. A confining shell service refuses a command that arrives without one, and the deployment default may be a mode the host cannot enforce at all — on the machine this was built on, workspace-write fails because the Windows ACL runner wants a temp root outside the workspace while the workspace is the user profile, so nothing runs confined and an unpolicied command is simply refused. The policy is therefore resolved per chime for the session being announced (sandboxPolicy.resolve({ session })), which is that session's own authority, never a widening of it. On such a host a session confined to workspace-write stays silent; ?verbose=1 reports the reason in lastError and the resolved mode in lastPolicy.
  • The toast requires an open page; the sound does not.
  • The browser half polls the host every second over /dsh-work-done-bell/state. There is no push channel: the sanctioned direction of package communication is browser -> host.
  • Toasts label the session by a short id, not its title.

Development

Four suites, all runnable with no harness running:

npm test                           # all four
node test/state-machine.test.mjs   # the decision table, on a manual clock
node test/integration.test.mjs     # the plugin inside a REAL cordis app
node test/client-bundle.test.mjs   # the browser bundle's contract
node test/docs-parity.test.mjs     # the two readmes' shared skeleton

integration.test.mjs is the one that matters most: it boots a real @deepseek-ai/cordis application with stub services and asserts that apply runs, that ctx.inject fires, and that both HTTP routes register. An earlier version of this plugin read ctx.get('webServer') once at apply time and called jobs.onJobsChanged unguarded; it looked healthy while registering nothing in production, because a host-composition row mounts during boot, before its services exist.

The suites need @deepseek-ai/cordis, @deepseek-ai/cordis-plugin-timer, @deepseek-ai/schemastery and @deepseek-ai/cosmokit resolvable from the repository. A checkout links them from the harness installation; node_modules is gitignored, so these links stay local:

$repo  = (Get-Location).Path   # this checkout
$dsh   = "$env:APPDATA\npm\node_modules\@deepseek-ai\dsh\node_modules\@deepseek-ai"
$web   = "$env:USERPROFILE\.dsh\profiles\web\node_modules\@deepseek-ai"
New-Item -ItemType Directory -Force -Path "$repo\node_modules\@deepseek-ai" | Out-Null
foreach ($p in 'cordis','cordis-plugin-timer') {
  New-Item -ItemType Junction -Path "$repo\node_modules\@deepseek-ai\$p" -Target "$dsh\$p"
}
foreach ($p in 'schemastery','cosmokit') {
  New-Item -ItemType Junction -Path "$repo\node_modules\@deepseek-ai\$p" -Target "$web\$p"
}

docs-parity.test.mjs guards the two readmes against drift: the same heading skeleton, the same code blocks, the same tables, the same inline technical terms. It cannot judge the prose, but it fails the moment one language grows a section the other lacks.

Layout

lib/index.js      host half  — quiescence state machine, sound, HTTP route
client/client.js  client half — shell.overlay toast stack and switch
cordis.patch.yml  the composition row this package contributes
test/             decision table, real-cordis integration, client + readme contracts

License

MIT