DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

xingheyewang-1 /

xingheyewang-1/dsh-whale-rod-cursor

Verified

🎣 鱼竿鲸鱼娘光标 —— DSH Web 的鱼竿光标:弹性绳吊着 Q 版鲸鱼娘,随鼠标甩飞/回弹,悬停变色,甩猛了尖叫,停下演「钓鱼佬又空军了」小剧场。A fishing-rod cursor companion for the DSH Web UI.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@f945bda9

🎣 dsh-whale-rod-cursor · 鱼竿鲸鱼娘光标

Listed on dsh-plugin.org License: MIT

一句话价值:把你 DSH Web 界面里那个冷冰冰的系统光标,换成一根鱼竿 —— 线上吊着只 Q 版鲸鱼娘,你甩鼠标她就跟着飞,悬停输入框会变色,鼠标一停她还自己演"钓鱼佬又空军了"的小剧场。

一个挂在 DeepSeek Harness Web 界面上的小玩具插件:

鼠标位置 = 鱼竿竿尖(默认直接把系统光标换成鱼竿),一条带弹性的绳 吊着 Q 版鲸鱼娘(当鱼饵)。鼠标一动,她被猛拽 → 甩飞出去 → 荡几下收回来; 甩猛了会冒萌语气泡(字随力度变大,最猛时和鲸鱼娘一样大), 安静下来还会补一句求饶/卖萌/生气的台词。 她还会跟着 DSH 的干活状态换姿态:平时 / 在忙 / 干完了。 悬停输入框 / 按钮 / 按下鼠标时,鱼竿会变色,让你用余光就知道"现在点得到什么"。

当前版本:v8(__WHALE_ROD_CURSOR_VER__ = '2026-09-15-v8-swingbubble',包版本 0.1.2)


一、它长什么样

   ╲  ← 竿尖钉在鼠标位置(箭头光标同朝向:竿身往右下拖)
    ╲
     │      ← 弹性绳(会随甩动拉长/回缩)
     │
    (🐳)    ← Q 版鲸鱼娘 = 鱼饵(猛拽、甩飞、Q 弹形变、荡几下收回)
     💬 "杀鲸啦!"
  • 竿子朝向:竿尖在左上、竿身朝右下延伸 —— 和系统箭头光标同一个朝向(v3 修正,v2 是倒着拿的)
  • 尺寸:整体 0.72 倍(v3 缩小一档),鱼竿与挂件一起缩;设置页可 0.5–1.2 调
  • 鱼饵沿绳方向旋转(最多 ±58°,不会翻跟头)
  • Q 弹形变:阻尼余弦振荡 amp = A·e^(-t/τ),压缩/拉伸绕角色中心发生
  • 绳末端严格接在她头顶:挂点不是画布中心,而是构建期用 jimp 扫 alpha 量出来的 "画布中线往下第一个实体像素"(当前素材是 (72,10);画布顶端到那儿有 8px 透明留白)。 Q 弹压缩的支点也改成"内容中心"。换素材只需重跑 node build.cjs,不用手改任何常数。

一·五、姿态包:平时 / 在忙 / 干完了(v6 新增)

三张姿态图都已抠好(都是上游 MIT 素材,声明见 NOTICE.md),构建期为每张分别量挂点:

姿态 素材 尺寸 挂点 什么时候用
idle 平时 keyed-idle.png 144×180 (72,10) 默认
work 在忙 keyed-work.png 159×180 (80,9) DSH 正在跑 / 或被甩得手忙脚乱
done 干完了 keyed-done.png 160×180 (80,9) 跑完了,停留 2.5 秒(可调)

两种驱动来源(设置页一键切):

  • 跟着 DSH 状态(默认):读官方客户端服务 ctx.get('sessions') 的列表快照 { current, byId },取当前会话那一行的 running 布尔值 —— 在跑 → work; 跑完 → done 停 2.5s → 回 idle。订阅 + 800ms 轮询兜底,状态一变就跟上。 服务读不到(版本差异)时自动退化成"跟着甩动",而且不会报错。
  • 跟着甩动:被甩飞 → work(手忙脚乱);荡稳了 → done(喘口气)→ idle。

性能:三张图都内嵌成三个 <image>,切换只改 display —— 不重新解码、不闪烁、 每帧零开销(只在状态真变了才动一次)。代价是 client.js 从 126.8 KB 涨到 317.9 KB (多约 180 KB base64,一次性解析;鼠标路径完全不受影响)。 将来若嫌包大,可以像桌宠那样改成宿主路由 GET /whale-rod/pose/<name>.png 按需懒加载。

