DeepSeek Harness 插件

syx2bzd/dsh-ricewhale

Star 数 ★ 0 分类 UI 增强 收录于 2026-09-20

DSH Web 界面的「鲸鱼女仆」物理挂件:拖拽投掷、吃 token 币计分、每满 500 个 token 冒一碗白饭。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:syx2bzd/dsh-ricewhale

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWEDERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yamlallowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

DSH Web 界面里的「鲸鱼女仆」物理挂件 —— 拖动重写版(在旧版 dsh-whale-charm 的基础上重做,素材沿用)。

按住拖起来 → 甩出去松手 → 撞屏幕四边回弹 → 落地摩擦减速;静止一会儿自己做待机动作(呼吸 / 跳 / 挥手 / 换姿势)。 屏幕上撒 token 币:蓝币 1 分、黄币 3 分,撞到就吃,连吃按倍数翻分,每满 5 连触发一次高光时刻,累计分持久化。 右键本体弹出设置面板(主面板 + token 设置,标题栏可拖动),面板会自动躲开本体不压住它。

安装

从 npm 安装(推荐):

dsh plugin --profile web add dsh-ricewhale

或者 clone 本仓库,用 link 方式装本地副本(要改代码时用这个):

# 先 clone 到任意目录,再用 link 方式装进 web profile
$env:DSH_HOME="$env:USERPROFILE\.dsh"
dsh plugin --profile web add link:<本仓库所在目录>

装完重启一次 DSH Web 宿主进程(Node 侧插件只在启动时加载)。之后改客户端逻辑只要 node mk.mjs + 刷新页面即可: 宿主每次请求都从 client.dist.js 实时读盘,不必再重启。 仓库里已经带了构建产物(client.dist.jslib/index.js),clone 下来即可直接安装,不需要先构建。

卸载:

dsh plugin --profile web remove dsh-ricewhale

与旧的 dsh-whale-charm 可以并存(两条鱼),也可以先 dsh plugin --profile web remove dsh-whale-charm 只留这条。

这一版针对"拖不动"改了什么

上一版的故障现象不是"抓不住元素",而是按一次之后整页永久静止,连右下角原厂挂件也点不动 —— 属于整页级渲染循环死亡。这一版从三个地方堵住:

# 上一版的问题 这一版的做法
1 requestAnimationFrame(loop) 写在 try 里面,任何一帧抛异常就再也不安排下一帧 → 永久静止 每帧先把下一帧安排出去schedule())再干活;try/catch 只保护当前帧;另有 1.5s 看门狗:帧号不动就自动复活循环、补挂 DOM、清掉卡住的拖动
2 命中判定用 elementFromPoint 一票否决 —— 结果落在别人身上时永远拖不动 判定分两段:本体中心区域永远可抓(保证拖动可用);只有边缘区域才让位给压在上面的元素(不抢输入框/别的挂件的点击)
3 pointerdown 只挂 document 捕获,容易被别的挂件吞掉 同时挂 window 捕获(比 document 捕获更早),且只在真的抓住时才 stopPropagation,其余情况原样放行
4 NodeList.forEach 绑面板标题栏 —— 一处抛错整段事件绑定全废 for 循环;setPointerCapture 挪到所有关键步骤之后(它抛异常不再连带跳过监听注册)

拖动链路本身(窗口捕获按下 → 跟手 → 松手按最后 90ms 位移算冲量)在真浏览器里实测:按住跟手位移与光标一致、松手冲量生效、飞出去撞四边回弹。

玩法与设置

右键本体弹出设置面板(标题栏可拖动;面板打开期间本体物理冻结,但仍然可以拖它)。

