Repository navigation
Releases: 555bbbAAA/dsh-purge
Release list
v1.3.4
修掉一个让「应用内更新永远装不上」的根因:host 收到 shutdown 后不退出。
与上一版本 v1.3.3 的对比
| 维度 | v1.3.3 | v1.3.4 |
|---|---|---|
| 应用内更新 | 点「安装并重启」报 Host did not complete graceful task teardown |
正常安装并重启 |
| host 退出时机 | 关完插件后靠事件循环自然结束(20 个插件的活句柄让它永不退出) | 回完 shutdown-complete 立即 process.exit(0) |
| 补丁总数 | 76 条 | 77 条(新增 #89) |
| 面板计数 | 70/71(#89 因目标 key 不对被误报 skipped) | 71/71(新增 desktop-host 目标 key) |
新增补丁 #89 DESKTOP_HOST_EXIT_AFTER_SHUTDOWN
dsh-desktop-host 的 stop() 在 shutdown(0) + 回话 + process.disconnect() 之后没有 process.exit(),靠事件循环自然结束。装了多个插件后,插件留下的活句柄(推理引擎子进程、WebSocket、定时器、SQLite 连接)让事件循环永远不空转,host 进程不退。
外壳侧 exitsWithin(exited, 1e4) 只等 10 秒,超时即 SIGTERM 并判「非优雅退出」,抛:
desktop update: Host did not complete graceful task teardown
(exit null, signal SIGTERM, shutdown acknowledged true, graceful deadline exceeded true)
此时 install() 流程中断,dshPurgeHandoffDesktopUpdate 一次都不会执行,安装器根本没被调起。
#89 在那两行之后插入 process.exit(0):插件已 dispose 完、外壳已收到确认,三个判据(exitCode=0 / shutdownCompleted=true / graceful=true)全部满足,安装继续。
新增 targetFiles key:desktop-host
desktop-shell 只解析到 app/lib/main.js 一个文件,而 #89 的目标在另一个包(dsh-desktop-host/lib/index.js)。不给它独立 key,状态判定读不到 markers,会把已打上的补丁误报成 skipped。
实测
在 0.2.1-rc.3 主机上走通完整应用内更新,升级到 0.2.1-rc.5:
- 升级前:
exit null / signal SIGTERM / graceful deadline exceeded true - 升级后:安装器正常调起,宿主版本变为
0.2.1-rc.5(buildCommitd4db512a) - 补丁 71/71,0 待应用,
update_phase=active
已知限制
- rc.5 下
dsh-better-sidebar与dsh-dream-skin停在 pending(waiting for service: webRuntime),不影响宿主运行,但侧边栏与皮肤可能不生效。 - 6 条 na 补丁(#28 #30 #31 #64 #65 #76)是目标包本机不装,属正常。
安装
dsh plugin --profile desktop add file:<path>/dsh-purge-1.3.4.tgz
v1.3.3
修面板打开慢:打开一次原来要发 48 次请求、约 1.07 MB,现在降到 12 次、约 200 KB。
与上一版本 v1.3.2 的对比
| 维度 | v1.3.2 | v1.3.3 |
|---|---|---|
| 打开面板的请求数 | 12 轮 × 4 接口 = 48 次 | 6 轮,update / override / own-servers 只在首轮拉 |
| 网络查询 | 每轮都去 GitHub 查 tag,冷启动 2.7 秒 | 首轮查一次,后端另有 30 秒短缓存(1373 ms → 0 ms) |
| 提示词正文 | 68 KB 每轮白拉 | 只在首次初始化文本框时拉,省约 750 KB |
| 设置页那一节 | 每次开合拉全量 19 KB,只用版本号一个字段 | 改 ?lite=1,315 字节 |
| 补丁分组渲染 | 每次轮询都重新分组 + 排序 + 算 tally | 按补丁状态签名缓存,状态没变直接复用 |
新增
invalidateUpdateCheckCache():点「检查更新」或切换通道后清短缓存;checkUpdate({ force: true })可绕过。
已知限制
- 30 秒缓存意味着刚发新版后最多 30 秒内面板可能仍显示旧结果;手动点检查更新即可立刻刷新。
- VM 上尚未实测这一版的流畅度改善;改动只在主机做过接口计时与缓存基准。
安装
dsh plugin --profile desktop add file:<path>/dsh-purge-1.3.3.tgz
v1.3.2
适配 DeepSeek Harness 0.2.1-rc.5,并修掉应用内更新报 desktop update: task inspection timed out 的根因。
与上一版本 v1.3.1 的对比
| 维度 | v1.3.1 | v1.3.2 |
|---|---|---|
| 宿主兼容 | 声明 0.2.1-rc.3 | 声明 >=0.2.1-rc.3 <0.3.0,rc.3 / rc.4 / rc.5 实测锚点全命中 |
| 官方更新窗口判据 | 只认自己的 restarting 标记与 restart.log | 增加「官方 pending 安装包版本 ≠ 当前宿主版本」,官方更新器不写我们的标记也能识别 |
| settle 与更新器抢事件循环 | updateBusy 只查标记 + tasklist | 先查 pending(只读目录与 JSON,不 spawn),再查 tasklist;点更新时 settle 立即让路 |
| 判据健壮性 | 无 | update-info.json 剥 BOM;JSON 坏时回退扫 pending 目录里的 *.exe 文件名 |
0.2.1-rc.5 兼容性核查结论
- 补丁目标文件 49 个,上游 rc.5 改到 0 个。
- 两棵干净树(rc.3 与 rc.5 各 42 个包)逐补丁比对,锚点与文件数 delta 全为 0。
- rc.5 的五处实质改动(
reasoningText()剥离<signature>、reasoning Body Slot 的 ownerProps 由text改为rawText/displayText、会话视图页签按 88px 估算决定是否挂 tooltip、mcpresources/list先查 serverCapabilities、commit 号变更)没有任何一条补丁触碰。 - 桌面外壳五条(#45 #46 #82 #83 #84)按顺序施加到 rc.5 的
lib/main.js,产出 520,975 字节,与 rc.3 上打完的结果完全一致。
已知限制
- VM 上尚未实测「远程更新 1.3.1 → 1.3.2」;发布前只在主机侧做了静态与单测验证。
desktop update: task inspection timed out的另一半成因(host 事件循环被同步 IO 按住)无法在插件侧完全消除;本次只保证「官方安装窗口内插件不写盘」,settle 之外的重活仍需等用户点应用。- 三个 rc.3 起不兼容的第三方插件(
@wingsky-1/dsh-mcp-manager0.2.8、@anionex/dsh-vision-toolkit0.1.46、dsh-workbuddy-connect0.7.x)与本插件无关,不要给 allow-version。
安装
dsh plugin --profile desktop add file:<path>/dsh-purge-1.3.2.tgz
装完确认 dsh.profile.bundles 首位是 dsh-purge,再重启宿主。
v1.3.1
1.3.1
优化插件运行流畅度。
与上一版本 v1.3 的对比
| 维度 | v1.3 | v1.3.1 |
|---|---|---|
| 状态查询开销 | 每次请求都重算 76 条补丁的目标文件 | gatherState 缓存 15 秒、targetFiles 缓存 10 秒,应用开始时自动失效 |
| 首屏 | 打开面板要等一次完整计算(约 2 秒) | 先取 lite(仅顶部数字与状态),再拉全量补丁表 |
| 前端轮询 | 1s / 1.5s / 0.4s / 1.2s 多档 | 3s / 5s / 1.2s / 3s,内容未变不重绘 |
| 启动预热 | 无 | 启动后 1.2s 与 5s 各预热一次缓存 |
功能、界面与补丁表均未变化。
安装
npm pack 得到 dsh-purge-1.3.1.tgz → 解到 profiles\desktop\node_modules\dsh-purge
并把 dsh.profile.bundles 的首位设为 dsh-purge
v1.3
1.3
以 1.2.12(实测能完整走通官方升级的那一条线)为基线重建,并补三处时序保护。
与上一版本 v1.2.12 的对比
| 维度 | v1.2.12 | v1.3(本版) |
|---|---|---|
| 官方升级路径 | #45 接管:插件归位 asar 后交还官方安装器 | 不变(保留 #45,这是慢机器也能装成的前提) |
| 安装空窗期 | 无保护:宿主退出到安装器起来之间,任何 relaunch / 换包 / 杀进程都会让 NSIS 判「程序正在运行」 | 新增 inOfficialInstallWindow():命中期间不排换包、不拉起宿主、不杀进程 |
| 状态口径 | 只有 applied / sealed / blocked_at | 新增 update_phase:active(正常)/ dormant(官方安装中)/ needs-reapply(宿主已升级,等点应用重打补丁) |
| 开机自愈时机 | 启动后 4 秒开始 reapply(写 70 个文件) | 延后到 120 秒,并在触发时再查一次相位;这期间「一打开就点更新」也不会撞超时 |
| 远程检查 | 默认开启 | 默认关闭,只有面板手动触发才请求远端 |
实测过的完整流程(VM,0.2.1-rc.2 → 0.2.1-rc.3)
① rc.2 上点「应用」→ 打补丁 + 换包,applied.json 记 host_version=0.2.1-rc.2
② 打开后立刻点「更新」→ 宿主能及时回话 → 进入安装流程 → 官方装 rc.3 → 自动拉起
③ rc.3 上点「应用」→ 解包 + 68 条补丁 + 换包,host_version=0.2.1-rc.3
(安装器清空的 resources\runtime 由 preflight 与 Startup 守卫补回)
已知限制
- 官方更新器在极慢的机器上仍可能报
task inspection timed out;此时用「退出 dsh → 直接跑 pending 安装包 → 补 runtime → 拉起」这条确定性路径 - 换包观察者依赖 schtasks / WMI 起进程,会话 0 或权限受限环境可能不落地,失败会写
asar-swap.log - 自动更新检查默认关闭,需要在面板手动触发
安装
npm pack 得到 dsh-purge-1.3.tgz → 解到 profiles\desktop\node_modules\dsh-purge
并把 dsh.profile.bundles 的首位设为 dsh-purge
v1.2.12
一句话:把 1.2.7–1.2.12 这几轮合并发布(对外版本号 1.2.12),主题是「状态可判定、启动无窗、红队写入安全」。
与上一版本 v1.2.6 的对比
| 维度 | v1.2.6 | v1.2.7 |
|---|---|---|
needs_extract |
依赖 sealedAsarHandoff() 取 asar 路径,全新密封安装时返回 null → 恒为 false,面板显示成 0/0 · na 76 |
改为从宿主 process.execPath 推 resources 目录,只看磁盘事实(app.asar 在、app\package.json 不在)。实测密封 true / 解包后 false |
| 开机自愈与「应用」抢写锁 | 自愈先写、用户点的应用被排队到超时,界面只看到「处理中 → 读取失败」 | ①「asar 在 + 解包树也在」时自愈直接跳过(settle.skip 记录原因)②apply 拿不到锁立刻返回 busy:「宿主正在做启动自愈写入,请等 10~30 秒后再点一次」 |
| 换包启动方式 | 换包观察者用 WMI 直接拉 powershell.exe,会分配控制台窗口(「第一次点应用弹出一个空白命令行」) |
改为先写 .vbs(sh.Run …, 0, False)再用 wscript //B 拉起;三条启动路径(助手 / watcher / 置顶)现在统一无窗 |
| 诊断日志 | apply 入口、settle 跳过、busy 分支都走 log(cfg, …) —— 只在 verbose 打控制台,文件里一条没有 |
全部改走 purgeLog,落盘到 %TEMP%\dsh-purge-desktop.log:[apply.enter]、[apply.busy]、[settle.skip] |
| 宿主真实版本 | 面板只能显示注册表 DisplayVersion(安装器不重写它,永远显示旧版本) |
/status 新增 host_version_real(读宿主 app\package.json),侧栏清洗页版本号右边显示「宿主 0.2.1-rc.x」徽标 |
| 应用阶段提示 | 只有一句「处理中…正在解包 / 换包」 | 按 apply_progress.phase 分开显示:正在解包(约 40~90 秒)/ 正在写补丁 / 正在换包并重启 |
| 状态字段语义 | needs_extract / initialized / pending_reason 三个字段并存,容易互相矛盾 |
/status 新增统一结论 blocked_at:none / needs_extract / needs_swap / broken_no_tree / unknown(旧字段保留兼容) |
| 解包标记 | PS1 与进程内两条路径写的时间戳格式不同 | 统一为 yyyy-MM-ddTHH:mm:ss.fffZ |
| 红队演练台 B1 | 证据图先落盘再 INSERT;UNIQUE(file) 撞车会留下孤儿图、甚至覆盖同名旧证据 |
写盘前记下原状,INSERT 失败时回滚(原来没有就删、原来有就写回原字节)。单测实测:同名换内容 → 抛 UNIQUE constraint failed: shot.file → 文件仍是第一次的 51 字节 |
| 红队演练台 B2 | schema.js 每次开库都 DELETE FROM stage,用户自建的 stage 会被反复删掉 |
只在 has('stage','attck')(确实是旧结构迁移)时清理一次 |
| 红队演练台 B3 | importBundle 的 scan_run 在 BEGIN 之前提交,导入失败会留一条假「已完成」扫描 |
移进事务内 |
| 红队演练台 B4 | 报告里的可执行命令直接拼明文口令 | 口令换成 <口令:凭据 username> 占位符,明文只留在凭据表与面板 |
这一版验证到的
rc.2 全新密封 → 点应用:解包 ✅ → 70 条补丁 ✅ → 换包 ✅(swap.log kill-round×2 → moved-ok)→ 自动重启 ✅
密封态点应用:[apply.enter] op=apply 落盘 ✅ · 无黑框 ✅ · 无「读取失败」 ✅
/status:plugin=1.2.12 · applied=70/76 · sealed=False · host_version_real=0.2.1-rc.3 ✅
红队 addShot:UNIQUE 撞车回滚 ✅(临时靶标单测)
已知限制
- 官方更新装完
electron-updater不自动拉起新版本,需要手动启动一次。 - 官方安装器不重写卸载注册表
DisplayVersion,判断实际版本请以面板上的「宿主」徽标或app\package.json为准。 - 更新安装期间手动启动 dsh 仍可能让安装器静默失手(
app.asar被重新映射住),插件侧无法阻止。 - 「同版本资产指纹更新」通路仍未在真实环境跑过,等下一次「同号换资产」时验。
安装
ELECTRON_RUN_AS_NODE=1 "<安装目录>\DeepSeek Harness.exe" "<插件目录>\scripts\postinstall.mjs"v1.2.6
一句话:撤掉那条会误报的用户侧提示。
与上一版本 v1.2.5 的对比
| 维度 | v1.2.5 | v1.2.6 |
|---|---|---|
| 面板提示 | 只要 pending 目录里有 5 分钟内的文件,面板就显示「正在安装更新,请稍候再启动 dsh」 |
撤掉这条提示:正常启动时也可能命中,容易误报成「你正在装更新」 |
/status 字段 |
新增 update_installing |
字段保留(仅排查用),界面不再展示 |
| 解包 / 换包 / 更新接管 / 补丁表 | —— | 与 v1.2.5 完全相同,未改动 |
已知限制
- 官方更新装完
electron-updater不自动拉起新版本,需要手动启动一次。 - 官方安装器不重写卸载注册表
DisplayVersion,判断实际版本请以resources\app.asar内package.json为准。 - 更新安装期间手动启动 dsh 仍可能让安装器静默失手(
app.asar被重新映射住)——插件侧无法阻止,只能避免自己再抢文件。
安装
ELECTRON_RUN_AS_NODE=1 "<安装目录>\DeepSeek Harness.exe" "<插件目录>\scripts\postinstall.mjs"v1.2.5
一句话:把 1.2.5–1.2.14 的所有修复合并成这一版发布,重点是「应用不再报读取失败、换包不再弹黑框、更新链路可判定」。
与上一版本 v1.2.4 的对比
| 维度 | v1.2.4 | v1.2.5 |
|---|---|---|
| 点「应用」时的解包 | 同步解包 182MB,宿主事件循环被占满 40–60 秒,/status 无响应,界面报「读取失败」 |
解包改异步(每 200 个条目让出事件循环),期间界面稳定显示「处理中…正在解包 / 换包」 |
| 换包助手启动 | 兜底路径 spawn(powershell, {detached:true, windowsHide:true}) —— detached 会忽略 windowsHide,弹出 powershell.exe 黑框;schtasks 的 /TR 也缺 //B |
三条启动路径(换包助手 / watcher / 窗口置顶助手)全部改为 vbs + wscript //B(窗口样式 0),实测无窗 |
| 官方更新接管 | quitAndInstall(true, true)(静默)→ 旧进程未退时安装器静默 no-op,重启后版本不变且无提示 |
改 quitAndInstall(false, true);归位后先写一行 delegate asar=… app=… 到 %TEMP%\dsh-purge-official-update.log,可判定断在哪一步 |
| 换包是否被排上 | 无日志,只能靠猜 | apply 外层新增 [apply] swap check 与 [apply] swap result 两行,任何分支都留痕 |
| 更新进行中误启动 | 用户此时双击 dsh 会把 app.asar 重新映射住,安装器静默 no-op |
/status 新增 update_installing,面板提示「正在安装更新,请稍候再启动 dsh(现在启动会打断安装)」 |
| 启动自愈 | —— | 检测到更新进行中只记日志 + 提示,不退出(1.2.12 曾尝试 process.exit,会被外壳判成 dsh desktop host stopped,已撤) |
| 补丁表 / 安装位 | 76 条补丁、file:<tarball> 标准位 |
与 v1.2.4 完全相同,未改动 |
这一版实测过的两条链
rc.2 全新密封 → 点应用:解包 ✅ → 70 条补丁写入 ✅ → 换包 ✅(asar-swap.log: start→kill×2→moved-ok)
→ 自动重启 → 面板 70/70、sealed=false
dsh 内升级 rc.2 → rc.3:安装器落地 ✅(asar 182,434,783 字节 = rc.3)
→ 再点应用:rc.3 上同样 70/76 ✅
已知限制
- 官方更新装完
electron-updater不自动拉起新版本,需要手动启动一次。 - 官方安装器不重写卸载注册表
DisplayVersion,判断实际版本请以resources\app.asar内package.json为准。 --repair-baks仍按补丁表里的短名拼归档路径(真实包名带dsh-前缀),映射未修。- 目标确实已不存在的少数补丁(如
#24的 preset 系列)仍计applied,可用target_present=false识别。
安装
ELECTRON_RUN_AS_NODE=1 "<安装目录>\DeepSeek Harness.exe" "<插件目录>\scripts\postinstall.mjs"v1.2.4
一句话:换包 / 重启期间不再把断连当成错误,界面只显示「处理中」。
与上一版本 v1.2.3 的对比
| 维度 | v1.2.3 | v1.2.4 |
|---|---|---|
| 点「应用」后的界面 | 换包与重启期间后端断连,前端直接弹「读取失败: timeout」,过一会儿又自己好了 | 申请时开 5 分钟容错窗口:窗口内读取失败一律显示「处理中…正在解包 / 换包,完成后会自动刷新,请勿关闭窗口」,并每 2 秒自动重试;窗口外或重启标志消失后才报错 |
| 新增文案 | 无 | 字典键 status.busy(中英) |
| 换包链路 / 补丁表 / 安装位 | —— | 与 v1.2.3 完全相同,未改动 |
已知限制
- 官方更新装完 electron-updater 不自动重启新版本,需要手动启动一次。
- --repair-baks 仍按补丁表里的短名拼归档路径(真实包名带 dsh- 前缀),映射未修。
- 目标确实已不存在的少数补丁(如 #24 的 preset 系列)仍计 applied,可用 target_present=false 识别。
安装
ELECTRON_RUN_AS_NODE=1 "<安装目录>\DeepSeek Harness.exe" "<插件目录>\scripts\postinstall.mjs"
v1.2.3
一句话:把上一版没修干净的 localSha 假值彻底修掉。
与上一版本 v1.2.2 的对比
| 维度 | v1.2.2 | v1.2.3 |
|---|---|---|
| localSha | v1.2.1 只去掉了「无 git 时回落到 stamp」,但 checkUpdate() 里另一处 localRev = gitSha | |
| 其它 | —— | 与 v1.2.2 完全相同,未改动 |