二、手感:猛拽 → 甩飞 → 荡几下收回(v4 换回低阻尼)

递进刚度 + 常数阻尼(阻尼小才有甩飞感):

k_eff = k_soft + k_yank · clamp(|v_rel| / 1600, 0, 1)      ← 甩得越猛,绳子越"硬"
F     = -k_eff·(绳长差)·方向 - c·v_rel + 重力              ← c 是常数(默认 2.6)
v    *= e^(-λ·dt)          (半隐式欧拉积分)

实测曲线(冒烟测试 [7] 每次都会重新量一遍):

阶段 数值
静息悬挂 鼠标下方 83px(绳长 62 + 重力沉降 21)
猛拽 600px 的瞬间 距离拉到 538px —— 初始拉力极大
之后 416 → 228 → 444 → 333 → 42 → 97 → 85 → 83px —— 荡出去最远 481px(静息的 5.8 倍),这就是"甩飞"
匀速拖拽 1200px/s 只拖出 82px 尾巴 —— 匀速时仍跟手
极端甩 1500px 峰值 1323px,照样收回 83px,不失控飞走

想要"乖乖滑回来"就把设置里的「阻尼」调大(8 就基本不荡了);想要更疯就调小。

三、颜色 = 可交互性提示

状态 颜色 含义
默认 深海青蓝 #4FA3D1 安静待着
悬停输入框 / 可编辑区 亮青绿 #5FE3B0 这里可以打字
悬停按钮 / 链接 淡金 #F2B23E 这个能点
按下鼠标 橙红 #F2603E(闪 150ms) 点到了

判定用 closest('textarea, input, [contenteditable]') 与 closest('button, a, [role=button]'), 不写死任何 DSH 的 class 名,界面改版也不会失效。

因为"能不能点 / 能不能打字"都画在鱼竿上了,所以藏掉系统光标也不丢信息。

四、两种光标模式

模式 行为 说明
鱼竿当光标(默认) html, html * { cursor: none },鱼竿钉在鼠标位置 竿尖严格跟手、零延迟;鱼竿本身就是光标
真光标 + 拖挂 系统光标照常显示,鱼竿挂在旁边 光标语义(I 型等)原样保留

应急出口:按 Alt+Esc 一键在两种模式间切换(万一找不到鼠标了)。 另外还有三条安全网:窗口失焦 / 鼠标离开窗口 / 标签页隐藏 / 组件卸载或渲染出错 —— 任一情况立即恢复系统光标。

五、气泡:触发看加速度 + 甩飞速度,字号看力度(v3 触发 / v4 字号 / v8 触发搬进物理循环)

两条触发线并行,谁大用谁:

① 事件线(mousemove):sp = 移动速度(px/s)、acc = 速度变化率(px/s²) = 瞬时加速度
② 物理线(每帧):    relSp = |她与鼠标的相对速度|   ← 抓"被拽飞"和"惯性滑行"
  • 力度 = max(acc / 加速度阈值, relSp / 甩飞阈值);> 1 就冒泡
  • 甩得越猛 → 冷却越短 → 冒泡越勤(下限 0.7s,防刷屏)
  • 字号随力度长大:13px × 力度^1.25,封顶 ≈ 鲸鱼娘的身高(0.72 倍时约 121px) —— 所以最猛那一下的气泡能跟她一样大;气泡的 padding/边框都是 em,整颗泡泡一起长大; 长句(比如「别甩啦别甩啦,我求饶还不行吗——」)会按字数自动收一点,免得顶出屏幕
  • 力度 ≥ 3 倍阈值 → 尖叫池(13 条),三种口味随机:
    • 纯尖叫:「啊啊啊啊啊——」「呜哇啊啊啊啊——」
    • 求饶:「求你了别甩了呜呜呜——」「我错了我错了!放我下来——」「钓鱼佬饶命啊——」「我招了!我承认我是条鱼——」
    • 哭唧唧:「呜呜呜我要吐了——」「哭给你看!呜呜呜呜——」「呜——我的呆毛要飞了——」「呜呜……我再也不偷吃 Token 了——」
  • 平静之后补台词:被甩完安静下来(相对速度 <150px/s 持续 0.7s,且距上次说话 >停留时长), 补一句求饶 / 卖萌 / 生气(默认 10 条),停留 2–3 秒(默认 2.6s,可调);每次"被甩"只补一句,不啰嗦
  • 抗噪三件套:dt 下限 8ms(160Hz 高刷鼠标的单像素抖动会被放大成几万 px/s²)、 速度先做 EMA 再求导、加速度再做 EMA;停顿 >150ms 后把基准归零(当作从静止起步,抽鞭照样抓得住)

