DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
P

dsh-power-button

Power Button

DSH 的独立电源控制:侧边栏电源按钮,带有向上的重启/关机菜单,以及 Windows 关机样式的覆盖层。自带重启和关机引擎(不依赖其他插件),采用 MIT 许可证。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:keyiadiannao/dsh-power-button#c51713526aa8d6ed3fc858aa7111735132026feb
README兼容性版本
Power button in the sidebar footerRestart / Shutdown menuShutdown confirm dialogShutdown progress overlayRestart completed toast

兼容性与来源证明

Power Button 以 dsh-power-button 发布,当前版本为 0.4.34。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/11/2

版本

0.4.34stable
2026/11/2
0.4.33stable
2026/11/2
0.4.32stable
2026/11/2
查看其余 17 个版本收起版本
0.4.30stable
2026/11/1
0.4.24stable
2026/11/1
0.4.23stable
2026/10/28
0.4.15stable
2026/10/22
0.4.12stable
2026/10/7
0.4.9stable
2026/10/7
0.4.6stable
2026/10/3
0.4.4stable
2026/10/3
0.4.3stable
2026/10/2
0.4.2stable
2026/10/2
0.4.1stable
2026/10/2
0.3.0stable
2026/10/2
0.2.6stable
2026/10/2
0.2.5stable
2026/9/30
0.2.3stable
2026/9/30

相关插件

正在加载相关插件…

最新版
0.4.34
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 12
周下载
0
最近提交
2026/11/2
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
0.2.1stable
2026/9/11
0.2.0stable
2026/8/20

相关插件

继续浏览 ui-customization 分类下经过校验的插件。

Client Ui Skill Explorer@linxin666/dsh-client-ui-skill-explorerDSH 技能中心:按来源(bundled / project / user / custom / runtime)浏览已加载的技能,在 Web GUI 面板中启用或禁用、创建和删除技能。Client Ui Git Graph@linxin666/dsh-client-ui-git-graph外部 dsh Web GUI 插件:空会话 Git 分支选择器和 Git 图,包含实际的主机端 Git 操作与防护,作为 dsh 配置文件包Client Ui Market@linxin666/dsh-client-ui-marketWorkshop 浏览卡片:浏览来自 dsh-market.com 的皮肤、宠物和社区插件,并在 GUI 中安装(资源安装到 DSH 主目录,插件通过可选的插件管理器安装)。Client Ui Web Ui Settings@linxin666/dsh-client-ui-web-ui-settings用于 dsh 设置页面的 Web UI 插件组:一个承载 dsh-web 系列插件启用开关和配置表单的一级设置分区。

README

dsh-power-button

English | 中文

A self-contained power & lifecycle controller for DeepSeek Harness: a sidebar power button with a Restart / Shutdown menu and a full-screen transition overlay. The restart engine is built in — no third-party dependencies.

Developed with DeepSeek AI assistance; reviewed before release.

Features

  • Sidebar power button in the footer action slot, theme-aware and styled to match the adjacent Settings trigger.
  • Restart / Shutdown menu with a Windows-style full-screen overlay; the page reloads by itself after a confirmed restart.
  • Self-contained restart engine: a detached .cjs helper takes over relaunching DSH through an ARM → COMMIT → ACK handshake, waits for the old process, the port and the session logs, then relaunches the same invocation in the same cwd. A --port 0 command line is pinned to the port the old process actually bound. In the Desktop app the restart is handed to Electron instead, when that app advertises a restart protocol. No PowerShell, no taskkill.
  • /restart and /shutdown commands, a restart_harness model tool (registration is skipped when another plugin already owns the name), and a read-only restart_status tool for checking whether a restart happened.
  • Localized UI and host notices (zh / en), following the profile's locale.preference.
  • Startup housekeeping: helper logs and scripts, per-restart handshake records, and undelivered notices older than 7 days are pruned from the runtime directory.

Screenshots

① Sidebar power button — theme-aware footer entry.

Power button in the sidebar footer

② Restart / Shutdown menu — two actions, one click away.

Restart / Shutdown menu

③ Shutdown confirm dialog — the default focus sits on Cancel; only an explicit confirm stops the process.

Shutdown confirm dialog

④ Shutdown progress overlay — shows the current stage while the process winds down.

Shutdown progress overlay

