Repository navigation
Releases: MoonlitDropOfBlood/DSH-Desktop
Release list
v1.10.10
v1.10.9
[1.10.9] - 2026-10-27
修复
- v1.10.8 修复后仍残余的两条错误状态源(切换会话后当前会话的右侧栏展开按钮消失 / 插件 client 重建后窗口控件模式冻结在首帧)。真实现场取证(保留现场、未刷新,Electron 临时 inspector + 全 DPI 原生捕获)确认 1.10.8 的 108px 常量与标记同源方案本身几何正常(右栏收起按钮右缘 1398、金刚键左缘 1412,间隙 14px),错乱来自另外两条独立缺陷:
- ① 版本信号通知死路:
placementStore.setVersion()先写versionModern再调 DOM 兜底通知,而该通知一见版本已到位就早退——权威版本到达后从不通知订阅者。首帧若按 DOM 兜底判定(如干净首帧 = LEGACY),之后即使桥报来 0.1.5+ 版本,placement 也永久冻结,控件模式与避让规则全部错误。修法:拆出独立publish();setVersion()直接发布版本结果(MODERN→LEGACY 方向同样生效),DOM 兜底通知保留原早退(省掉版本落定后的无效全文档扫描)。 - ② 右栏状态标记被隐藏会话钉死:
<html data-dsh-desktop-rightbar-open>原由文档级querySelector("[data-sidebar-right-open]")推导,而核心会保留其他会话的右栏子树(hidden但仍带 open 属性)——现场实测文档中同时存在两个 open 面板、其一属于隐藏会话。切到右栏收起的会话后,隐藏面板让标记恒为真,当前会话的头部展开按钮被display:none持续隐藏(2 秒轮询只是反复算出同一个错误结果)。修法:只统计可见的 open 面板(closest('[hidden], [aria-hidden="true"]') === null,与核心visibleSidebarPane同口径);观察器同时监听data-sidebar-right-open/hidden/aria-hidden,会话切换立即生效,2s 轮询仅兜底插入前赋值。 - 两条修复均不触碰 1.10.8 的 108px CSS 常量、80px 头部避让与标记清理逻辑。
- ① 版本信号通知死路:
内部
- 新增
scripts/test-placement-rightbar.js行为守卫(已并入npm test):从client.js逐字抽取生产函数(PLACEMENT/isModernVersion/createPlacementStore/hasVisibleRightbarOpen)配微型 DOM double 真执行——实现缺失或仍是旧语义都会明确 FAIL,不是拿副本测副本。54 条断言覆盖:版本到达必须切换且恰好通知一次、重复/无效版本不重复通知也不撤销已生效值、DOM 兜底不污染权威值(双向)、可见性语义(仅隐藏 / 仅 aria-hidden / 混合 / 隐藏祖先 /aria-hidden="false"/ closest 抛错上抛)、观察器过滤器三属性齐全。变异验证:把三组旧实现改回去分别 15 / 2 / 6 条断言翻红,门禁非绿摆设。 - 隔离真机动态几何验证:临时 DSH_HOME + 独立端口起真实核心(0.2.1-rc.3),加载本仓库插件产物,无头 Edge + CDP 驱动完整动态链——隐藏 open 面板不置标记(座位保持 28×28 / margin-right 80px)、取消隐藏立即置标记并
display:none(矩形归零)、再次隐藏后座位与 80px 几何恢复、金刚键组全程唯一。 eslint.config.js补齐 Node.mjs脚本的全局声明:scripts/**/*.mjs此前落在 node globals 之外(WebSocket也缺失),全量npm run lint恢复零报错。
v1.10.8
[1.10.8] - 2026-10-24
修复
- 金刚键导致部分 UI 错乱(电脑息屏恢复后 / 插件 client 刷新后发作,按 Ctrl+R 刷新才恢复):金刚键小组件本身一直画得对(固定
top:10px; right:8px,组宽 92px),错乱来自它宣称「右上角被占」的方式——这件事被拆成了三份互不相干的状态:① 小组件 DOM(React 渲染);②<html data-dsh-desktop-corner>在场标记(effect 设置,从不清理);③--dsh-desktop-controls-clear占位宽度(sync()JS 实测小组件宽度后写进<html>的内联 style,而插件的apply()cleanup 会removeProperty掉它)。②③ 因此能互相打架,且坏状态只有整页刷新(Ctrl+R)才能复位——正是本次报障的现象。两种坏法各有一种典型症状:- 占位宽度一丢失 → 核心侧避让规则退化成
calc(var(--dsh-desktop-controls-clear, 0px) - var(--detail-gutter, 0px))=calc(0px − 24px)= 负外边距,把核心自己的按钮往右推进金刚键带。实测量到:右栏打开时,「收起」按钮的margin-right从 108px 掉到 0px,位置 x=1504→1612,与金刚键组(x∈[1546,1638])重叠 26px——按钮被浮层盖住、点击被吃掉(与 v1.10.7 修的那处重叠同源,但触发条件不同:那次是核心自己的留白算错,这次是壳的占位变量丢了)。 - 标记一泄漏 → 核心为一个已经不在屏幕上的小组件继续让路:会话头部 corner 座位永久留着 80px 空洞(那条 80px 常量规则原本没带标记限定),详情操作组被无谓地推走 84px。
- 修法(把状态收敛到一个真源,让坏状态结构上不可能):占位宽度改为样式表常量
[data-dsh-desktop][data-dsh-desktop-corner]{--dsh-desktop-controls-clear:108px}——它与「金刚键在场」标记同源,二者不可能再不一致,也没有 JS 变量会丢;标记随小组件一起摘除(WindowControls的 effect cleanup +apply()的 cleanup 各一次,fiber 死在 React 卸载之前也覆盖到);避让公式再包一层max(0px, …)——万一变量缺失或为 0,退化成「不避让」(按钮组回到核心自己的位置)而不是「往右撞进金刚键」;头部 corner 座位的 80px 规则补上[data-dsh-desktop-corner]限定,没有金刚键时不留空洞。 - 实测对照(Edge 无头 + CDP 复现台,右栏打开态量几何):修复前 cleanup 后重叠 26px;修复后同一步骤重叠 0px、按钮位置不变(x=1504..1532,
margin-right:108px)。标记撤掉后头部座位外边距从 80px 回到核心自己的 -16px(停止让路)。
- 占位宽度一丢失 → 核心侧避让规则退化成
内部
-
新增
scripts/repro-corner-hmr.mjs真机复现台(npm run repro:corner):Edge 无头 + CDP,注入一个仿真 preload 桥(window.dshDesktop,字段与preload.js对齐)让桌面壳的客户端插件在普通浏览器里真渲染出金刚键,然后量几何 / 截图。场景:stale(模拟插件 cleanup 后的半死状态,直接量出与金刚键组的重叠像素)、rebuild(touch 插件client.js→ 核心的 HMR watch stat 到 mtime 变化 → 广播rebuilt帧 → 浏览器端拆掉重建该 client 模块)、offline(CDP 断网再恢复 = 息屏后 SSE 重连)、openbar(右栏开关)。配套scripts/repro-plugin-lifecycle.mjs(npm run repro:plugin-lifecycle)给 profile 里的插件副本插桩,把apply()的进入/退出、WindowControls挂载、占位测量值打到window.console——核心的ctx.logger在渲染进程里不可见,只能这样取证。 -
scripts/test-corner-avoidance.js补四条新不变量(已并入npm test):① 占位宽度不得由 JSsetProperty发布(可丢失的值不能进避让公式);② 标记必须带 cleanup(与小组件同生共死);③ 避让规则永不为负(max(0px, …),变量缺失时退化为 0 而非负外边距);④ 头部 80px 规则必须带[data-dsh-desktop-corner]限定。AGENTS.md §4 与 docs/agents/desktop-ui.md §4 同步补上这条红线与完整推导。
v1.10.7
[1.10.7] - 2026-10-20
修复
- 金刚键与「自动化任务」详情页右上角按钮重叠(按钮被盖住、点不到):DSH 的「自动化任务」管理插件(
@deepseek-ai/dsh-client-ui-schedule)把任务管理整页注册在核心main槽,右半边的详情面板就是那个编辑页(面板里的「运行时间 / 重复 / 日期 / 时间 / 时区」几行即是改时间的地方),它顶栏右上角那排操作按钮(关联会话 / 更多 / 关闭)落在 x∈[W−100, W−16]、y∈[8,36] —— 与桌面壳的金刚键固定浮层(x∈[W−100, W−8]、y∈[10,38],z-index 顶格)完全重叠:按钮被浮层盖住,点击也被浮层吃掉(看上去像两个「更多/关闭」叠在一起)。修法沿用右栏 chrome 那把尺子:把操作组整体左移margin-right: calc(var(--dsh-desktop-controls-clear) - var(--detail-gutter)),--dsh-desktop-controls-clear是壳实测发布的值(金刚键组 92 + 窗口内缩 8 + 间隙 8 = 108px),减掉核心自己的详情留白后两端相消,按钮组右缘恒为 W−108(金刚键左缘再往左 8px),核心改留白(24→20→16)只会让间隙变宽、永不相撞。选择器只认插件的稳定 data 属性data-detail-tab(:has(> [data-detail-tab]) + :last-child,核心的哈希类名t-XoWW_*变了也不受影响),并三重限定作用域:[data-slot="main"](右栏抽屉里是同一个组件,但它排在 38px 高的 dock 条之下,与金刚键本就不重叠,不该被推)、[data-rightbar-collapsed](右栏文件浏览器开着时中心列右缘不到窗口右缘,本来就不撞)、新增的 MODERN 模式标记[data-dsh-desktop-corner](LEGACY 模式不发布 clearance、不触发)。另经实机测量排除两处原有避让机制均已生效:右栏抽屉自己的全屏/收起按钮(被--dsh-desktop-controls-clear推开)、会话头部 corner 座位(常量 80px 让位 / 右栏打开时整条隐藏)——注入桌面壳真实 CSS 后扫描冲突带(W−100…W−8 × 10…38),每种可达状态下该带内只剩金刚键自己。
内部
-
新增
scripts/test-corner-avoidance.js并并入npm test:把这次的几何常量钉死——金刚键度量(28px 盒 / 4px 间隙 / 8px 内缩 / 10px 顶距 → 组宽 92px)、clear 的 108px 推导、避让规则的形状(clear − gutter、:has(> [data-detail-tab]) + :last-child、三重作用域)与「留白相消后按钮组右缘 ≤ 金刚键左缘 − 8px」的不等式,避免以后改动其中任一常量而静默恢复重叠。AGENTS.md §4 与 docs/agents/desktop-ui.md §4 同步补上这条红线与完整推导。 -
同批修掉 v1.10.7 自己的 Linux 发布失败(CI):v1.10.7 首次发版时 Linux job 挂在 rpm 目标上(
rpmbuild failed (exit code 1)),AppImage 与 deb 都已打好,整个 job 却红 →releasejob 被跳过 → Release 根本没发出去(Windows/macOS 也白跑)。根因不在我们的代码:2026-10-19 GitHub 把ubuntu-latest换成 26.04 镜像,其 rpm 6.0.1 忽略 electron-builder 内置 fpm 1.9.3 的--define buildroot <dir>(rpm 4.20+ 改从%{_builddir}/<name>-<version>-build/BUILDROOT取文件)→ rpm 包里每个文件都是 "File not found" → rpmbuild exit 1。修法两条:① Linux job 固定runs-on: ubuntu-24.04(rpm 4.18.2;v1.10.6 的.rpm正是在它上面产出的),勿跟随ubuntu-latest;② rpm 目标拆成独立 step 且continue-on-error: true——一种格式绝不能阻断整个发布,artifact 上传配if-no-files-found: ignore。AGENTS.md §11 与 docs/agents/install-and-update.md §11 同步补上这条红线。
v1.10.6
[1.10.6] - 2026-10-01
修复
- 「重启核心」快捷键 macOS:⌘⇧R → ⌃⌥⇧R(Windows/Linux 仍为 Ctrl+Alt+Shift+R):1.10.5 改的
⌘⇧R与壳自带的「强制重新加载」撞车——⌘⇧R正是 Electron 给{ role: "forceReload" }的默认加速键,而该 role 就在buildMenu()的视图菜单里(main.js),与新注册的「重新启动 DSH」同处一个应用菜单模板。上次漏掉的原因:结论「全树扫描不存在primary+shift+KeyR绑定」只扫描了 DSH 核心的 node_modules 树,而 Electronrole加速键是原生命令层注册的,DSH 的dsh-client-shortcuts/lib/protocol.js完全感知不到——该结论对核心成立、对壳不成立。新键 ⌃⌥⇧R 同样是三修饰键(protocol.jsL200 对 windows/macos 的modifiers.length >= 3直接放行,DSH 与浏览器/系统都够不着),但解决了 ⌘⌥⇧R 真正难受的根因:不是"三个修饰键"本身,而是 ⌘ 与 ⇧ 同在右手小指、必须叠键或换手;⌃⌥⇧R 是 ⌃左小指 / ⌥左拇指 / ⇧右小指 / R左食指,两只手零叠键,且修饰键名字与 Windows 端逐字一致。同时避开 L221 在 mac 上保留的两个族:⌥不带⌘(重音死键命名空间)与⌃+⌘。core.shortcut.mac的 zh/en 两条文案(locales.js+client.js内嵌副本,共四处)改为 ⌃⌥⇧R,core.shortcut.win两条不动。restartDSH()链路、菜单结构、托盘行为均无变化。
内部
- 新增
scripts/test-shortcut-collisions.js并并入npm test:把这次事故的根因(方法论漏洞)固化成 CI 守卫——解析main.js取出restartCoreAccelerator()的两个平台取值,与「所有显式accelerator:字面量」+「所有在用 Electronrole的默认加速键」逐平台求交集,并校验 ≥3 修饰键、protocol.jsL221 保留族、DSH web 双修饰键生成空间。role 可以不写accelerator仍自带一个默认键,这正是 role 不可见、扫描扫不到的成因。脚本内含一条自证断言,证明它确实能抓到 v1.10.5 那个⌘⇧R,避免守卫本身空转。scripts/test-locales.js另加四条字面量断言,把 win/mac 快捷键提示钉死(该提示已错过两次,不该再靠人眼同步三处副本)。
v1.10.5
[1.10.5] - 2026-09-30
变更
- 「重启核心」快捷键 macOS 特例:⌘⌥⇧R → ⌘⇧R(Windows/Linux 仍为 Ctrl+Alt+Shift+R):MacBook 上三修饰键是要小指+无名指+食指同时按住别扭姿势,纯属手势负担,且两端本就不该用同一个键。改前把 DSH 侧的占用查了个遍(这次不靠推测):
dsh-client-shortcuts在本壳里跑的是 web runtime——我们的 preload 不暴露keyboard桥,client.js:1859的runtime === "desktop"分支会抛 "Desktop keyboard bridge unavailable",所以它必然落到 web 变体;全树扫描KeyR只找到一条真正的快捷键声明(dsh-client-ui-sidebar-right/lib/client.js:275,右栏 refresh =primary+KeyR/primary+alt+KeyR,其余 6 处命中是终端区裸 Ctrl+R 的放行规则、LuckySheet 表格键、xterm 枚举表),即 mac 上⌘R(我们自己的刷新)与⌘⌥R(DSH web 刷新)占着前两格,不存在任何primary+shift+KeyR绑定,且protocol.js:109明确放行primary+shift两修饰键。反过来 Windows/Linux 的三修饰键是真不能动:Ctrl+Alt+R 正是 DSH 的 web refresh、Ctrl+Shift+R 是 Chromium 硬刷新,只有modifiers.length >= 3那条一律放行的规则能给出第三个空位。实现上两处注册点(app 菜单注册 + 托盘展示)收敛到同一个restartCoreAccelerator(),不再各写一份字面量;设置页说明文案core.shortcut.mac的 zh/en 两条改为 ⌘⇧R,Windows 两条不动。restartDSH()链路、菜单结构、托盘行为均无变化。
v1.10.4
[1.10.4] - 2026-09-29
修复
- 侧栏左下角更新徽章"点了没反应 + 能反复点"(更新全局单任务):两条独立根因——① 徽章没有任何运行中状态:鲸港自更新的进度只经
dsh:shellDownloadProgress推给设置页桌面版分区,那是侧栏徽章唯一看不到的地方,点击的返回值被.catch(() => {})吞掉,屏幕上一个字都不变;②dsh:downloadShellUpdate根本没有并发保护(核心更新有自己的installInProgress,壳自更新一把都没有),第二次点击会对同一个 temp 路径再起一条完整下载,两条完成回调各拉一次安装器。修复:主进程新增全局单更新任务状态机updateTask(核心安装与鲸港自更新共用一把锁——两条链都要替换运行中的应用文件,本就不可能并行),setUpdateTask()是唯一写入口(开任务/推进阶段/收尾都在这里广播,纯进度按 400ms 节流、阶段切换立即推),pushUpdateState()把它连同 kind/phase/percent 推给渲染端;sendShellProgress()成为壳下载进度的唯一漏斗并顺带驱动该状态;dsh:installUpdate/dsh:downloadShellUpdate忙时回{busy:true}(不再静默 resolve 成功形状的失败);updateDSH守卫扩为installInProgress || updateTaskBusy()。渲染端徽章改三态:idle(保留两次点击防误触)/ busy(disabled 状态徽章 + 细进度条,文案按「检查中…/下载中 N%/正在校验安装包…/已下载,正在启动安装程序…」切换,判定放在 autoUpdate 早退之前——运行中的任务没有静默这一说)/ failed(「更新失败,点击重试」,单击即可重试,tooltip 带失败原因);设置页两个下载按钮同步置灰。拉起安装器后状态保留 30s 再清零,避免秒内二次点击再拉一个安装器。新增 5 组 i18n key(zh-CN/en-US 同步进locales.js+client.js内嵌副本,scripts/test-locales.js加 20 条断言)。机制详解见 docs/agents/install-and-update.md §9e。
v1.10.3
[1.10.3] - 2026-09-26
变更
- 「重启核心」快捷键 Ctrl+Alt+R → Ctrl+Alt+Shift+R(macOS ⌘⌥⇧R):DSH 0.1.7 引入客户端快捷键系统(
dsh-client-shortcuts),其默认键位规则把Ctrl+Alt+X系划为默认规划区——desktop 下 Ctrl+Alt+B(右栏开关)/Ctrl+Alt+O(打开本地)/Ctrl+Alt+Enter(全屏,fixed)已占用,web 下 Ctrl+Alt+T/P/O/B 更多,按规则"不含 Alt 的默认键位使用 Mod+Alt",后续 R 系命令(刷新/重载类)落进 Ctrl+Alt+R 只是时间问题。壳的重启快捷键与该规划区冲突后让路:app 菜单(真正注册处)、托盘菜单展示项、设置页快捷键说明文案(zh/en × win/mac 四条,locales.js+client.js内嵌副本同步)统一改为三修饰键 Ctrl+Alt+Shift+R——保留 R 的 Restart 语义,DSH 默认键位规则最高只到双修饰键、不会生成三修饰组合,浏览器/系统也无占用,彻底跳出冲突区。纯展示层变更:restartDSH()链路、菜单结构、托盘行为均不动。
v1.10.2
[1.10.2] - 2026-09-21
修复
- 右栏展开后会话头部残留 88px 死区(金刚键双重避让):0.1.5+ 现行方案假设「右栏打开 → 头部 corner 座位
:empty自动隐藏」,但核心槽位 outlet 恒留一个display:contents锚点 div(<div data-slot="conversation.session.header.corner">)作为子节点——即使 ExpandButton 在展开态渲染 null——:empty永不命中,核心的:empty{display:none}与「margin-right:80px 规则随之失效」的设计前提一并落空:展开后空 corner 仍以margin-left:8 + margin-right:80占位,头部右缘留出 88px 死区(此时金刚键小组件落在面板上方、面板自带的全屏/收起按钮已由--dsh-desktop-controls-clear正确避让,头部这份避让纯属多余)。修复:apply() 新增一个 attributeFilter MutationObserver(+2s 轮询兜底面板重挂载),把面板的data-sidebar-right-open状态镜像为<html data-dsh-desktop-rightbar-open>标记,CSS[data-dsh-desktop][data-dsh-desktop-rightbar-open] [data-conversation-header-corner]{display:none}按标记整条隐藏——刻意不用:has()探测 corner 内容:Chromium 跨display:contents锚点的:has()失效重算不可靠,实测会把收起态的展开按钮一并误藏(本次经会话内动态插件两态实测验证:展开态 corner 完全脱离布局、收起态按钮正常显示)。LEGACY(≤0.1.4)无该 DOM 属性、结构性不受影响;普通浏览器无data-dsh-desktop标记同样不受影响。
v1.10.1
[1.10.1] - 2026-09-18
变更
- 核心启动链提速(spawn 前 shell 侧开销 ~54ms,此前实测 184–796ms):①
dshRuntime()不再为选运行时同步 spawnnode.exe --version——改为读 fetch-node.js 早就写在二进制旁的.version标记(缺失/解析失败才回退 execFileSync 探测),并把解析结果进程级记忆化(内置 node 只随壳更新变化、override env 启动即固定);② 重启链杀核后的首次端口复查立即执行(killDSH 已等死透 + settle 窗,原来的盲等 400ms 前摇是纯延迟);③killDSH的 400ms settle 从syncSleep改为异步定时器——原实现每次重启/退出都把主线程硬冻结 400ms(窗口拖动/托盘/启动页全卡)。新增启动耗时日志core ready in N ms (spawn → URL),以后启动变慢可直接从日志归因(壳准备 vs 核心自身启动)。真机验证(隔离环境 + E2E_RESTARTS 钩子):冷启动 spawn 后 4377ms 就绪,完整重启链 4.76s。
修复
log()的 stdout EPIPE 崩溃风暴:stdout 是管道且读取方先退出时(dev 管道、CI 采集器、后台任务托管),EPIPE 从流上异步抛出 → uncaughtException → 处理器自己又console.log→ 再抛 EPIPE → 无限递归,实测日志以 ~30MB/s 膨胀。修复:进程启动时给process.stdout/stderr挂空error监听吞掉流级错误 +console.log本体包 try/catch(同步抛的边角);文件日志是唯一权威落点,console 损失永远不许拖垮主进程。- build-installers 发布 job 的 401 Bad credentials(v1.10.0 发布事故):
releasejob 的三个 gh CLI 步骤用secrets.GH_TOKEN(个人 PAT)调 GitHub API——该 secret 未配置/失效时 gh 直接报401 Unauthorized: Bad credentials,Release 发不出去(4 个构建 job 全部成功、产物已上传,唯独最后一步发布失败)。工作流顶部本就有permissions: contents: write,内置GITHUB_TOKEN的权限完全覆盖「创建/编辑 Release + 上传资产」,改为secrets.GITHUB_TOKEN后不再依赖任何仓库 secret,这类失败从根上消失。release-whaleharbor-promo.yml此前已用GH_TOKEN || GITHUB_TOKEN兜底,本次对齐。 - build-installers 资产校验的空间→点号误判(v1.10.0 发布事故续):GitHub 上传资产时把文件名空格规范成点号(
DeepSeek Harness Desktop Setup 1.10.0.exe→DeepSeek.Harness.Desktop.Setup.1.10.0.exe),verify 步骤按原始名精确比对永远匹配不上,8 个资产明明全在 Release 上却 5 次重试后判失败。改为双侧归一化(小写 + 空格→点)后比较。