v8:气泡触发搬进物理循环(修"被甩飞却没气泡")

bug 现场:她明明被甩出去老远,却一声不吭;反而切回窗口时蹦一个巨大尖叫。

原因(三条都指向同一个错:触发点放在了错误的地方):

现象 原因
匀速快拖 → 没气泡 老逻辑只在 mousemove 里、只看加速度;匀速拖动速度大但加速度≈0,阈值永远碰不到
飞出去那半秒完全没气泡 鼠标停了就没有 mousemove 事件 —— 而她"被甩飞"恰恰发生在鼠标停之后的惯性滑行段,那段压根没有检查在跑
切回窗口反而尖叫 指针瞬移进窗口 + 基准归零 → 算出个假的"天大加速度"

修法:

  • 触发搬进物理循环(每帧都跑),强度用「她与鼠标的相对速度」relSp —— 这才是"被甩得多猛"的物理真相,匀速拖拽与惯性滑行两段全覆盖; 加速度那条(猛一顿 / 猛一停)保留,两条谁大用谁
  • 新增设置项「甩飞灵敏度」(默认 1400 px/s);原来的「甩动灵敏度」仍是加速度阈值
  • 指针重新进窗口(focus / mouseenter)时:趁她还隐身,直接吸附到新锚点, 既不会被假猛拽甩飞,也不会冒出一声莫名其妙的尖叫(位置一帧内不跳,因为她本来就不可见)

回归测试([4.8]):匀速快拖 3300px/s → 拖动中冒 28px 泡;停手后(零 mousemove)惯性滑行期再冒 19px 泡 ✔

v8:绳子在 Q 弹形变中也不会脱钩

形变是绕「内容中心」压缩的,所以头顶会随形变上/下移动(峰值可达 32px)。 以前绳末端死钉在锚点上 → 甩起来的瞬间会看起来"绳子跟头脱开了"。 现在绳末端(和气泡位置)按同一套变换算出"形变后的头顶",两者永远重合:

静置时误差        0.000px
Q 弹形变中误差    0.01px    (按下鼠标触发形变后实测)

五·五、闲置小剧场(v7 新增)

鼠标停下来(默认 6 秒)她就自己开演,台词池 20 条,主题围绕 吊鲸鱼 / 钓鱼佬 / 空军 —— 一半嘲讽、一半卖萌:

「钓鱼佬今天又空军了吧~」「空军司令您好,敬礼!」「你把鼠标当鱼漂甩,钓得到才有鬼」 「钓我?先准备一吨小鱼干再说」「要不要我给你咬一口?就一口哦」「本鲸鱼今天心情好,允许你摸一下头」

  • 台词间隔默认 7 秒,不会连着重复(记住最近说过的 5 条)
  • 优先级:尖叫 > 平静台词 > 小剧场 —— 三者共用"上次说话时刻"闸门,永远一句一句、不抢麦
  • DSH 在干活时不插嘴(work 姿态期间闭嘴,专心当"在忙的鲸鱼")
  • 鼠标一有动静就停演,重新计时
  • 池子可在设置页随便改(一行一条);不喜欢就一键关掉

六、它不会妨碍你做事

  • 整层 pointer-events: none —— 点击、选中、拖拽、快捷键全部照常
  • 每帧只写 transform 与 SVG 坐标属性,不碰任何布局属性,不会引起重排
  • 标签页隐藏时暂停 rAF
  • 套了渲染错误围栏:即使出错也只显示一行红字,绝不把异常抛给框架(避免整块 overlay 被卸载),并且顺手把光标还回去

七、安装

从插件市场 / npm(发布后可用):

# 认准 profile:本插件是 Web 端插件,profile 用 web
dsh plugin --profile web add dsh-whale-rod-cursor

从 GitHub 源码安装:

dsh plugin --profile web add git+https://github.com/xingheyewang-1/dsh-whale-rod-cursor.git