面板 内容
主面板 弹性(软/标准/弹)、大小、零重力、钉住、待机动作、判定框、token 玩法开关、重新撒币、清零重计、回原位、换个角落、收起
token 设置 玩法 / 可吃 / 手动吃、漂浮动画 / 爆币粒子 / 计分牌、连吃翻倍 / 高光时刻 / 不补位 / 判定圆;数量、补位时长、生成时长、token 大小、黄币概率、combo 窗口、得分倍率
  • 生成时长:0 = 一次性撒满;>0 = 慢慢撒出来。
  • 不补位:吃光即止,不再刷新。
  • 音效:吃到 token 播泡泡破裂声(黄币音量 = 蓝币 × 1.5);撞屏幕四边 / 地板播卡通 Q 弹碰撞声(撞得越狠略响一点)。两个 mp3 内联在产物里,首次用户手势时解锁并预解码。
  • 币不会撒在本体脚下(避免开局就自动吃币),也不会撒进底部聊天栏区域。

实现

client.js       客户端源码(注入页面执行,图在打包时内联)
client.dist.js  打包产物(mk.mjs 生成);宿主每次请求实时读它
lib/index.js    宿主插件(mk.mjs 生成,不要手改):三条路由 + tapIndex 注入
                /dsh-ricewhale/widget.js(实时读盘)· /ui-font.ttf · /video/eat-rice.mp4(支持 Range)
assets/         五张透明 PNG(爬行 / 站姿 / 蓝币 / 黄币 / 白饭)+ 字体 + 吃白饭视频 + 两个音效(sfx-pop 吃币 / sfx-bump 撞墙)
src/            原始素材(rice-src.png 等)
mk.mjs          打包:内联五张图 → 子集化字体 → 生成 client.dist.js 与 lib/index.js
ttf-subset.mjs  字体子集化(1.6MB → 53KB 内联)
backup.mjs      版本快照工具(可选,见「本地版本快照」)
tools/          无头 Edge(CDP)实测:测试页、serve、cdp、白饭实测、rice 抠图

改完客户端逻辑重新打包:

node mk.mjs

白饭系统(不可设置)

一句话:每吃满 500 个 token 冒出一碗白饭,场上停 10 秒,撞到就把总分(本局 + 累计)砍掉一半。

  • 不能设置:设置面板和 token 设置里都没有它的开关(有测试盯着这条)。
  • 出现条件:累计吃掉 500 个 token 出 1 个;被吃掉或自己消失后,再吃满 500 个才出下一个。
  • 寿命:场上停留 10 秒,剩 2 秒开始变淡,到点自己消失并提示"白饭凉了"。
  • 大小:跟随"token 大小"滑块 —— 白饭宽度 = token 直径 × 1.5。
  • 跟着 token 玩法开关:关掉 token 玩法,白饭立刻收走(重新打开才继续计数)。
  • 吃到:本局分与累计分各 -50%(四舍五入),连吃清零;屏幕中央弹出 「白饭时刻」 提醒(跟高光时刻同一套动效,配色是白色泛光), 随后播放 assets/eat-rice.mp4居中、完整显示不裁切(1:1 素材在 1920×1080 屏上是 1080×1080,左右留黑边), 音轨过一级压缩后放大 3 倍(原音轨响度只有 -41dB,直接放几乎听不见),播放期间其它音效全部静音;点任意处或按 Esc 跳过。
  • 命中判定和 token 一样走圆-矩形最近距离,不会因为鲸鱼动得快而穿过去。

素材处理:src/rice-src.png(原图,自带透明通道)→ node tools/cut-rice.mjsassets/rice.png(260×215,25KB)。 (该脚本用到 sharp,已列在 devDependenciesnpm install 后可用;只跑插件不需要它。)

本地版本快照(可选)

backup.mjs 是开发时留回滚点用的工具,跟插件运行无关;快照目录不进版本库(见 .gitignore)。

node mk.mjs                        # 构建产物(不会自动留快照)
node backup.mjs --note "改了什么"   # 留一份快照到 backups/<时间戳>/
node backup.mjs --list             # 看所有快照(标出 构建前/构建后/手工)
node backup.mjs --final --note "最终版"   # 标记一版为「确认的最终品」
node backup.mjs --prune            # 只列出可清理的旧快照(不删)
node backup.mjs --prune --yes      # 真删(还需在终端里手动输入 yes)

回滚某个快照:照 backups/<时间戳>/RESTORE.md 里的命令复制回去,然后刷新浏览器即可 (宿主每次请求实时读 client.dist.js,只有 lib/index.js 的路由/注入变了才需要重启宿主)。 每份快照装的是哪一版,看 backups/NOTES.md