⑤ Restart completed toast — after the auto reload, a notice confirms DSH is back.

Restart completed toast

Install

dsh plugin --profile web add "github:keyiadiannao/dsh-power-button#master"

Restart DSH; a power button appears in the sidebar footer. Requires Node ≥ 22.19.

Configuration

Configured through the profile's cordis layer (cordis.patch.yml or the settings UI):

KeyDefaultMeaning
enableModelTooltrueRegister the restart_harness model tool. Set false to keep restart on the GUI button and /restart only.
maxDelayMs5000Upper bound (ms) for the model tool's delayMs. The effective floor is 1000 ms.
restartWakeModequietWhat the session that asked for a restart is told afterwards. quiet stages the notice for its next step without waking anything; notify also wakes that session once it is live, so the model reports the restart without a user message. Neither mode restarts anything on its own.
- id: dsh-power-button
  config:
    enableModelTool: true

How it works

Restart is an explicit ARM → COMMIT → ACK handshake. The old process does not exit until a live helper owns the relaunch; every failure before the ACK keeps the old process running. After spawning the successor, the helper waits up to 180 seconds for readiness. The browser allows a five-minute polling budget for the full restart, including shutdown and preparation. A refused request remains an error even if later health probes fail.

click power → Restart
[host]    POST /api/dsh-power-button/restart
          write the per-restart helper .cjs (0600: it embeds the relaunch argv)
          spawn `node <helper>` detached
[helper]  ARM  → status { stage: 'armed' }
[host]    wait for ARMED (5 s), then write the COMMIT file for this restartId
[helper]  ACK  → status { stage: 'committed' }
[host]    only now: unref the helper, flush live sessions (≤5 s),
          request exit after delayMs with a 15 s watchdog behind it
[helper]  wait for the old PID to exit, the port to free, the session logs to settle
          write the v2 marker, then spawn DSH with the same invocation and cwd
          poll /health until instanceId differs and restart.restartId matches
[client]  reload

Five invariants hold this together:

  • The helper lives outside the process tree (detached, a real .cjs file — a multi-line node -e is mangled by Windows CreateProcess), so terminating DSH cannot kill it mid-flight.
  • Success is confirmed by a per-process instanceId that must change, so a brief outage never fakes it.
  • The launcher's exit channel is read at ctx.get('appExit'), never as a property: it is an optional host service this plugin does not inject, and a property read resolves to undefined — which would skip graceful disposal and hard-kill instead.
  • Exit is bounded end to end, and the bounds are derived rather than duplicated: graceful exit gets a 15 s watchdog, the pre-exit flush cap is 5 s, and the helper's patience for the old PID is computed from both, so they cannot drift into the helper giving up first.
  • The successor's environment is re-read from the registry, not inherited: a process environment is a snapshot from its launcher, so a variable changed with setx or System Properties would otherwise never reach the relaunched instance. The block is composed in the order Windows uses — the inherited block as the base layer, machine values over it, then user values shadowing those — and a REG_EXPAND_SZ value is resolved against the block as it stands at its own stage, so a machine value cannot see a user-only name. That isolation is between registry layers, not a byte-exact replay of how Windows builds the block: names the launcher already carried stay visible at every stage, which is deliberate because some of them — SystemRoot on a real machine — exist only in the process environment. PATH keeps both halves (machine first) and each part is expanded according to its own type before duplicates are dropped. It is read through reg export (UTF-16LE), so non-ASCII values survive on any console code page; the export is a transient file under the harness home that is deleted in the same call, and it inherits that directory's ACL exactly as .credentials.yaml does — the file mode is not a privacy guarantee on Windows. A variable deleted from the registry still cannot be seen, and a directory deleted from a registry PATH survives while the launcher's block still carries it — it cannot be told apart from one a package manager injected at launch, and dropping those would break children that resolve tools by name. Non-Windows platforms keep plain inheritance.

Shutdown posts /api/dsh-power-button/shutdown and stops without relaunching. It is irreversible, so the button and /shutdown both open a confirm dialog; the model is never given shutdown.

Desktop

The Desktop application runs the Host as a child of its Electron shell, so exiting that child invokes the app's crash recovery and replaying its command line yields a Host without a window or its original IPC channel. Two cases, decided by what the host advertises:

  • Host advertises a restart protocol (DSH_DESKTOP_RESTART_PROTOCOL in the Host environment, IPC channel connected): the plugin writes the restart marker, flushes live sessions, and asks the shell to restart; Electron owns the relaunch. If the shell does not take over within 20 seconds, the request fails, the transition is released, and the button works again.
  • Host advertises nothing (every released DeepSeek Harness so far): restart and shutdown are refused with 503 and reason: "desktop-unsupported"; no helper or exit is scheduled. Use the application's Quit menu or tray action, then reopen it — closing the main window can leave the app running in the tray.

Making the first case available means changing DeepSeek Harness itself, which is outside this plugin's boundary; the steps are in docs/desktop-restart-protocol.md.

Safety

  • Destructive POSTs go through the deployment's own browser-trust fence and authentication via ctx.connection.requestRejection — the call the host's /api route uses. /api/dsh-power-button/* is longer than the official /api prefix, so longest-prefix matching never routes these requests through that fence; delegating keeps them under the operator's real policy, including LAN authorities derived from an all-interface bind and any trustedHosts / --trusted-host declaration.
  • On a host with no connection service (a profile without the web bundle) the plugin falls back to its own rules: Host must be a loopback authority or one the host declared, plus the cross-site and full-authority Origin checks. That fallback is narrower than the official fence and can only refuse; it does not provide browser-session authentication.
  • A refusal answers with a stable reason code and logs the observed Host / Origin / sec-fetch-site / remote address. host-fence and not-authenticated mean the deployment decided, not this plugin.
  • An at-most-once latch rejects duplicate transitions, so a concurrent second POST gets 409.
  • The model tool's delayMs is floored at 1000 ms — the model cannot kill the process before its own turn settles.
  • The restart marker is consumed on boot, so a later ordinary launch never misreports a restart. Command lines are redacted in logs; helper and marker files are written 0600, the runtime directory 0700.

Restart awareness

Three audiences, deliberately not one:

  • The UI shows a localized "Restarted" toast. The restart identity stays on /health for the process's whole life; acknowledging the toast clears only the pending flag.
  • The session that asked gets a notice shaped by restartWakeMode — Agent.inject() when quiet, Agent.followup() when notify. Only a restart with a recorded causal session gets one: a GUI click records none and is never attributed to whichever conversation happens to be open. At most one notice per session is queued and it is deleted once delivered.
  • Every other session can call restart_status, which reports whether a restart happened, its id, stage, the instances involved, timings, who asked, and whether the running process is the instance that restart produced.

The plugin never appends a model-visible event and never forges a turn: awareness is handed to the Agent API, whose inject() durably stages an agent/inbox/spliced record for the next legitimate step. Delivery is once per notice in normal operation; a crash between the inbox write and the deletion can repeat it, and the notice text is written so a repeat is harmless.

/health also reports appExit: "available" | "missing" — whether the launcher-provided exit channel actually resolves here, which turns a delayed restart into a one-request diagnosis. Both exit paths log the pre-exit flush tally (live / fulfilled / rejected / timedOut), so a refused or partial durable write is visible afterwards instead of looking like a clean exit.

Development

pnpm build            # tsdown: host + client bundle (committed to lib/)
pnpm typecheck        # tsc --noEmit over src
pnpm typecheck:tests  # the root tsconfig excludes tests/
pnpm test             # vitest: unit + process-level acceptance
pnpm check            # all of the above, in order

CI runs both typechecks, tests and build on Windows, Ubuntu and macOS, gates that the committed lib/ matches a fresh build byte for byte, and checks the pnpm pack tarball; a separate Linux job repeats everything on Node 22.19, the floor engines.node declares. tests/restart-runtime.spec.ts runs the exact helper the host generates as a real process against real TCP ports - the relaunch chain, no relaunch without COMMIT, bounded spawn retries, a stale instance refused, and the failure diagnoses - and the suite isolates DSH_HOME, so it never touches your real ~/.dsh.

License & Attribution

MIT. The "detached helper relaunch" idea follows anweat/dsh-restart (MIT); the implementation is independently written (real .cjs file, no PowerShell, dynamic port), no code copied.

Thanks to @qq1131909103: PR #8 established that the Desktop Host belongs to the Electron shell, which is why this plugin refuses power actions there instead of spawning a competing Host, and what docs/desktop-restart-protocol.md is built on.