装完必须重启 dsh web(客户端 bundle 是启动时进内存缓存的,只刷新页面不够), 然后硬刷新页面。仓库里已经带了构建好的 lib/client.js,不需要任何构建步骤与授权。

本地开发版安装(本机就是这条):

# 一条命令搞定(幂等,可反复跑)
node H:\DSH_Workspace\tools\dsh-whale-rod-cursor\install-to-profile.mjs

# 它会做三件事:
#   1. 复制插件到 ~/.dsh/plugins/dsh-whale-rod-cursor
#   2. 复制插件到 ~/.dsh/profiles/web/node_modules/dsh-whale-rod-cursor
#   3. 备份并在 ~/.dsh/profiles/web/cordis.patch.yml 末尾追加 insert 条目

⚠️ 必须重启 dsh web(客户端 bundle 是启动时进内存缓存的,硬刷新不够)。 重启后硬刷新页面,控制台输入:

__WHALE_ROD_CURSOR_VER__     // 应输出 '2026-09-15-v7-theater'

看到这个版本戳 = 新代码真的生效了。看不到 = 还在跑老 bundle。

安装前的"信任信号"(插件市场收录要求)

项 说明
支持 profile web(dsh.client.platform: 'web')。终端 TUI 不受影响,装不装都不影响命令行
需要的 DSH 版本 客户端插件规范:@deepseek-ai/cordis ^4.0.1、@deepseek-ai/dsh-client-runtime ^0.1.0-rc.6(peer)
权限 无网络、无文件访问、无外部服务。只做三件事:往 <head> 插一段 CSS、在 shell.overlay 画 SVG 装饰层、读 localStorage 存自己的设置
唯一"有副作用"的行为 默认模式会隐藏系统光标(html * { cursor: none }),并给出四条恢复路径:Alt+Esc、窗口失焦、鼠标离开窗口、卸载/渲染出错
读取的 DSH 内部状态 只读 ctx.get('sessions') 的列表快照里当前会话的 running 布尔值(判断"在忙/干完")。读不到就自动退化,不影响功能
遥测 无。不发送任何数据
卸载 dsh plugin --profile web remove dsh-whale-rod-cursor + 重启 dsh web

预览

示意图

上图是程序绘制的示意图(node tools/make-preview.cjs 生成),不是真机截图 —— 真机截图见 assets/preview/screenshot.png(欢迎 PR 补充,Win+Shift+S 即可)。

⚠️ 一个坑(重要):本插件是手工放进 node_modules 的,没有写进 profile 的 package.json dependencies(桌宠 dsh-whale-girl-pet 才是靠 npm 装的)。 所以如果你哪天在 profile 目录里跑 pnpm install / pnpm prune, pnpm 可能把"不在依赖表里的目录"当垃圾清掉 —— 鱼竿会突然消失。 届时重跑一次 install-to-profile.mjs 即可复原。

八、设置(DSH 设置 → 🎣 鱼竿光标)

项 默认 说明
启用 开 想清静时一键关掉(关掉会立刻还回系统光标)
光标模式 鱼竿当光标 见第四节;也可 Alt+Esc 切
整体尺寸 0.72 鱼竿 + 挂件一起缩放
姿态包 开 关掉就永远只用 idle
姿态来源 跟着 DSH 状态 或「跟着甩动」;服务读不到会自动退化
"干完了"停留 2.5 s done 姿态显示多久(0.8–8s)
小剧场 开 鼠标停下自己开演(吊鲸鱼/钓鱼佬/空军)
停下多久开演 6.0 s 2–60s
台词间隔 7.0 s 2.5–60s,不连着重复
绳长 62 px 绳的自然长度
软跟随刚度 70 静止时只剩它 → 越大气氛越"紧"
瞬间拉力 320 甩动时额外刚度 → 初始拽力极大
阻尼 2.6 小 = 甩得飞、甩完还荡;大 = 乖乖滑回来(8 基本不荡)
指数衰减 1.2 绝对阻尼 λ
重力 1.00 沉降量 ≈ g/k
甩动灵敏度 45k 鼠标瞬时加速度阈值(px/s²)—— 抓"猛一顿 / 猛一停"
甩飞灵敏度 1400 px/s 她与鼠标的相对速度阈值 —— 抓"被拽飞 / 惯性滑行"(v8 新增)
气泡冷却上限 4.5 s 实际冷却 = 上限 ÷ 甩动强度(下限 0.7s)
气泡语录 10 条 一行一条,改完立即生效
尖叫语录 13 条 力度超阈值 3 倍时专用(纯尖叫 / 求饶 / 哭唧唧三味),字号能长到和鲸鱼娘一样大
平静台词停留 2.6 s 求饶/卖萌/生气台词的显示时长(2–3 秒)
平静台词 10 条 被甩完安静下来时补一句
小剧场台词 20 条 吊鲸鱼 / 钓鱼佬 / 空军;鼠标停下时轮播

