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

应用自控 cheng-wj/dsh-app-control

DeepSeek Harness
cheng-wj14 天前有提交已提供中文文档扫描:含敏感能力

在会话内重启、更新并体检桌面应用

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add cheng-wj/dsh-app-control
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

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

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件
查看扫描证据(共 18 处,展示前 13 条)
  • 读取本地文件
    src/index.js:171
    const buf = readFileSync(file)
  • 读取本地文件
    src/index.js:189
    if (!existsSync(file)) return
  • 读取本地文件
    src/index.js:192
    const text = readFileSync(file, 'latin1').replace(/ /g, '\n').replace(/ /g, '\r\n')
  • 写入本地文件
    src/index.js:193
    writeFileSync(file, text, 'latin1')
  • 写入本地文件
    src/index.js:203
    mkdirSync(SCRIPT_DIR, { recursive: true })
  • 写入本地文件
    src/index.js:204
    mkdirSync(LOG_DIR, { recursive: true })
  • 读取本地文件
    src/index.js:207
    if (!existsSync(from)) continue
  • 写入本地文件
    src/index.js:209
    copyFileSync(from, to)
  • 执行外部命令固定命令
    src/index.js:218
    const child = spawn('powershell.exe', [
  • 读取本地文件
    src/index.js:268
    const files = readdirSync(LOG_DIR)
  • 读取本地文件
    src/index.js:271
    .filter((f) => statSync(f).isFile())
  • 写入本地文件
    src/index.js:293
    mkdirSync(LOG_DIR, { recursive: true })
  • 写入本地文件
    src/index.js:294
    writeFileSync(join(LOG_DIR, 'apply-trace.log'), trace.join('\n') + '\n', 'utf8')
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 插件:在模型侧重启、更新、检查 DeepSeek Harness 桌面应用(Windows)

README

由 DeepSeek 最新模型翻译生成
dsh-app-control 在 DSH 会话内向模型提供三个工具,用来重启、更新和体检 DeepSeek Harness 桌面应用本身。 核心卖点不是「能重启」,而是重启不会把自己弄死。这件事比看上去难:从 DSH 会话里重启 DSH,要同时躲开四个独立的坑,每一个都会让应用关上之后再也打不开,而且不报错。 三个工具 | 工具 | 作用 | 是否中断会话 | | dsh_status | 列出 DSH 进程、python 记忆桥、已装插件版本(对比 registry 最新版) | 不中断,只读 | | dsh_restart | 干净地关闭全部 DSH 进程,等待退出,然后自动重新打开 | 中断 | | dsh_update | 装指定版本插件(绕开 already-installed bug),然后重启 | 中断 | 模型可以直接调用。典型对话: 「帮我重启 DSH」→ 调用 dsh_restart 「dshmarket 更新失败了」→ 先 dsh_status 看版本,再 dsh_update 传 dshmarket@1.66.44 「记忆插件好像没生效」→ dsh_status 看 python 桥接进程在不在 安装 dsh plugin add 底层就是 pnpm add,它接受 Git 仓库、本地目录和 tarball。
展开完整文档(README 剩余 1 节)
dsh-app-control

在 DSH 会话内向模型提供三个工具,用来重启、更新和体检 DeepSeek Harness 桌面应用本身。

核心卖点不是「能重启」,而是重启不会把自己弄死。这件事比看上去难:从 DSH 会话里重启 DSH,要同时躲开四个独立的坑,每一个都会让应用关上之后再也打不开,而且不报错。

三个工具

| 工具 | 作用 | 是否中断会话 |
| dsh_status | 列出 DSH 进程、python 记忆桥、已装插件版本(对比 registry 最新版) | 不中断,只读 |
| dsh_restart | 干净地关闭全部 DSH 进程,等待退出,然后自动重新打开 | 中断 |
| dsh_update | 装指定版本插件(绕开 already-installed bug),然后重启 | 中断 |

模型可以直接调用。典型对话:

「帮我重启 DSH」→ 调用 dsh_restart 「dshmarket 更新失败了」→ 先 dsh_status 看版本,再 dsh_update 传 dshmarket@1.66.44 「记忆插件好像没生效」→ dsh_status 看 python 桥接进程在不在

安装

dsh plugin add 底层就是 pnpm add,它接受 Git 仓库、本地目录和 tarball。本插件不发布到 npm,仓库本身就是分发渠道。

方式一:从 Git 安装(推荐)

dsh plugin --profile desktop add git+https://github.com/cheng-wj/dsh-app-control.git

装的是仓库快照。已实测:从 Git 装下来的 assets/dsh-tools.bat 仍是 399 对 CRLF(.gitattributes 保住了它),三个工具正常注册。

缺点是升级要重新 add 一次。

方式二:本地目录链接(改代码立刻生效)

dsh plugin --profile desktop add link:"C:\Users\ZY\Documents\deepseek-harness\默认工作区\dsh-app-control-plugin"

link: 装的是目录软链,改完 src/index.js 重启就生效,不需要重新打包。适合自己开发调试。

方式三:tarball 离线分发

从 Releases 下载 .tgz,或从源码自行打包:

dsh plugin --profile desktop add "C:\path\to\dsh-app-control-1.0.0.tgz"

适合拷给别人、内网分发,或者留个可归档的快照。

五个坑(这是本插件的全部价值)

前三个坑在开发过程中都真实触发过,第四个是参数层面的隐蔽 bug,第五个是插件发布层面的坑——它让插件「看起来装好了,其实一次都没跑」。

坑 1:taskkill /T 会杀掉调用者自己

taskkill /IM "DeepSeek Harness.exe" /T /F 里的 /T 会向上遍历进程树。如果调度脚本是 DSH 的子进程,它就是自己的行刑对象:应用被关掉,脚本也被干掉,于是没人负责重新打开。

解法:用 WMI 的 Win32_Process.Create 启动调度器。新进程的父进程是 WmiPrvSE.exe,不在 DSH 树里,/T 打不到它。

$result = ([wmiclass] 'Win32_Process').Create($cmdLine)

坑 2:start "" "app.exe" 不是脱离

批处理里用 start 打开应用,新进程会继承 cmd 的控制台。用户关掉那个小黑窗时,Windows 发送 CTRL_CLOSE_EVENT,Electron 收到后直接退出——表现就是「关掉脚本窗口,DSH 也跟着退出了」。

解法:重开应用同样走 WMI,父进程是 WmiPrvSE.exe,没有共享控制台,关任何窗口都不影响它。

坑 3:.bat 必须是 CRLF(最阴的一个)

纯 LF 的批处理文件不会报错。cmd.exe 对 call :LABEL 是按字节偏移记账的,遇到 LF 只换行不回车时偏移算错,脚本会在中途静默停止:

[1/2] all DSH processes are gone ← 走到这里 [2/2] DSH is running again ← 永远不出现

应用被关掉了,再也没有重开,而且没有任何错误信息。这个坑排查了很久,最后用 A/B 对照确认:内容完全相同、只有行尾不同的两个文件,LF 版停在中途,CRLF 版完整跑完。

解法:ensureCrlf() 在每次运行前按字节统计 CR/LF 数量,不一致就原地修复。

function crlfCounts(file) {
const buf = readFileSync(file)
let cr = 0, lf = 0
for (const byte of buf) {
if (byte === 13) cr++
else if (byte === 10) lf++
}
return { cr, lf }
}

⚠️ 不要用 awk '/\r$/' 检查:它匹配的是字面字母 r,不是回车符,对正确的 CRLF 文件也会报「没有 CR」。只能用字节计数,或者 node。

坑 4:cmd.exe 把 = 当作参数分隔符

把 --delay=5 传给批处理,实际收到的是两个参数:--delay 和 5。只匹配字面量 --delay= 的解析器永远不会命中,选项被静默忽略。

解法:匹配裸 --delay,从下一个参数取值。

if /I "!ARG!"=="--delay" (
set "DELAY=%~2"
shift
shift
goto MAIN_LOOP
)

同一个解析器还负责 --profile,并且在倒计时之前校验包列表非空——否则一个没有包名的 update 会先把 DSH 关掉、什么也不装、再重开一遍。

顺带一个相关约束:WMI 创建的进程不继承调用者的环境变量。所以 DSH_DELAY / DSH_PROFILE 这类环境变量传不进去,选项必须在命令行上显式传。环境变量只作为手动运行 .bat 时的兜底保留。

坑 5:插件「装好了」但 apply() 从未执行(最隐蔽的一个)

现象:dsh plugin add 成功,profile 里能看到依赖,重启后也没有任何报错——但工具一个都不出现。日志全绿。

原因有两层,都会让 Loader 静默跳过整行:

(a)Config 必须是 schemastery Schema,不能是普通对象。

cordis 会把行的 Config 当成校验器调用。普通对象不可调用,apply() 前就抛错,整行被丢弃。

// ✗ 错误:apply() 永远不会被调用
export const Config = { delaySeconds: { type: 'number', default: 10 } }

// ✓ 正确 import z from '@deepseek-ai/schemastery'
export const Config = z.object({ delaySeconds: z.number().default(10) })

(b)peer 依赖必须惰性 + 可选解析。

@deepseek-ai/schemastery 和 @deepseek-ai/dsh-tools 都是 peer,只由宿主提供。用静态 import 时,只要宿主一解析不到,整个模块导入就失败——而 Loader 把「插件导入失败」当作非致命跳过:记一条日志、不建 fiber、其余插件照常工作。于是插件完全隐身。

更麻烦的是 link: 安装:node_modules/dsh-app-control 指向源码目录,裸包名会按源码树解析,而 peer 是 hoist 在 profile 里的,所以恰好解析不到。

// ✓ 惰性 + 可选,再从各 profile 目录兜底解析 let z = null
try { z = (await import('@deepseek-ai/schemastery')).default } catch {
const { createRequire } = await import('node:module')
z = createRequire(join(DSH_HOME, 'profiles', 'desktop', 'noop.cjs'))('@deepseek-ai/schemastery').default
}
export const Config = typeof z?.object === 'function' ? z.object({ /* ... */ }) : undefined

Config 缺失时导出 undefined 即可——cordis 会把行配置原样透传;工具本身不依赖 schema,代价只是少了设置界面。

诊断心法:这类失败在宿主进程里完全不可见。插件应把 apply() 的每一步 writeFileSync 到一个 trace 日志里,否则「工具没出现」和「插件没加载」无法区分。本插件的 trace 在 %DSH_HOME%\dsh-app-control\logs\apply-trace.log。

配置

在 profile 的 cordis.patch.yml 里给这一行加配置即可:

- dsh-app-control:
delaySeconds: 10 # 倒计时秒数,留出取消的余地 profile: desktop # dsh_update 的默认 profile

dsh_restart 和 dsh_update 每次调用也可以在参数里覆盖 delaySeconds,用 0 立即重启。

文件结构

dsh-app-control-plugin/
├── src/index.js # 插件主体:暂存脚本、驱动调度器、注册三个工具 ├── assets/ │ ├── dsh-tools.bat # 调度器:解析参数 → 倒计时 → taskkill /T → 重开 │ ├── launch-detached.ps1 # 经 WMI 脱离进程树启动,CRLF 守卫 │ ├── launch-app.ps1 # 经 WMI 打开应用本体 │ └── run-visible.ps1 # 输出同时打到控制台和日志(UTF-8 无 BOM) ├── cordis.patch.yml # bundle 挂载声明 └── package.json

运行时会把这四个脚本复制到 $DSH_HOME/dsh-app-control/scripts/,日志写到 $DSH_HOME/dsh-app-control/logs/。不写 node_modules(可能只读、升级时被替换),日志也放在插件目录外,所以升级插件不会丢历史记录。

平台

仅 Windows。调度器依赖 taskkill / tasklist / WMI / PowerShell,这些没有跨平台等价物。

在非 Windows 宿主上插件行仍会挂载,工具也会注册,但每次调用都会返回明确错误,而不是悄悄什么都不做。

已知限制

- 会中断正在进行的对话。dsh_restart / dsh_update 关闭应用时,当前会话跟着断。模型被告知要先提醒你保存工作。
- 单实例锁。Electron 的单实例机制会让重复启动落回已有实例,所以不会开出两个 DSH;但也意味着「重开失败」不会以弹窗形式暴露,只能看日志。
- 日志是 UTF-8 无 BOM。早先用 PowerShell 的 Tee-Object 写日志,PowerShell 5.1 下会写成 UTF-16LE,普通编辑器打开每个字符之间都是 \0。现在改用 StreamWriter,明确指定无 BOM 的 UTF-8。

License

MIT
预览分享卡片长什么样 ↓cheng-wj/dsh-app-control
分享 · DeepSeek Harness Hub
cheng-wj/dsh-app-control

在会话内重启、更新并体检桌面应用

这是你的仓库?认领条目

回到顶部