dsh-deepseek-style-theme 1.43.12 → 2.0.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,14 +8,14 @@
8
8
 
9
9
  | 上游 | 作者 | 本插件用到了什么 |
10
10
  |---|---|---|
11
- | [dsh-theme-mineradio](https://github.com/dhicoc/dsh-theme-mineradio) | [@dhicoc](https://github.com/dhicoc) | 流体背景的**三段 GLSL 着色器**(顶点 / 流场 / 显示)是上游的逐字节副本;四分之一分辨率流场 + 双 framebuffer 乒乓的求解器结构、玻璃色散折射滤镜、光标视差、对话框悬停倾斜同样移植自上游 |
11
+ | [dsh-theme-mineradio](https://github.com/dhicoc/dsh-theme-mineradio) | [@dhicoc](https://github.com/dhicoc) | 流体背景的**三段 GLSL 着色器**(顶点 / 流场 / 显示)是上游的副本(**唯一改动见 2.0.74:`mediump`→`highp`**,为了让 Intel 核显不再把噪声画成方块);四分之一分辨率流场 + 双 framebuffer 乒乓的求解器结构、玻璃色散折射滤镜、光标视差、对话框悬停倾斜同样移植自上游 |
12
12
  | [deepseek-harness-background](https://github.com/HaoyueQin/deepseek-harness-background) | [@HaoyueQin](https://github.com/HaoyueQin) | 液态玻璃配方的**技法来源**(半透明填充 + 竖向光泽 + 背板滤镜链的设计思路),本插件按自己的选择器与 `--dshome-glass-*` 变量重新表达,未复制源码 |
13
13
 
14
14
  两个项目均为 MIT 许可;完整许可原文见 [`THIRD-PARTY-NOTICES.md`](./THIRD-PARTY-NOTICES.md),随包发布,再分发时必须保留。详细的移植范围与改写点见下文「[第三方代码与署名](#第三方代码与署名)」。
15
15
 
16
16
  ## 特性
17
17
 
18
- - **流体流动背景(1.42.0+)**:全屏 WebGL2 双通道流体模拟——四分之一分辨率的流场(衰减 + 带速度的指针笔刷,两个 framebuffer 乒乓)被全分辨率的域扭曲噪声渲染器采样,带旋流迭代与三色柔性混合;按钮悬停会轻推流场、点击则荡开涟漪。配色跟随 DSTT 三色令牌(峰谷红 / 谷时蓝 / 常态绿)实时重新着色,无需重挂。**无 WebGL2 时自动回落到原来的粒子背景**(粒子实现完整保留)
18
+ - **流体流动背景(1.42.0+)**:全屏 WebGL2 双通道流体模拟——四分之一分辨率的流场(衰减 + 带速度的指针笔刷,两个 framebuffer 乒乓)被全分辨率的域扭曲噪声渲染器采样,带旋流迭代与三色柔性混合;按钮悬停会轻推流场、点击则荡开涟漪。配色跟随 DSTT 三色令牌(峰谷红 / 谷时蓝 / 常态绿)实时重新着色,无需重挂。**无 WebGL2 时自动回落到原来的粒子背景**(粒子实现完整保留)。流场自 **2.0.81** 起优先存储在 **`RGBA16F`** 里(探测 `EXT_color_buffer_float` + 4×4 探针确认 FBO complete,否则诚实退回 `RGBA8`)——8 位存储会把每帧衰减舍入到 1/255,弱值卡住、场里长出平台,域扭曲把平台画成"飘动的方块"(实测:同样 240 步,RGBA8 的场均值 0.0172 挤在 13 个台阶上,RGBA16F 正常衰减到 0.00002);页面可直接读 `window.__dshomeFluidFormat` 确认这台机器拿到的是哪种场
19
19
  - **液态玻璃(1.42.0+,1.43.0 起分两套配方)**:一套「湿玻璃」配方——半透明填充 + 顶部最亮、约 38% 处消失的竖向光泽渐变 + 统一的 `blur() saturate() brightness() contrast()` 背板链 + 内嵌顶部高光与发丝描边,悬停只提亮填充;所有旋钮都是 `--dshome-glass-*` 变量。1.43.0 新增 **`液态 / 白磨砂`** 二选一(见下文 DSTT 设置):`液态` 更通透、折射更强、边框带自走高光;`白磨砂` 就是上面这套。**折射**(SVG `feDisplacementMap`)只加在四个区域上(侧边栏 / 对话框 / 标题栏悬停态 / 用户气泡):它仅 Chromium 支持,且每个元素一次滤镜采样
20
20
  - **鼠标跟随的对话窗光斑(1.42.0+)**:光标在对话窗(消息区与输入框)上移动时,窗口上有一团跟随鼠标的柔光;它用 `background-attachment: fixed` 锚在视口上,所以滚动不会把光斑一起拖走,也不需要覆盖层元素。悬停玻璃面时另有一层随光标偏移的高光(`--dshome-spec-x/y`)
21
21
  - **玻璃拟态**:侧边栏、会话卡片、输入框半透明填充 + 毛玻璃
@@ -39,12 +39,18 @@
39
39
  - **常态绿**:始终绿色,无高峰区分;
40
40
  - **常态蓝**:始终蓝色,无高峰区分。
41
41
 
42
- 另有两行开关:
42
+ 另有几行开关与选项:
43
43
 
44
+ - **背景方式**(`backgroundMode`,默认 `classic`;2.0.73+):一行四选,**切换即时生效、不用刷新页面**。
45
+ - **① 主色+纯白+近白**(`classic`,默认):1.43.11 那套(软主色 + 纯白 + 近白),按钮与背景同一色系、没有第二种色相;
46
+ - **② 主色+纯白**(`white`):同一软主色 + 纯白。着色器三个 uniform 里第三个复用白色(深色复用该族的近黑),所以**只有两个颜色参与**;
47
+ - **③ 自选背景**(`custom`;2.0.76 起的分工见「[插件商城适配](#插件商城适配与壁纸--侧栏插件共存)」):**我们这层完全不画**——流体/粒子画布整体卸载,主题自己的 per-colour 底色也按**选择器**让位(带 `:not([data-dshome-bg=custom])`,不是拿 `!important` 对打),深色蒙版只用在你自己填的图片上。**背景到底是谁的**:装了 `dsh-plugin-wallpaper-engine` 且它正在渲染时**连纯白都不画**,背景交给它;没有它时是**纯白(浅色)/ 纯黑(深色)**。**颜色(蓝/绿/红)只驱动按钮与品牌 token**,不参与背景。想放自己的图就填**图片 URL / 任意 CSS 背景值**,或点「桌面壁纸」(写入 `desktop`,由宿主端读本机壁纸,见隐私一节);不合法的值不会白屏;
48
+ - **浓三色**(`bold`):1.43.12 的三浓色,保留可选(用户要求先留着)。
49
+ - **动态背景(流体)**(`ambientBackground`,默认开;2.0.75+):关掉后**不挂载 WebGL2 流体,也不回落到粒子**——不是把它藏起来(藏起来的画布照样在算),而是根本不创建,GPU 占用归零,背景只剩静态配色。集成显卡把流体画成方块、或风扇被它拉满时,关这个。
44
50
  - **流体跟随笔刷**(`fluidBrush`,默认关):开启后光标才把速度写进流场、拖出尾迹;**改完刷新页面生效**。
45
51
  - **玻璃风格**(`glassStyle`,默认 `液态`):
46
52
  - **液态**(1.43.0+):Apple Liquid Glass 方向——填充降到 `rgb(255 255 255 / .14)`、顶部光泽降到 `.07`,背板链改为靠 `saturate(1.75)` 让身后颜色发亮,共用的 `feDisplacementMap` 走更大的 scale(104,白磨砂仍是 60),边框上再跑一圈自走的 `conic-gradient` 高光(`@property` 注册的 `<angle>`,与鼠标无关)。上玻璃的只有四处:**侧边栏外壳 / 对话框 / 标题栏(悬停)/ 用户消息气泡**;
47
- - **白磨砂**:1.42.x 那套白磨砂 + 蓝变光边框,**逐像素不变**(新配方整块挂在 `html[data-dshome-glass="liquid"]` 下,已用 1991 个元素的计算样式签名验证过:切到白磨砂时新样式表贡献为零)。
53
+ - **白磨砂**:1.42.x 那套白磨砂 + 蓝变光边框,**样式逐像素不变**(新配方整块挂在 `html[data-dshome-glass="liquid"]` 下,已用 1991 个元素的计算样式签名验证过:切到白磨砂时新样式表贡献为零)。**唯一的例外是悬停倾斜**:它自 2.0.82 起两套配方都生效(原先只在液态下挂),运动与配方无关——见「已知产品侧缺陷」一节;
48
54
 
49
55
  ### 高峰判定(1.37.0+)
50
56
 
@@ -53,6 +59,87 @@
53
59
  - 切换**彻底**:背景光效、按钮、输入框边框、卡片旋转描边、粒子、产品品牌 token(`--dsw-alias-brand-primary` 等)全部跟随品牌变量,无残留色。
54
60
  - DSTT 面板状态行实时显示「距高峰结束还剩 X 小时 X 分」。
55
61
 
62
+ ## 插件商城适配(与壁纸 / 侧栏插件共存)
63
+
64
+ 本主题与商城里的两个热门插件同装一套时会出现「谁画背景、谁管侧栏」的重叠,2.0.76 起按下面这套约定共存。**原则:只读探测、不做 `!important` 对打、不碰它们的 DOM。**
65
+
66
+ ### 与 `dsh-plugin-wallpaper-engine`(壁纸引擎,实测 0.7.2)
67
+
68
+ 它把壁纸画在 `.we-layer{position:fixed;inset:0;z-index:-2}` 里 —— **在 body 背景之上、内容之下**,也就是说我们在 `<body>` 上画的任何东西都会被它盖住;反过来,如果我们的流体画布(`z-index:-1`)还在跑,就会盖住它的壁纸。
69
+
70
+ - **探测**:只读它自己的标记 `body[data-we-wallpaper]`(它渲染时置上、停止时移除;本插件用 MutationObserver 跟随,无需刷新)。**不读它的设置、不改它的 DOM。**
71
+ - **③ 自选背景下的分工**(2.0.76 语义):
72
+
73
+ | 状态 | 背景由谁画 |
74
+ |---|---|
75
+ | ③ + 壁纸引擎正在渲染(`body[data-we-wallpaper]`) | **它**。我们的流体卸载、主题底色让位、**连纯白也不画** |
76
+ | ③ + 没有壁纸引擎 | **我们**:纯白(浅色)/ 纯黑(深色) |
77
+ | ③ + 输入框填了图片 / CSS 值 / 点「桌面壁纸」 | **我们**(注意:此时它仍在壁纸引擎图层之下,若壁纸引擎在跑就看不到) |
78
+ | ①②/浓三色 | 我们(per-colour 渐变 + 流体),与从前一致;**若壁纸引擎正在渲染,面板会出现橙色提示「切到 ③」(提示,不自动切)** |
79
+
80
+ - **让位是"选择器让位",不是 `!important` 对打**:主题自己的四条背景规则带 `:not([data-dshome-bg=custom])`,进 ③ 就不匹配,所以壁纸引擎自己的 `body[data-we-wallpaper]` 样式不会被我们压掉。
81
+ - **提示而不是自动切换**(2.0.77):检测到它在渲染、而当前档位不是 ③ 时,DSTT 面板出现橙色提示 +「切到自选背景」按钮;**我们绝不替用户改档位**(标记的 observer 只重渲染面板,不调用改档位接口,冒烟里有断言钉住)。
82
+ - **不抢它的玻璃**:它用 `data-we-glass-window` / `data-we-sidebar-glass` 管设置窗与侧栏玻璃;这两块我们不插手(若两边同时开玻璃,以它为优先是推荐配置)。
83
+ - **它的前置条件**:DSH ≥ `0.1.5-rc.1`(Desktop ≥ 2.0.7)且 `dsh-better-sidebar` ≥ `0.19.0`;本主题与这组版本同装验证过。
84
+
85
+ ### 与 `dsh-better-sidebar`(右侧栏,实测 0.19.1)
86
+
87
+ 它是 VSCode 式右侧栏(资源管理器 / 编辑器 / 终端 / git / 浏览器),并对外暴露 `ctx.betterSidebar` 服务。
88
+
89
+ - **探测**:只读 DOM 标记 `[data-dsh-better-sidebar]`(它的面板宿主)与 `[data-dsh-center-col]`(它给中心列打的标记);宿主侧无需任何配合。
90
+ - **布局**:它用 `#root [data-dsh-center-col]{margin-bottom:var(--dsh-sidebar-height)}` 把会话列顶起来;本主题**不写中心列的尺寸、不动它的 tab 栏 / 面板内部**,只对产品自己的表面(侧栏外壳、对话框、标题栏)做玻璃与配色。
91
+ - **已知交互(重要)**:它的面板宿主几何同步会在检测到**页面级 transform** 时降级(它自己会打 `data-dsh-panel-host-degraded`)。本主题的「对话框悬停倾斜」会给对话框卡片写 `transform: perspective(800px) … scale(1.01)` —— 这是**卡片级**而非页面级,正常情况无碍;但若你在同装后看到悬停抖动 / 底部滑块闪动,先按上一节的顺序二分:`__dshomeTilt()` 看倾斜此刻是否在动、`tilt(false)` 一行冻结它、再 `ambient(false)` 关掉动态背景画布(2.0.82 起两套玻璃配方都会倾斜,所以"切白磨砂"不再是有效的二分手段)。
92
+ - **右侧栏配色**:它面板内部的配色由它自己管;本主题的深色规则只覆盖产品原生的右栏表面(`.VOzbGW_panel` 等),不改它的 class 命名空间。
93
+
94
+ ### 适配清单(写给以后接手的人)
95
+
96
+ | 我们读的东西 | 谁写的 | 用途 | 失败时会怎样 |
97
+ |---|---|---|---|
98
+ | `body[data-we-wallpaper]` | 壁纸引擎 | ③ 里决定"画纯白"还是"完全不画" | 读不到就当没装:③ 画纯白/纯黑 |
99
+ | `body[data-ds-dark-theme]`、`theme` 服务 | 产品 / 主题服务 | 明暗标记(不依赖产品属性名,见健壮性一节) | 退回主题服务;再不行按 `data-dshome-dark` 缺省=浅色 |
100
+ | `[data-dsh-center-col]`、`[data-dsh-better-sidebar]` | better-sidebar | 只用于"不越界"的文档与自查,不改写 | 什么都不做(我们本来也不碰) |
101
+ | `body[data-dshome-*]` | 本主题 | 自己的全部开关 | —— |
102
+
103
+ > 适配的原则是**单向只读**:本主题从不写别的插件的属性,也不依赖它们的内部 class(散列类名会随它们重建失效——本仓库就吃过 `.gdEzaW_bubble` 失效没人发现的亏)。
104
+
105
+ ## 已知产品侧缺陷与主题的处置(2.0.78+)
106
+
107
+ ### 悬停消息时的横向溢出 → 对话框 8px 抖动 + 底部滑块闪动
108
+
109
+ **现象**:鼠标在对话框右端(发送键 / 小圆圈)附近移动时,两颗按钮的观感来回跳,底部有滑块一闪一闪。
110
+
111
+ **定位链(真机采样,2026-09-15)**:
112
+
113
+ 1. 会话滚动区 `wSkVaW_scrollBody` 出现横向溢出:`scrollWidth 917 > clientWidth 891`,溢出元素是消息行的 `span._bubble_*` —— 产品在**悬停消息**时展示的操作栏把那一行撑得比列还宽;
114
+ 2. 横向溢出 → **8px 细横向滚动条**被生成 → 同一滚动区的 `clientHeight 842 → 834`;
115
+ 3. 对话框固定在该滚动区下方 → 卡片 `top 699 → 691`(−8px);
116
+ 4. 指针因此落到另一个元素上 → 操作栏收起 → 滚动条消失 → 对话框落回 → 回到第 1 步。**~5Hz 两态自激**,表现出来就是"按钮跳 + 滑块闪"。
117
+
118
+ **主题的处置**(2.0.78):给会话滚动区加 `overflow-x: clip`(守护块,锚点 `.wSkVaW_scrollBody`,规则按 `[class*="scrollBody"]` 子串匹配,散列类改名也不会静默失效)。横向不再产生滚动条,那 8px 就不存在,闭环断开;每个代码块自己的横向滚动不受影响。代价:超出列宽的部分会被裁掉而不是可滚动 —— 在聊天列里这是更小的恶。**溢出的根因在产品侧,值得上报。**
119
+
120
+ **第二半:我们自己的倾斜**(2.0.79 想修,2.0.82 才算修对)。滚动条链条断掉后,真机逐帧采样显示剩下的抖动来自悬停倾斜本身:
121
+
122
+ ```
123
+ card=700/757 … under=div.uV2eYG_row hovCard=1
124
+ card=700/765 … under=button.uV2eYG_primary hovCard=1 ← scale(1.01) 把卡片从 757 推到 765
125
+ card=699/761 … under=div.wSkVaW_widthHandle hovCard=0 ← 边缘越过了指针 → 底下换成拖拽把手
126
+ card=700/757 … under=div.wSkVaW_widthHandle hovCard=0 ← 倾斜解除、卡片缩回
127
+ ```
128
+
129
+ 指针**静止**时,1% 放大把卡片边缘推出 8px,于是指针底下的元素在"对话框控件"与"列的宽度把手"之间翻转,而每次翻转都会重新武装或解除倾斜 → 因为过渡只有 0.1–0.24s,比被滚动条中介的那条**更快**。
130
+
131
+ **2.0.79 修错了**:它把抬升去掉(`TILT_SCALE: 1.01 → 1`),并把 `input / textarea / [contenteditable]` 也算成"不能压在动面上的控件"。两条都是矫枉过正,而且同因:**输入框几乎盖满整张卡片**,把它排除等于让倾斜在"鼠标放到对话框上"这个它唯一存在的姿势里永不触发,抬升也跟着一起没了。用户报回来的是「鼠标放在对话框,放大、倾斜没了」——修法本身成了新的缺陷。
132
+
133
+ **2.0.82 的修法(保留效果,切断回路)**:
134
+
135
+ 1. **抬起回来**:`TILT_SCALE` 恢复 `1.01`;
136
+ 2. **输入框上可以倾斜**:`TILT_CONTROLS` 只留 `button / [role=button] / a[href] / [class*="andle" i]`,文字录入不再挡。倾斜是**带着输入框一起动**的,指针不会因此掉出输入框;
137
+ 3. **滞回取代"越界即释放"**(关键):指针进入控件时**冻结当前角度**——不重画、不回弹、不重新武装;回到卡片空白处再续;只有指针**离开卡片自己的矩形**才释放,释放后还有 `TILT_COOLDOWN_MS = 200` 的冷却期才允许下一次进入。那条自激回路需要"释放"来喂它,而现在指针静止时倾角是**死的**,没有任何反馈通路。
138
+ 4. **两套玻璃配方都倾斜**:原先 `paint` / `onOver` 各有一道"不是液态就早退"的闸门(理由是白磨砂要保持逐像素不变),结果是**用白磨砂的人永远看不到这个效果**——用户点名的第二条要求就是「白磨砂玻璃也要有」。现在闸门拆掉,而且运动**自带过渡**(`TILT_TRANSITION`,值与原液态样式表里那条相同),这样任何配方都不会因为少了一条 `transition: transform` 而变成硬跳;
139
+ 5. 状态可从页面直接读:`window.__dshomeTilt()` → `{ recipe, leaning, frozen, engagements, sinceRelease }`。"效果不见了"因此不再需要猜是哪道闸门吃掉的。
140
+
141
+ > 排查方法记在这里,方便复现:`ResizeObserver` 盯住卡片到 body 的祖先链(谁改高度谁自己报),再对滚动区打 `scrollWidth/clientWidth` 与"右边缘越界元素";最后用 rAF 逐帧记录"指针底下是谁 + 候选元素的矩形",翻转对就能一眼看出。跨机器复现用 `tools/symptom-probe.js`(贴进控制台,`run(秒)` 同时采样 GPU 状态与光标下的逐字段 diff,`tilt(false)` 一行就能把倾斜冻结做对照)。
142
+
56
143
  ## 健壮性设计(1.33.1+)
57
144
 
58
145
  产品壳的构建期 hash 类名(如 `wSkVaW_header`)不是 API,产品升级重构建后可能变化。本主题对此做了分层防护:
@@ -208,6 +295,7 @@ deepseek-style-theme:
208
295
  4. `Content-Type: application/json`——让跨站尝试必须预检,而本路由从不回应预检;
209
296
  5. `payload.path` 必须是**本机绝对路径**:相对路径、含 NUL、UNC(`\\host\share`、`//host/share`)一律拒绝。UNC 会让 Windows 向该主机做认证,可被用来外带 NTLM 哈希。
210
297
  - **数据可见性**:客户端读取会话列表元数据(标题、运行状态、token 用量)仅用于页内展示「运行中子代理」面板,不上传任何外部服务器;唯一的网络跳转是点击品牌标识时打开 `deepseek.com`(显式用户操作)。宿主端的唯一请求是上一条所述的 `GET {baseURL}/models`,只发往你配置的 DeepSeek 端点,不携带会话内容。
298
+ - **桌面壁纸(2.0.75+,只在显式选择时触发)**:只有当你在 **③ 自选背景**里把输入框填成 `desktop`(或点「桌面壁纸」按钮)时,宿主端才读一次本机壁纸——优先 Windows 的 `TranscodedWallpaper`(当前实际显示的那张),退回注册表 `HKCU\Control Panel\Desktop\WallPaper`,再退回注册表的纯色值——并把图片经**同源围栏下的 GET 子路径**发给本页当 CSS 背景。该端点**不接受任何输入**(没有路径参数、没有查询串),所以它能供出的永远只有宿主自己解析到的那张图;响应带 `Cache-Control: no-store`,壁纸换了刷新即见。**图片只在本机回环上传输,不上传、不缓存、不落盘**,会话记录里也不会出现它的内容。网页本身没有任何 API 能访问系统壁纸,所以这一步只能由宿主端做。留空**不会**触发它(留空 = 纯白/纯黑,或让位给壁纸引擎)。
211
299
  - **配置落盘**:DSTT 主题模式与同步开关写入 profile 的 `settings.yaml`(`deepseek-style-theme` 段);模型目录同步在需要时写入同一文件的 `llm-deepseek` 段(带乐观锁,不覆盖你并发的修改)。
212
300
 
213
301
  ## 卸载
@@ -222,11 +310,16 @@ dsh plugin --profile web remove dsh-deepseek-style-theme
222
310
 
223
311
  ## 自测工具(开发用,不随包发布)
224
312
 
225
- `tools/` 里的四个脚本都在本机直接跑,**不进发布产物**(`package.json` 的 `files` 只含 `lib/`、`cordis.patch.yml`、`README.md`、`LICENSE`)。前三个不需要浏览器、不需要网络;第四个需要自己起一个无头 Chrome。
313
+ `tools/` 里的脚本都在本机直接跑,**不进发布产物**(`package.json` 的 `files` 只含 `lib/`、`cordis.patch.yml`、`README.md`、`LICENSE`)。除 `gui-probe.mjs`、`symptom-probe-selftest.mjs` 与 `--open` 的 `bridge-smoke.mjs` 外,都不需要浏览器、不需要网络。
226
314
 
227
315
  | 工具 | 作用 | 运行 |
228
316
  |---|---|---|
317
+ | `symptom-probe.js` | **贴进浏览器控制台的现场探针**(2.0.81+):专门给「症状机器不是开发机」的情况用。先打印一份环境 JSON——每个补丁块是否落到 DOM 上(`style[data-plugin-css]` 清单 + 13 个锚点是否存在:锚点按产品构建哈希命名,换构建就会静默跳过,2.0.78 的 `overflow-x: clip` 就是靠它守住的)、`data-dshome-*` 标记、每块 canvas 的 z-index/opacity/所在 GPU/是否 context lost、消息列的 `scrollWidth - clientWidth` 与超宽/自溢出的子元素、发送按钮等控件的盒模型与 transition;再给 `run(秒)`:**同时**采样 GPU 状态(fps、context lost、`gl.getError()`、canvas 尺寸抖动)与光标下的逐帧变化(命中元素链、盒、transform、padding、margin 的逐字段 diff,带 240 条截断与变化率),最后是 `tilt(false)` / `clip(true)` / `ambient(false)` / `wallpaper(false)` / `glass(false)` 五个开关,用来把「关掉 X 之后症状还在不在」变成一句话答案。不写任何设置、不弹权限框 | 控制台粘贴整份文件 |
318
+ | `symptom-probe-selftest.mjs` | 上面那份探针的自测(19 项):在一个合成页面上跑(我们自己的 canvas + 带超宽子元素的消息列 + 每 60 ms 改一次 transform 的卡片 + CDP 派发真实鼠标移动),断言环境报告的字段形状、`run()` 的采样与逐字段 diff、五个开关的实际效果(含 `clip` 在 `overflow-y:auto` 旁会计算成 `hidden` 这条 CSS Overflow 3 规则) | `chrome --headless=new --remote-debugging-port=9333 --user-data-dir=%TEMP%\dsh-probe-chrome about:blank`,然后 `node tools/symptom-probe-selftest.mjs` |
229
319
  | `bridge-smoke.mjs` | 宿主端私有 RPC 通道:协议、错误路径,以及完整围栏(非回环对端 / 缺 `Host` / DNS rebinding / 跨站来源 / `Origin` 不匹配 / 非 JSON 类型 / UNC 路径 / `file.*` 端点识别与校验,24 项检查;加 `--open` 为 25 项,会真的用系统默认应用打开一个临时文件,**会在桌面弹出窗口**,默认不启用) | `node tools/bridge-smoke.mjs [已安装的 lib/index.js] [--open]` |
320
+ | `dstt-schema-smoke.mjs` | DSTT 设置 schema 与写入路径的一致性:**每个能写进 `settings.yaml` 的值都必须过 `register()` 的校验**(1.43.2 那次 schema 缺 `wide` 的发布阻塞就靠它守)。含背景方式四档的往返、未知 id 拒写、自定义背景的归一化(控制字符→空格、去首尾、长度上限)、动态背景开关的读写与布尔回读,以及「客户端枚举 = 宿主枚举」的跨文件检查(29 项) | `node tools/dstt-schema-smoke.mjs [lib/index.js]` |
321
+ | `bg-recipes-smoke.mjs` | 客户端源码层的数据与契约断言(2.0.73+,随每版增补):① 必须含纯白 + 近白、② 只有两个颜色参与、`bold` 浅色无 `#FFFFFF`、③ 的基底/让位规则与选择器守卫、壁纸引擎标记与「提示而非自动切换」、桌面壁纸端点与 `WallpaperStyle` 映射、`darkSync` 作用域、两条反引号守卫(整表扫描)、发送按钮 hover 不再位移、流场 16F 探测与回退、**悬停倾斜的抬升 1.01 与 `TILT_CONTROLS` 不含文字录入、进入控件时冻结而非释放、释放只在离开卡片矩形、两套玻璃配方都生效(2.0.82)**、横向裁切覆盖消息列/对话框/转写区(64 项) | `node tools/bg-recipes-smoke.mjs [lib/client.js]` |
322
+ | `fluid-precision-test.mjs` | **流场存储精度对照实验**(2.0.81+):把 `lib/client.js` 里的真实 `VERTEX_SHADER` / `FLOW_SHADER` 抠出来,在无头 Chrome 里对同一场景各跑 240 步,分别存 RGBA8 与 RGBA16F,读回统计"取值分布 / 落在 1/255 网格上的层级 / max / mean",并判定 16F 是否真的摆脱了量化(5 项)。**需要 Chromium 系浏览器**,且 Chrome 在受限进程里起不来,请从普通终端跑 | `node tools/fluid-precision-test.mjs [--chrome <路径>] [--keep]` |
230
323
  | `catalog-sync-smoke.mjs` | 模型目录同步的全部分支:一致 / 可描述漂移 / 聚合网关目录 / 只追加 / `off` / baseURL 解析顺序 / 无密钥 / 端点故障 / 命名空间未就绪 / 版本冲突(27 项检查,全用替身,无需凭据与网络) | `node tools/catalog-sync-smoke.mjs [已安装的 lib/index.js]` |
231
324
  | `catalog-sync-live.mjs` | 用**真实端点 + 真实密钥**跑一遍同步:A 场景(目录已一致)应 0 写入,B 场景(人为制造漂移)应恰好 1 次写入并复原条目;写入被拦下,不落盘 | `DEEPSEEK_API_KEY=... node tools/catalog-sync-live.mjs [--profile web] [--drift-id deepseek-v4-pro]` |
232
325
  | `gui-probe.mjs` | 无头浏览器直连 CDP 量实时页面:主题注入了哪些样式与补丁块、标题栏几何与子元素 flex order、标题栏下方带边框元素与**逐行亮度扫描**(1px 横线会表现为数值尖峰)、各胶囊的 `corner-shape`、中/E 悬停前后、对话/轨迹标签、`--models` 时的模型选择器选项、`--file-card` 时合成两张交付表面并验证左键/右键菜单(条目、定位、复制提示、预览转发、选中后关闭)、`--deliverables` 时报告真实页面上两处交付表面的存在情况与点击后果、`--ambient` 时报告背景到底是流体还是粒子回落、折射是否挂上、玻璃配方是否生效,并悬停一次验证 `--dshome-spec-x/y` 真的在写、`--glass` 时逐个报告玻璃面的计算样式与 `::before`/`::after` 是否已被产品占用、`--messages` 时报告气泡的类名分组、祖先对齐链与 `data-chat-flow-kind` 取值表(气泡的 role 判定就靠它)、`--shot <目录>` 时落一张全页截图,`--pre <文件>` 可在截图前先跑一段页面侧表达式(`--pre-arg` 作为 `window.__preArg` 传入),用于拍出「指定玻璃配方 × 指定明暗」的矩阵 | 见下 |
@@ -253,6 +346,8 @@ node tools/gui-probe.mjs --models --file-card
253
346
  │ ├── bridge-smoke.mjs # 宿主端私有 RPC 通道冒烟测试
254
347
  │ ├── catalog-sync-smoke.mjs # 模型目录同步冒烟测试(六种分支)
255
348
  │ ├── catalog-sync-live.mjs # 同步的真端点/真密钥校验(写入不落盘)
349
+ │ ├── symptom-probe.js # 贴进控制台的现场探针(环境报告 + 采样 + 逐帧 diff + 开关)
350
+ │ ├── symptom-probe-selftest.mjs # 上面那份探针的自测(合成页面 + CDP 真实鼠标)
256
351
  │ └── gui-probe.mjs # 实时页面的无头浏览器探测与像素扫描
257
352
  └── lib/
258
353
  ├── index.js # host 端:打开工作区 / 交付文件 RPC、DSTT 设置、模型目录同步
@@ -265,7 +360,7 @@ MIT
265
360
 
266
361
  ### 第三方代码与署名
267
362
 
268
- 本插件的流体着色器、玻璃折射滤镜与光标视差**移植自 [dsh-theme-mineradio](https://github.com/dhicoc/dsh-theme-mineradio) v2.3.8**(MIT,Copyright (c) 2026 John Wu)——三段 GLSL 是上游的**逐字节副本**,只改了命名与外部依赖;1.43.0 的**对话框悬停倾斜**同样移植自上游 `startSpotlight` 的 tilt 分支(常量 `TILT_MAX 0.0175` / `TILT_PERSPECTIVE 800` / `scale(1.01)` / 松手 240ms 后清内联属性,按本主题只作用于对话框)。液态玻璃配方则**仿照 [deepseek-harness-background](https://github.com/HaoyueQin/deepseek-harness-background) 的玻璃样式**(MIT,Copyright (c) 2026 HaoyueQin),是按本插件选择器与 `--dshome-glass-*` 变量对该技法的重新表达,未复制其源码。
363
+ 本插件的流体着色器、玻璃折射滤镜与光标视差**移植自 [dsh-theme-mineradio](https://github.com/dhicoc/dsh-theme-mineradio) v2.3.8**(MIT,Copyright (c) 2026 John Wu)——三段 GLSL 是上游的副本,只改了命名与外部依赖,**外加 2.0.74 记录在案的一处改动:`precision mediump float;` → `precision highp float;`(FLOW_SHADER 与 DISPLAY_SHADER)**,原因是 Intel 核显在 ANGLE/D3D11 下把 `mediump` 当真 16 位浮点,sin 哈希噪声会塌成方块;WebGL2 保证片元着色器支持 `highp`,在把 mediump 提升为 32 位的 GPU 上此改动为空操作。1.43.0 的**对话框悬停倾斜**同样移植自上游 `startSpotlight` 的 tilt 分支(常量 `TILT_MAX 0.0175` / `TILT_PERSPECTIVE 800` / `scale(1.01)` / 松手 240ms 后清内联属性,按本主题只作用于对话框)。液态玻璃配方则**仿照 [deepseek-harness-background](https://github.com/HaoyueQin/deepseek-harness-background) 的玻璃样式**(MIT,Copyright (c) 2026 HaoyueQin),是按本插件选择器与 `--dshome-glass-*` 变量对该技法的重新表达,未复制其源码。
269
364
 
270
365
  两份完整许可原文见 `THIRD-PARTY-NOTICES.md`,随包发布,再分发时必须保留。
271
366
 
@@ -23,7 +23,16 @@ dispersion / specular-parallax subsystem of **dsh-theme-mineradio v2.3.8**:
23
23
  Only naming and external dependencies were adapted: plugin-scoped identifiers
24
24
  were renamed to this plugin's `dshome-` prefix, and the upstream settings/theme
25
25
  store and React layer were replaced by function parameters. **The GLSL shader
26
- sources are byte-for-byte copies of upstream.**
26
+ sources are copies of upstream, with one recorded deviation (v2.0.74): the
27
+ `precision mediump float;` qualifier in FLOW_SHADER and DISPLAY_SHADER was
28
+ changed to `precision highp float;`.** The reason is a rendering defect, not a
29
+ feature: under ANGLE/D3D11 on Intel integrated GPUs `mediump` is a real 16-bit
30
+ float (`min16float`), and the display shader's noise --
31
+ `fract(sin(dot(st, vec2(12.9898,78.233))) * 43758.5453123)` -- needs roughly 24
32
+ bits of mantissa, so at 16 bits the hash collapses into constant plateaus and the
33
+ noise lattice shows up as large drifting squares. WebGL2 guarantees highp in
34
+ fragment shaders, and on GPUs that promoted mediump to 32 bits the change is a
35
+ no-op. Every other line of every shader is unchanged.
27
36
 
28
37
  Upstream notes that its fluid shader is itself a faithful port of the
29
38
  `ds-join-shader-bg` shader in the deepseek.com site bundle, with the shader