九、开发

cd H:\DSH_Workspace\tools\dsh-whale-rod-cursor

# build 会逐张现量素材挂点(jimp 扫 alpha)→ 注入 __WHALE_POSES__ → 存档 lib/whale-anchor.json
node build.cjs      # lib/client.src.js --(注入三张素材 + 各自挂点)--> lib/client.js(并留 lib/client.js.prev 回滚点)
node --check lib\client.js
node smoke-test.cjs # 106 项冒烟测试

改逻辑请改 lib/client.src.js,不要直接改 lib/client.js(每次 build 都会覆盖它)。

smoke-test.cjs 用最小的假 DOM + 假 React 把 bundle 真跑一遍,并手动泵 rAF 帧验证行为:

  1. 模块加载协议 / 插件三件套
  2. 挂点链条:三张素材各自的 sha256 → whale-anchor.json → 产物里注入的 __WHALE_POSES__ 三者必须一致
  3. 两个插槽注册(外壳 overlay + 设置页)
  4. 几何:竿尖在 (0,0)、握把朝右下、每张姿态的绳末端都落在她头顶那一像素上(自写 SVG 变换求值器,精确到 0.001px)
  5. 姿态包:三张图都挂着且只有一张可见;喂一个假的 DSH sessions 服务({current, byId:{s1:{running}}}) 验证 在跑→work、跑完→done、2.5s 后→idle;再点设置页的「跟着甩动」按钮验证另一条驱动路径
  6. 物理:倾角夹在 ±58°、静止回落、吊线无 NaN
  7. 气泡:缓甩小字萌语 → 暴甩尖叫(字号顶到鲸鱼身高)→ 平静后补求饶/卖萌/生气
  8. 手感曲线:猛拽峰值 → 甩飞最远距离 → 收敛到静息悬挂 → 极端甩动不失控
  9. 保命:Alt+Esc 还光标、卸载后光标仍可见

它抓到的真 bug:factory 忘了 return module.exports(插件会被静默判定为"没有导出")、 页面刚打开头几秒气泡被冷却时间误伤、v3 首版阻尼太大导致"甩不飞"(用户体感反馈)、 鲸鱼娘变换里缩放挂错锚点导致头顶被抬高 25px, 以及画布顶端到头顶的透明留白让绳末端悬在半空(只能靠量像素发现,肉眼看代码永远看不出来)。 姿态包这轮它自己也踩了一次:work/done 挂点相同,测试一开始只按挂点认人 → 把两张认成同一张, 改成"尺寸 + 挂点"一起认才对。

十、已知边界 / 未来可做

  • 姿态只有 idle / work / done 三张。上游还有上百个 WebM 动作,想要"生气/开心/惊慌"这类情绪姿态得另找素材 + 走一遍声明流程
  • 目前是静态 PNG。想做动画(透明 WebM)得再走一遍素材声明流程,并且要考虑解码开销
  • 三张姿态都内嵌在 client.js 里(317.9 KB)。想瘦身就改成宿主路由懒加载
  • 只作用于 Web 界面(platform: 'web'),不影响终端 TUI
  • 藏系统光标是"整站生效"的:DSH 界面里若有个别控件自带特殊光标,也会被一起藏掉(鱼竿会替它变色)

十一、出处与授权

见 NOTICE.md。简短版:

  • Q 版鲸鱼娘形象来自 yanzwzz/dsh-whale-girl-pet(MIT), 由星河野望从预览 GIF 首帧抠图 + 缩放加工
  • Q 弹振荡 / 阻尼 / 重力的取值基准参考社区插件 dsh-think-bounce-pet(作者 9livewolf,声明 MIT), 只借公式与常数,未复制其任何代码或界面

本插件以 MIT 发布。这是社区作品,与 DeepSeek 官方无隶属关系(名字里带 dsh- 只是遵循社区命名习惯)。

—/ 5

No ratings yet

Verified DSH bundle

Commit f945bda99b75

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout