dsh-aurora-effort-slider
把 DeepSeek Harness 模型座位里的「推理等级」那一行,换成一条可以直接拖动的星河滑轨。
不用先钻进等级列表再点一下——拖到哪就是哪。


| 浅色 · High | 深色 · High |
|---|---|
![]() |
![]() |
特性
- 直接拖动:滑轨长在官方「推理等级」那一行里,档位随拖动即时切换;也支持方向键 /
Home/End。 - 星河视觉:深空轨道 + 星云填充 + 34 颗星点(亮度越亮、颗粒越大),光刃停在当前档位。
- MAX 曲速:到达最高档时,原本就在的粒子加速向左掠过(不是新发射一批),拖尾随之拉长, 随后 2.2 秒内继续"上红线"加力并轻微呼吸。
- 滑停而不是急刹:离开 MAX 时用 smoothstep 衰减(两端导数为 0);若在滑行途中又推回 MAX, 会接管当前速度继续加速,而不是归零重来。
- MAX 光环与文字染色:卡片套上紫色描边 + 随蓄能增强的辉光;菜单行的数值与收起态触发器上的 档位文字一并染色,非 MAX 时干净还原官方颜色。
- 不做卡片位移:所有反馈由光承担(刻度一闪、光刃过曝、星流),窗口和卡片纹丝不动。
- 跟随 DSH 的深色主题(
data-ds-dark-theme);尊重prefers-reduced-motion,此时退化为静态状态。
安装
只走 DSH Desktop 自己的插件面板——命令行装不了 desktop profile
(bin.js 对保留 profile 直接报错:profile "desktop" is managed exclusively by the Electron application)。
- 打开 DSH Desktop,进入 Web 侧边栏 → Plugins → 添加插件;
- 填入本目录的绝对路径(或已解压的发布包目录),安装;
- 在应用内刷新页面。若没出现,重启 DSH Desktop。
更新 / 卸载
- 更新代码:本地目录安装的本质是
link:依赖——宿主读的就是这个目录里的lib/client.js。 改完代码刷新页面即可生效,不需要卸载重装。 - 改包名则必须重装:profile 里记录的是包的名称(
dependencies条目 +dsh.profile.bundles列表)。一旦改动package.json的name(例如把@local/xxx改成 公开发布名dsh-aurora-effort-slider),刷新页面是不够的——滑轨会直接不出现,必须在插件面板 卸载旧的、再按新目录安装。这也是从发布包升级时要卸载重装的原因。 - 卸载:Plugins 页面里卸载,或先禁用。插件卸载时会把官方节点、样式、观察器全部还原,零残留。
- 备份 profile 的
package.json(macOS 上是~/Library/Application Support/DSH/profiles/desktop/package.json,以实际安装位置为准); - 加一条依赖:
"dsh-aurora-effort-slider": "link:/绝对路径/dsh-aurora-effort-slider"; - 在
dsh.profile.bundles数组里追加"dsh-aurora-effort-slider"; - 在
profiles/desktop/node_modules/下建一个指向该目录的符号链接; - 重启 DSH Desktop。
卸载时先把链接删掉再用面板/手改配置文件——不要用递归删除去删符号链接,那可能顺着链接把插件目录里的文件删掉。
它是怎么工作的
两半
| 半边 | 职责 |
|---|---|
lib/index.js(宿主) |
空逻辑 + 一次客户端产物静态核对。存在的唯一理由:让本包成为 cordis 树上的一行,否则 dsh.client 的 bundle 不会被扫进启动图 |
lib/client.js(客户端) |
注册席取得 session 作用域 + 官方数据面读写 + 用 portal 把滑轨注入官方那一行 |
集成模型(三条,全部照 DSH 生态里已被验证过的形状)
成为一个席:注册进官方插槽
conversation.input.right,从框架拿到sessionId。 席本身只渲染一个不可见锚点,用来定位"我自己这张 composer 卡片"。读写走官方公开数据面,一个 DOM 都不点、一个状态都不猜:
用途 接口 读档位表 / 当前档位 / 提交中 / 失败原因 modelDirectories.directoryFor(sessionId).store.getSnapshot()→{ current, groups, status, pending, error }写档位 directory.select({ provider, model, reasoningEffort })—— 与官方模型菜单同一个写入口订阅 store.subscribe()+React.useSyncExternalStoreUI 用
ReactDOM.createPortal注入官方那一行:React 自己拥有这棵子树,官方重渲染不会抹掉它, 也就不需要悬浮层、补内边距、轮询定位那一套。
依赖的官方锚点(全部是语义属性,不是哈希类名)
| 锚点 | 官方产物里的形状 |
|---|---|
| 自己的 composer | [data-composer-card] |
| 席位按钮 | button[aria-haspopup="menu"][aria-expanded="true"] |
| 菜单 | 席位的 aria-controls → getElementById(...)(portal 到 body) |
| 目标行 | 菜单里 [role="menuitem"] 恰好两行时的第 2 行(子面板用 menuitemradio,所以 menuitem 唯一标识根面板) |
| 档位文字 | 文本恰好等于档位名的最内层 span(官方把档位单独放在一个 span 里) |
fail-open:任何一步认不出(拿不到 session / 目录未就绪 / 认不出那一行 / 模型没有推理元数据) 就什么都不做,官方界面保持原样——绝不会因为本插件点不开。
两个不易察觉的坑(都已在实现里处理)
- 菜单是"测量后固定定位"的:官方
place()读offsetHeight算位置,且只在open/pane/state/query变化 +resize+scroll时重算。所以我们在菜单一打开就先把那一行加高、 把高度预留好(而不是先按矮菜单落位、插进去之后才被顶上去——那会表现为卡片先压住触发器、 一动档位才跳上去)。高度变化后再分 3 次派发resize兜住调度竞态。 - 不要给轨道加
will-change:给一个每帧改变内部宽度的容器强制提升合成层,会导致图层反复 重新栅格化,实测表现为拖动时整个卡片一闪一闪。合成层的收益要用 DevTools 量过再谈。
开发
node check.mjs # 交付前预检:结构与数据面断言(含发布一致性)
preview/harness.html 是不用装 DSH 就能看像素的离线仿真台:真 React 渲染插件组件 +
假 modelDirectories store(形状照抄官方 createSnapshotStore)+ 假官方菜单(aria 契约一致)
- 复刻官方的
place()定位。
cd dev && npm i # 仿真台用的真 React(不进安装产物)
open ../preview/harness.html
# URL 片段可叠加:#off / #high / #max / +#dark / +#hover / +#drag / +#shot
改完代码先跑预检、再在仿真台看清像素,最后刷新真机——插件的效果必须先在像素上验证过, 不要把回归直接推给使用者。
仿真台里的两个坑(踩过)- headless 下
requestAnimationFrame不触发(无 GPU 合成 + 虚拟时间),必须垫成setTimeout(…,16),否则曲速循环一帧都不跑,引擎看起来"正常"其实没动。垫片已在harness.html里。 - 亚像素几何(圆角端头、握把胶囊这类)看图比统计可靠:颜色阈值检测很容易把光晕、星点、 轨道外的白底算进来,我就因此连续误判过三次。
已知边界
- 必须先点开模型菜单才能改档位——滑轨活在官方那一行里,输入框工具行上没有常驻读数。
- 注入后菜单卡片会高约 28px。
- 依赖官方 DOM 语义属性。官方若改成非
menuitem结构、去掉aria-controls或data-composer-card,本插件会静默退回"什么都不做"(官方菜单照常可用)。 - 只在 macOS 的 DSH Desktop 上实测过;代码本身是纯 Web,其他平台理论上同样可用。
变更记录
见 CHANGELOG.md。
许可
MIT。无第三方代码:光刃、雪弗龙、粒子层都是自己写的 DOM/CSS。


No comments yet. Be the first to write one.