验证

node test-host.mjs     # 宿主侧:导出 / 路由(含视频 Range)/ 注入去重 / 热读 / 图片·字体内联 / 构建规则回归
node test-dom.mjs      # 客户端(Node + 最小 DOM 沙发):拖动链路、面板拖拽、不抢别人点击、白饭、诊断接口

真浏览器实测(无头 Edge + CDP,本机已验证):

node tools/serve.mjs . 4320
# 起无头 Edge:--headless=new --remote-debugging-port=9222 --user-data-dir=<任意> --autoplay-policy=no-user-gesture-required
node tools/cdp.mjs nav http://127.0.0.1:4320/tools/drag-test.html 1280 800
node tools/test-rice.mjs 4320     # 白饭 16 项:500 个触发 / 10s 消失 / 1.5 倍大小 / 减半 / 视频 / 耦合开关
node tools/cdp.mjs eval "window.__T.dragReal({dx:300,dy:-200}).then(r=>JSON.stringify(r.rec))"
node tools/cdp.mjs shot .shot.png  # 截一张图看效果

拖动测试页里有三个按钮:跑拖动实测 / 测甩出去 / 开面板,结果直接打在页面上。

拖不动时怎么查

在 DSH 页面按 F12,控制台里:

__dshwc.state()          // 就绪/是否抓住/位置速度/token/白饭/面板状态
__dshwc.diag()           // 最后一次 pointerdown、最后一次松手记录、最近日志
__dshwc.selftest()       // 在页面里真跑一遍"按下→移动 160px→松手",结果写进 document.title
__dshwc.eatProbe()       // 吃币链路体检:开关状态、本体盒、最近一枚币、是否判定命中
__dshwc.dropTokenOnPet() // 往本体正中间放一枚币并立即判定:ate=false 就是吃币坏了
  • 页面标题出现 |dshwd:{...} → 自检结果;moved 是"跟手"就说明拖动链路通。
  • 币吃不到时先跑 __dshwc.dropTokenOnPet():正常情况下应当 ate:truetokenDead:true
  • 屏幕底部出现红色「挂件循环出错 ×N(点这里重启)」→ 帧内异常,点一下即可重启循环(正常情况下不会出现)。
  • 帧内异常超过 3 次不会停摆:requestAnimationFrame 已经在 finally 之外先安排好了。

素材与授权

逐项清单与替换办法见 THIRD-PARTY.md注意:素材已经内联进产物client.dist.js / lib/index.js 各含 5 张图 + 1 份字体子集 + 2 段音效的 data: URI), 所以把 assets/package.json#files 里删掉并不能阻止它们随 npm 包发布。

  • 代码:MIT(见 LICENSE)。
  • 图片素材(鲸鱼立绘 / token / 白饭)与 assets/eat-rice.mp4:作者自备素材,MIT 只覆盖代码,再分发前请自行确认素材可用性
  • 字体assets/canger-mo.ttf(仓耳与墨 W01)及由它子集化出的 assets/ui-font-subset.ttf第三方字体,商用 / 再分发请先确认授权。 不用这个字体时删掉这两个文件即可 —— mk.mjs 会自动回退到宿主字体路由,界面照常。
  • 音效assets/sfx-pop.mp3(吃币)、assets/sfx-bump.mp3(撞墙)来自第三方音效库,再分发前请确认授权; 想换成自己的音效,直接同名替换后 node mk.mjs 即可(打包时按 data URI 内联)。

已知边界

  • 物理边界是整个视口,不避让输入框、侧边栏等 DOM 元素;本体边缘压在别的元素上时会退让(中心区域始终可抓)。
  • 每张姿势是静态图,拖动 / 旋转 / 挤压都是对同一张图的变换,不含逐帧动画。
  • 粒子硬上限 120、特效 4,且粒子节点不使用 will-change(上一版 ~140 个合成层把页面拖垮过)。
  • 计分牌固定在屏幕底部中间,不与面板抢位。

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。