🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

电源控制 keyiadiannao/dsh-power-button

DeepSeek Harnessv0.1.0
keyiadiannao5 天前有提交已提供中文文档扫描:含敏感能力

DeepSeek Harness 的自包含电源与生命周期控制插件:侧边栏底部电源按钮 + 上拉重启/关机菜单 +…

37.9/100
综合分
9
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:npm 同名包「dsh-power-button」归属 whichwitchwin/dsh-power-button,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add keyiadiannao/dsh-power-button
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · browser
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-power-button」归属 whichwitchwin/dsh-power-button,装到的可能不是本插件

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-power-button @ 0.1.0
✓Node 引擎要求 >=22.19 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 03:46:30

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 33 处,展示前 23 条)
  • 读取本地文件
    lib/index.js:157
    return JSON.parse(fs.readFileSync(markerPath(), "utf8"));
  • 写入本地文件
    lib/index.js:165
    fs.mkdirSync(RUNTIME_DIR, {
  • 写入本地文件
    lib/index.js:169
    fs.writeFileSync(markerPath(), JSON.stringify(data), {
  • 读取本地文件
    lib/index.js:272
    names = fs.readdirSync(RUNTIME_DIR);
  • 读取本地文件
    lib/index.js:280
    const marker = JSON.parse(fs.readFileSync(file, "utf8"));
  • 删除本地文件
    lib/index.js:306
    fs.unlinkSync(markerFile);
  • 删除本地文件
    lib/index.js:313
    fs.unlinkSync(markerFile);
  • 删除本地文件
    lib/index.js:324
    fs.unlinkSync(markerFile);
  • 读取本地文件
    lib/index.js:355
    names = fs.readdirSync(noticeDir());
  • 删除本地文件
    lib/index.js:364
    fs.unlinkSync(file);
  • 读取本地文件
    lib/index.js:422
    names = fs.readdirSync(noticeDir());
  • 删除本地文件
    lib/index.js:433
    fs.unlinkSync(file);
  • 删除本地文件
    lib/index.js:461
    fs.unlinkSync(file);
  • 读取本地文件
    lib/index.js:577
    const { size } = fs.statSync(file);
  • 写入本地文件
    lib/index.js:578
    if (size > LOG_MAX_BYTES) fs.writeFileSync(file, "", "utf8");
  • 写入本地文件
    lib/index.js:581
    fs.appendFileSync(file, line, "utf8");
  • 写入本地文件
    lib/index.js:711
    fs.mkdirSync(RUNTIME_DIR, {
  • 写入本地文件
    lib/index.js:759
    fs.writeFileSync(file, JSON.stringify(record), { mode: 384 });
  • 执行外部命令来自配置/变量
    lib/index.js:1511
    helper = spawn(process.execPath, [HELPER_FILE], {
  • 发起网络请求
    lib/client.js:590
    fetch(ACK, {
  • 发起网络请求
    lib/client.js:606
    const r = await fetch(HEALTH, { cache: "no-store" });
  • 写入剪贴板
    lib/client.js:982
    navigator.clipboard?.writeText(t("desktopGuide") + " docs/desktop-restart-protocol.md");
  • 发起网络请求
    lib/client.js:1221
    Promise.resolve().then(() => fetch(url, {
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-llm@deepseek-ai/dsh-client-ui-layout@deepseek-ai/dsh-client-ui-sidebar
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

5 张 · 点击查看大图

功能亮点

  • 侧边栏电源按钮
  • 上拉重启关机菜单
  • 自带重启关机引擎

为 DeepSeek Harness 自带电源控制:侧边栏电源按钮配上弹式重启/关机菜单,Windows 关机风格遮罩,自带重启与关机引擎(不依赖其他插件)。

README

由 DeepSeek 最新模型翻译生成
dsh-power-button DeepSeek Harness 的自包含电源与生命周期控制插件:侧边栏底部电源按钮 + 上拉重启/关机菜单 + 全屏过渡动画。重启引擎内置在本插件中,不依赖第三方插件。 由 DeepSeek AI 辅助开发,发布前经人工 review。 功能 - 侧边栏电源按钮:注册到页脚操作位(sidebar.footer.action),主题自适应,外观与旁边的"设置"按钮一致 - 重启/关机菜单 + Windows 关机风格全屏过渡;重启确认后页面自动刷新 - 自包含重启引擎:写一个 detached 的 .cjs helper,经 ARM → COMMIT → ACK 握手接手拉起职责,等旧进程、端口与会话日志都落定后,以相同调用方式与原目录重新拉起 DSH;--port 0 命令行会被固定为本进程实际绑定的端口。
展开完整文档(README 剩余 1 节)
dsh-power-button

DeepSeek Harness 的自包含电源与生命周期控制插件:侧边栏底部电源按钮 + 上拉重启/关机菜单 + 全屏过渡动画。重启引擎内置在本插件中,不依赖第三方插件。

由 DeepSeek AI 辅助开发,发布前经人工 review。

功能

- 侧边栏电源按钮:注册到页脚操作位(sidebar.footer.action),主题自适应,外观与旁边的"设置"按钮一致
- 重启/关机菜单 + Windows 关机风格全屏过渡;重启确认后页面自动刷新
- 自包含重启引擎:写一个 detached 的 .cjs helper,经 ARM → COMMIT → ACK 握手接手拉起职责,等旧进程、端口与会话日志都落定后,以相同调用方式与原目录重新拉起 DSH;--port 0 命令行会被固定为本进程实际绑定的端口。不使用 PowerShell、不使用 taskkill
- /restart 与 /shutdown 命令、restart_harness 模型工具(名字已被其它插件占用时跳过注册),以及只读的 restart_status 诊断工具
- 界面与宿主文案本地化(中文 / English),跟随 profile 的 locale.preference
- 启动清理:自动清理运行目录下超过 7 天的 helper 日志与脚本、每次重启的握手记录,以及尚未投递的通知

截图

① 侧边栏电源按钮 —— 主题适配的底部常驻入口。

侧边栏底部的电源按钮

② 重启 / 关机菜单 —— 两个动作一次到位。

重启 / 关机菜单

③ 关机确认对话框 —— 默认焦点在「取消」,只有显式确认才会停止进程。

关机确认对话框

④ 关机进度遮罩 —— 进程收尾时显示当前阶段。

关机进度遮罩

⑤ 重启完成提示 —— 页面自动重载后确认 DSH 已恢复。

重启完成提示

安装

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

重启 DSH 后生效:侧边栏底部出现电源按钮。需要 Node ≥ 22.19。

配置

通过 profile 的 cordis 层配置(cordis.patch.yml 或设置界面):

| 键 | 默认 | 含义 |
| enableModelTool | true | 注册 restart_harness 模型工具。设 false 则重启仅保留在 GUI 按钮与 /restart。 |
| maxDelayMs | 5000 | 模型工具 delayMs 参数的上限(ms)。有效下限为 1000 ms。 |
| restartWakeMode | quiet | 重启后如何告知发起它的那个会话。quiet 只把通知暂存给它的下一个 step,不唤醒任何东西;notify 额外在该会话变成 live 后唤醒它,模型无需用户发消息即可报告结果。两种模式都不会自行再次重启。 |

- id: dsh-power-button
config:
enableModelTool: true

工作原理

重启是一次显式的 ARM → COMMIT → ACK 握手。旧进程在有一个存活的继任者接手拉起职责之前不得退出——没有任何进程负责拉起是 UI 唯一无法挽回的结果,因此 ACK 之前的任何失败都会让旧进程继续运行。

点击电源 → 重启 [宿主] POST /api/dsh-power-button/restart 写出本次重启专用的 helper .cjs(0600:内嵌拉起 argv) spawn node <helper> detached [助手] ARM → status { stage: 'armed' } [宿主] 等到 ARMED(5 秒),写入本次 restartId 的 COMMIT 文件 [助手] ACK → status { stage: 'committed' } [宿主] 此时才:unref helper → flush 活跃会话(≤5 秒) → delayMs 后请求退出,其后有 15 秒看门狗 [助手] 等旧 PID 退出、端口释放、会话日志落定写 v2 marker,用相同 execPath/argv/cwd 拉起 DSH 轮询 /health 直到 instanceId 变化且 restart.restartId 匹配 [客户端] 自动刷新

四条不变量支撑这套流程:

- helper 必须脱离进程树(detached + 真实 .cjs 文件——多行 node -e 会被 Windows CreateProcess 破坏),否则终止 DSH 时 helper 一起被杀
- 重启成功以每次进程独立的 instanceId 变化为准,短暂离线本身不算成功
- 启动器的退出通道在 ctx.get('appExit') 读取,不能当属性读:它是本插件未在 inject 中声明的可选宿主服务,按属性读会得到 undefined,从而跳过优雅销毁、直接硬杀
- 退出全链有界,且边界是推导出来的而非各写一份:优雅退出 15 秒看门狗、退出前 flush 上限 5 秒,helper 等旧 PID 的耐心由两者计算而来,避免日后漂移成"helper 先放弃"
- 新进程的环境从注册表重新读取,而不是继承:进程环境是启动器创建时的快照,否则用 setx 或系统属性改过的变量永远到不了重启后的实例。环境块按 Windows 的顺序组合——以继承块为底层,系统值覆盖其上,用户值再覆盖系统值——REG_EXPAND_SZ 只对它自己那一阶段可见的变量展开,因此系统值看不到仅用户存在的名字。这种隔离是注册表层之间的隔离,不是逐字节复现 Windows 构建环境块的过程:启动器原有进程块里的名字在每一阶段都可见——这是刻意的,因为其中有些(本机上的 SystemRoot)只存在于进程环境里。PATH 保留两半(系统在前),每段按各自类型展开后再去重。读取走 reg export(UTF-16LE),非 ASCII 值在任何控制台代码页下都能保真;导出文件是 harness home 下的临时文件,同一次调用内删除,它继承该目录的 ACL——和 .credentials.yaml 完全一样,在 Windows 上文件模式并不构成隐私保证。从注册表删除的变量仍然看不到,非 Windows 平台保持纯继承

关机 POST /api/dsh-power-button/shutdown,终止且不拉起。由于不可逆,电源按钮和 /shutdown 都会先弹确认对话框;模型不暴露关机。

安全

- 破坏性 POST 由本部署自己的浏览器信任栅栏与认证保护:通过 ctx.connection.requestRejection 取自宿主,与宿主 /api 路由用的是同一个调用。/api/dsh-power-button/* 比官方 /api 前缀更长,最长前缀匹配不会把这些请求交给那道栅栏;委托给它,才能让端点始终处于运维者真实策略之下——包括 Web 运行时从"绑定所有网卡"推导出的 LAN 权威,以及任何 trustedHosts / --trusted-host 声明
- 宿主没有 connection 服务时(例如不含 web bundle 的 profile),插件退回自己那份规则副本:Host 必须是 loopback 权威或宿主声明过的权威,外加跨站与完整 authority 的 Origin 校验。该副本比官方更窄、只会拒绝,但它不提供浏览器会话认证
- 被拒时返回稳定的 reason 码,并把观测到的 Host/Origin/sec-fetch-site/remote 地址写进日志。host-fence 与 not-authenticated 表示是部署自己的规则判的,不是插件
- at-most-once 锁:并发重复触发会被拒绝(第二次返回 409)
- 模型工具 delayMs 下限 1000 ms——模型无法在自身 turn 结束前杀掉进程
- 重启 marker 在启动时消费即删除,后续普通启动不会误报;命令行日志脱敏,helper 与 marker 以 0600 写入,运行目录 0700

重启后,会话能知道什么

三件独立的事,刻意不合并:

- 界面弹出本地化 toast。进程整个生命周期都通过 /health 的 restart.fromInstanceId、restart.restartId 暴露重启身份;确认 toast 只清 pending 标志,不会抹掉身份
- 发起重启的那个会话收到通知,形态由 restartWakeMode 决定:quiet 用 Agent.inject(),notify 用 Agent.followup()。只有记录了 causal session 的重启才会发;GUI 点击不记录会话,也就不会归到恰好打开着的那个会话上。每个会话最多排队一条,投递后即删除
- 其他会话可调用 restart_status,获取是否发生过重启、restartId、阶段、被替换与新实例、各阶段时间、发起者,以及当前进程是否就是该次重启的产物

本插件从不自己追加模型可见的消息、不伪造 turn:通知交给 Agent API,inject() 会持久登记一条 agent/inbox/spliced 记录交给下一个合法 step 认领。正常运行时每条通知只投递一次;若在 inbox 写入与删除之间崩溃则可能重复,通知文案已写成重放无害。

/health 另外报告 appExit: "available" | "missing"——本宿主里启动器的退出通道是否真的可用,把"重启偏慢"变成一次请求就能定位的问题。两条退出路径都会记录退出前 flush 的计数(live/fulfilled/rejected/timedOut),使被拒或部分失败不再是"看起来像干净退出"。

开发

pnpm build # tsdown:宿主 + 客户端 bundle(提交到 lib/)
pnpm typecheck # tsc --noEmit 检查 src
pnpm typecheck:tests # 根 tsconfig 不包含 tests/
pnpm test # vitest:单元 + 进程级验收
pnpm check # 以上按序全跑

CI 覆盖 Windows / Ubuntu / macOS:两套类型检查、测试、构建、一道"提交的 lib/ 与重新构建结果逐字节一致"的门禁(git 安装直接运行这些产物),以及 pnpm pack 检查发布包确实含 lib/ 与 cordis.patch.yml。另有独立 Linux job 在 Node 22.19(engines.node 声明的下限)重跑全部步骤。

tests/restart-runtime.spec.ts 把宿主生成的那一份真实 helper 当独立进程执行,对着真实 TCP 端口跑,钉住单元测试无法证明的行为:完整拉起链、没有 COMMIT 就不拉起、spawn 重试上限、健康门禁拒绝旧实例、--port 0 落到实际绑定端口,以及失败诊断(marker-write-failed、会话日志仍在变化)。测试通过 vitest setup 隔离 DSH_HOME,不会碰你真实的 ~/.dsh。

License 与致谢

MIT。"detached helper 拉起"的思路参考 anweat/dsh-restart(MIT);实现为独立编写(真实 .cjs 文件、不使用 PowerShell、动态端口),未复制其代码。
预览分享卡片长什么样 ↓keyiadiannao/dsh-power-button
分享 · DeepSeek Harness Hub
keyiadiannao/dsh-power-button

DeepSeek Harness 的自包含电源与生命周期控制插件:侧边栏底部电源按钮 + 上拉重启/关机菜单 +…

回到顶部