npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-pet-live2d

v3.1.3

Published

Live2D 桌宠插件:为 DSH Web GUI 挂一只可拖动、会跟随鼠标、能换动作与表情的 Live2D 宠物。

Readme

dsh-pet-live2d

给 DSH(DeepSeek Harness)Web GUI 用的 Live2D 桌宠插件:一只可以拖动、跟着鼠标看、 点她会害羞、还会跟着会话状态换动作的桌宠。

自带 DS鲸鱼娘(8 组动作 + 44 个表情/道具),开箱即用。

宠物会跟着插件一起更新:随包的那只(以及它的默认设置:台词、互动反应、 会话相位、摸鱼槽位)在插件升级时自动同步到 %DSH_HOME%\pets\ds-whale-girl\。 你自己改过的那份不会被覆盖(判定是内容指纹,改过就一个字都不碰), 想拿回随包版本就把目录删掉、重启 dsh web,它会重新装一份。更新日志见 CHANGELOG.md。

界面预览:DS鲸鱼娘桌宠(大肥鱼 pet-live2d)

功能

  • 拖动 / 缩放:位置和大小记在 localStorage,重启还在
  • 跟随鼠标:视线和头部跟着指针,移开(或窗口失焦)自动回正
  • 点击反应:点头部才挥锤撒娇,点身上其它地方只出气泡
  • 事件穿透:只有角色剪影吃鼠标事件,方形画布的透明处穿透到底下的页面,不挡 DSH 的 UI
  • 跟着会话走:订阅 DSH 的真实事件(tools/* 等),思考/工具/等待/完成/出错换动作与表情, 长任务持续播放对应动画
  • 待机摸鱼:静置一会儿自己演一段(不会演「点击」「出错」这类专属动作)
  • 都会自己收尾:动作、定格、表情到点全部回到初始待机,不会卡住
  • 全都可配:20 个互斥槽位(装扮 + 表情),每个槽位一张可增删、带权重的条目表, 条目之间还能配「同时 / 前提」关系;会话相位是同一套池子机制

安装

# 从 npm 装(推荐;插件和自带宠物一起下好)
dsh plugin --profile web add dsh-pet-live2d

# 或从仓库装(# 后面是 pnpm 的 path: 协议,注意那个斜杠)
dsh plugin --profile web add "github:A8Chann/dsh-pet-live2d#path:/dsh-live2d-pet"

# 或先克隆再装本地目录
git clone https://github.com/A8Chann/dsh-pet-live2d
dsh plugin --profile web add "link:./dsh-pet-live2d/dsh-live2d-pet"

装到哪个 profile? 取决于你在哪里用它:

  • 浏览器里跑的 dsh web ⇒ --profile web(上面几条都是这个);
  • DeepSeek Harness 官方桌面客户端 ⇒ 它用的是 --profile desktop,例如 dsh plugin --profile desktop add dsh-pet-live2d。

装完重启一次(插件在启动时加载,客户端 bundle 也不做热重载)。

Cubism Core:不用手动装

live2dcubismcore.min.js 是 Live2D 株式会社的专有运行时,不能随插件分发 —— 但你也不 用自己去找:插件第一次用到它时,宿主半区会去 Live2D 官方 CDN 取一份 (校验过再发出去),并缓存到 %DSH_HOME%\pets\.runtime\live2dcubismcore.min.js,之后离线也能用。

只有当这台机器访问不了外网时,才需要手动下载 Cubism SDK for Web、把 Core/live2dcubismcore.min.js 放到上面那个路径。

宠物:随包自带

插件包里就带着一只可用的宠物(pets/ds-whale-girl/,CC BY-NC-SA 4.0)。第一次运行时 宿主半区会把它复制进 %DSH_HOME%\pets\,所以装完插件、重启 dsh web 就能看见。 只在目标不存在时复制 —— 你自己改过或换过的宠物目录永远优先,不会被覆盖。

怎么用

  • 右键点宠物 呼出面板:「动作」「装扮」两个页签,底部是大小滑杆和「归位」。 平时画面上没有常驻 UI。
  • 改配置 去 DSH 设置页 → 桌宠(面板只负责"点一下换个样子")。

设置说明

摸鱼:每个槽位一张条目表

摸鱼 = 静置一会儿之后,宠物自己换个样子。每个槽位各掷一次骰子(不是"这次只动一两个"), 条目上的权重就是"多久动一次"。

  • 一张表里的条目可以增删:+ 名字 是虚线药丸,行尾 × 删掉。 宠物给的那套只是建议,你加进来的运行时真的会抽到。
  • 摸鱼默认盯宠物声明的那几个槽位(这只宠物是七个:右手 / 左手 / 情绪 / 脸红 / 嘴部 / 眼部 / 自拍,写在 pet.json 的 live2d.fidgetSlots 里),其余槽位在卡片底部点一下就 加进来(+ 槽位)。
  • 「默认」=回到默认(把这个槽位清空)。默认 10 : 脸红 1 = 大约每 11 次摸鱼脸红一次、 其余时间回到没有。想让某个槽位完全不动,把它的条目删光或权重归 0。

会话相位:同一套池子

每个会话相位下面是"槽位 → 条目表",机制和摸鱼一样。宠物跟着 DSH 的真实事件换相位:

| 相位 | 什么时候 | 这只宠物演什么 | |---|---|---| | thinking | 模型在想 / 刚开工 | 抬头看 | | tool | 调工具(detail 带工具名) | 写本本 + 流汗 | | waiting | 有操作等你批准 | 问号 | | asking | 它问了你一个问题、在等你回答 | 举手 + 问号 | | helper | 起了子代理(一段长活) | 喵喵手 + 调皮 | | queued | 你发的话排队了(它还在忙) | 感叹号(短促一下) | | done | 这一轮说完(庆祝 3.5 秒) | 开心 + 情绪花花 | | failed | 出错了 | 大哭 + 流汗 |

来源是 agent/status、tools/pre-execute|post-execute、approval/request、 user-questions/request、subagent/start|end、agent/inbox/inserted、 agent/turn-stopping、agent/error —— 按主题折成上面这几个相位。

相位表一开始就列出全部相位,显示的是有效池子:

| 行头标记 | 含义 | 那一行有什么 | |---|---|---| | 默认 | 你没改过,用的是宠物默认 | 没有 × | | 已改过 | 你改过,用的是你的 | 有 × = 恢复默认 |

改动只在真的编辑时才落盘,所以"看一眼"不会留下覆盖 —— 以后宠物更新了默认值, 没改过的相位照样吃得到。

相位是"接管",不是"叠加":会话一开始,宠物换相位那一套样子 ——

  • 相位点名的槽位用它抽到的(thinking 就是头顶鲸 + 画笔);
  • 相位没点名的槽位一律让位(收回):你手选的掏出手机、爱心眼、自拍不会在整场 会话里一直挂着。挂在槽位上的动作(掏出手机是定格动作)也会跟着交还身体,手放下来;
  • 装扮槽永远归你:眼镜 / 发饰 / 魔爪 / 巴菲 / 桌布 / 手机换色 会话不碰;
  • 会话进行中想改也能改:手点一下会临时盖过相位的那一格(这场会话里有效);
  • 会话结束后,你原来的样子回来(让位不是删除)。

右键面板的「装扮」页签跟着相位走 —— 会话中它显示的是相位抽到的,不是你上次手选的。

互动:摸头 / 摸尾巴 / 转圈

点她身上会有反应,判定用的是模型自己的几何,不是画出来的区域:

| 互动 | 怎么触发 | 默认反应 | |---|---|---| | 摸头 | 点在头部(含头发、耳朵 —— 宿主读 cdi3 里作者的部件命名认出来的 21 个部件) | 重锤出击 / 问号 / 星星眼 随机一个,不脸红 | | 摸尾巴 | 点在尾巴/翅膀上(狐狸尾 / 猫尾 / 狼尾 / 大翅膀…15 个部件) | 吐魂 / 问号 随机一个 | | 转圈转晕 | 鼠标绕着角色转圈:默认 2 圈、1.6 秒内 | 演「晕晕」 |

  • 摸头/摸尾巴按三角面判定:圆顶带耳朵尖的头部轮廓、尾巴的边缘都对得上,不是方框。 顶点是当前帧变形后的,所以头歪着、身体摆着也准。
  • 尾巴只认"鲸鱼尾鳍"那一块:这只模型有 16 块 drawable 的名字里带"尾/翅/翼",但其中 11 块是可选配件(狐狸尾 / 猫尾 / 狼尾 / 天使翅膀…)的几何、一直留在原地、横跨全身。 全算成尾巴的话"点到哪儿都是尾巴",而摸头又优先,可见的尾鳍反而摸不到。所以尾巴是按 贴图认的:texture_00.png 上鲸鱼尾鳍那一块对应的 5 块 drawable(都属部件 尾巴(蒙皮))。
  • 可点区域跟着尾巴动:决定事件归谁的那层轮廓是开机抓一次的,尾鳍摆动时会摆出去 —— 现在尾巴有一块实时跟随的可点矩形并进轮廓里,所以摆到哪儿都点得到。
  • 摸头优先于摸尾巴:尾巴判定收紧之后两者基本不再重叠,重叠处仍然算摸头。
  • 尾巴/翅膀是可选配件:没戴的时候它们的几何是退化的,"摸尾巴"就是没反应 —— 这是对的,不是坏了。戴上尾巴(装扮槽)之后才摸得到。
  • 转圈看的是累计转角(不是位置绕了几圈),所以贴着角色转小圈、远远转大圈都算。
  • 三个互动各自可开关,反应也能改(见下)。共用的三句台词在「气泡」设置里。

上表那三组是默认反应,来源分两层:宠物 pet.json 里声明了就用它的;没声明就用 插件内置的这几个(重锤出击 / 问号 / 星星眼、吐魂 / 问号、晕晕)—— 自己做的宠物不写 这三个键也有反应。设置页「互动」卡的行尾会标明当前用的是哪一层(宠物默认 / 内置默认 / 已改过),候选勾选本来就是最高优先级。

气泡:说什么、在哪、要不要

她说话时会弹一个小气泡(问候、点击、摸头、摸尾巴、转晕、归位,以及每个会话相位一句: 思考中 / 用工具 / 等你批准 / 等你回答 / 叫了帮手 / 消息排队 / 完成 / 出错)。

  • 所有文本都能改:设置页「气泡」卡里逐条编辑。一组台词用 | 分隔多个变体 (随机挑一句);留空 = 用宠物默认(pet.json 的 live2d.lines),所以"看一眼"不会 把默认改掉。
  • 位置可调:左右 / 上下偏移两个滑杆(相对她头顶的默认位置),另有"一句话停留多久"。
  • 总开关:关掉之后任何台词都不弹。

关系:同时(pairs)与前提(requires)

条目下面缩进那一层是关系,两种刻意用不同前缀:

| 关系 | 含义 | 例 | |---|---|---| | 同时 pairs | 抽中它 / 选了它就一起点亮 | 喵喵手 → 贴纸 = 猫猫 | | 前提 requires | 必须先处于那个状态才播得出来 | 挤番茄酱 → 左手 = 蛋包饭 |

  • 两者都能加能删(行尾 ×,条目下面的 + 关系 里按「同时 / 前提」分组选目标)。
  • 摸鱼抽签时前提是闸门:前提不成立的条目不进池子。前提可能靠同一轮里别的槽位满足 (挤番茄酱要蛋包饭),所以抽签会抽到稳定为止(最多三轮)。
  • 手动点选时前提由插件补上:点「自拍」会先把手机掏出来,跟点「挤番茄酱」会把蛋包饭 端上来是同一套 —— 不会"点了没反应"。
  • 关系跟着选项走(不是池子里的某一条):同一个姿势在摸鱼表、相位池、右键面板里看到的 是同一份关系,改一处三处一起变。

装扮:穿在身上的东西

眼镜 / 发饰 / 魔爪 / 巴菲(桌面摆设)/ 桌布 / 手机换色 这六个槽位是装扮,和"这一轮临时挑的 表情"不是一回事:

| 场景 | 临时表情 | 装扮 | |---|---|---| | 会话相位开始 / 结束 | 由相位接管,相位结束就撤掉 | 不动 | | 点「归位」 | 清空 | 保留 | | 重启 / 刷新页面 | 回到默认 | 从 localStorage 穿回来 |

这只宠物有什么

44 个表情归入 20 个互斥槽位(换过宠物 / 改过配置的话,以设置页和 pet.json 为准)。 分类依据是模型作者在 cdi3 里自己写的分组和中文名(例如 ParamGroup29 被作者命名为 「C款动作开关」,里面正好是一组互斥的手部状态),不是按文件名猜的。

| 槽位 | 不选 | 可选项 | |---|---|---| | 眼镜 | 无 | 圆眼镜 / 方眼镜 / 椭圆眼镜 / 墨镜 | | 贴纸 | 无 | 猫猫 / 兔兔 / 蝴蝶结 | | 发饰 | 戴着 | 摘掉发箍 / 单边马尾 | | 桌布 | 白色 | 黑色 | | 魔爪 | 无 | 粉魔爪 / 白魔爪 | | 鲸鱼 | 无 | 头顶鲸 / 放桌上 | | 桌面摆设 | 无 | 巴菲 | | 右手 | 无 | 掏出手机 / 喵喵手 / 双手比耶 / 挤番茄酱 / 写本本 | | 自拍 | 无 | 自拍 / 快速自拍 | | 左手 | 无 | 撤回 / 画笔 / 橡皮 / 蛋包饭 | | 眼部 | 默认 | 星星眼 / 爱心眼 / 呆呆眼 / 晕晕 / 阴暗 | | 情绪 | 平静 | 开心兴奋 / 悲伤 / 大哭 / 生气 / 调皮 / 闭眼口水 / 吐魂 | | 嘴部 | 闭嘴 | 吐舌 / 吹泡泡糖 | | 符号 | 无 | 问号 / 感叹号 / 流汗 | | 氛围:花花 | 无 | 情绪花花 | | 氛围:心跳 | 无 | 心跳 | | 氛围:冒爱心 | 无 | 冒爱心 | | 脸红 | 否 | 脸红 | | 其他 | 无 | 手机换色 | | 点菜 | 无 | 点菜按下 |

一个选项可以带多个表达式(「白魔爪」= 桌面粉魔爪 + 魔爪换色),选择常驻(不会过几秒 自己消失;自动清理只留给"反应"和"会话相位")。

做一只自己的宠物

宠物放在 %DSH_HOME%\pets\<id>\,最小结构:

%DSH_HOME%\pets\<id>\
  pet.json          # 清单(renderer: live2d)
  c_0120.model3.json
  model\            # .moc3 / physics3 / cdi3
  textures\         # 贴图
  motions\          # .motion3.json
  expressions\      # .exp3.json
  catalog.json      # 可选:动作/表情的中文名与分类
{
  "petManifestVersion": 2,
  "id": "ds-whale-girl",
  "displayName": "DS鲸鱼娘",
  "renderer": "live2d",
  "license": "...",
  "live2d": {
    "model": "c_0120.model3.json",   // 相对于本目录
    "scale": 1,                      // 在自适应缩放上乘算
    "translate": { "x": 0, "y": 0 },
    // 槽位:一个槽位 = 一个互斥组,`none` 是"不选"
    "expressionSlots": [
      { "id": "eyes", "label": "眼部", "none": "默认",
        "options": [{ "label": "爱心眼", "expressions": ["爱心眼"], "pairs": { "heart": "冒爱心" } }] }
    ],
    // 会话相位 -> 槽位 -> 选项(读成"每个槽位一条、权重 1"的池子)
    "looksByPhase": { "done": { "whale": "头顶鲸", "mood": "开心兴奋" } },
    // 摸鱼默认盯哪些槽位(用户还能再加;不写就是"手/情绪/脸红/嘴/眼"那五个兜底)
    "fidgetSlots": ["rhand", "lhand", "mood", "cheek", "mouth", "eyes", "selfie"],
    // 互动反应候选(标签 = 动作的中文名或表情名)。**三个键都可以不写** ——
    // 不写就用插件内置的:摸头 重锤出击/问号/星星眼、摸尾巴 吐魂/问号、转晕 晕晕
    "patReactions": ["重锤出击", "问号", "星星眼"],
    "tailReactions": ["吐魂", "问号"],
    "spinReactions": ["晕晕"],
    // 可选;模型自己表达不了的「作者意图」
    "motionOptions": {
      "OpenCase":   { "hold": true },
      "Selfie":     { "prepend": "OpenCase" },
      "SprayWater": { "preset": { "jingyu": 1 } }
    },
    "motionGuards": { "SprayWater": { "whale": ["头顶鲸", "放桌上"] } }
  }
}
  • 动作和表情列表以 .model3.json 里声明的为准,插件启动时从模型读出 —— 换模型 / 改模型 文件立刻生效,不用改插件代码。
  • motionOptions:hold(停在最后一帧)/ persist(定格且不自动放手)/ prepend(先播前置 动作)/ preset(开播前把某些参数写死)。不写就是"播一次然后回待机"。
  • motionGuards:动作的前提,形如"槽位 = 标签白名单"。白名单形式没法自动满足,只能拦 (喷水要鲸鱼,而鲸鱼有"头顶"和"放桌上"两种)——所以"能自动补上"的前提请写在选项的 requires 上(形如"槽位 = 某一个标签")。
  • 路径片段只允许 [A-Za-z0-9._-],中文文件名会让整个宠物加载失败。

动作与表情的语义(定格 / 前置动作 / 参数还原 / 表情叠加)见 skill cubism-engine。

宿主 HTTP 接口

| 方法 | 路径 | 说明 | |---|---|---| | GET | /api/live2d-pet/catalog | 已安装宠物 + 各自的动作/表情清单 + 运行时 URL | | GET | /api/live2d-pet/asset/<id>/<path> | 只服务 model3.json 引用闭包内的文件(白名单 Set 比对 + realpath 包含,.. 永远匹配不上) | | GET | /api/live2d-pet/runtime/live2dcubismcore.min.js | Cubism Core:本地有就发本地的,没有就去 Live2D 官方 CDN 取一份并缓存(x-live2d-core-source: cdn);两边都拿不到才 502 | | GET | /api/live2d-pet/runtime/live2d-vendor.js | 插件内置的 MIT vendor 分包(pixi.js + 引擎),按需懒加载 |

API 与资产路由默认只答本机回环请求。

架构与二次开发

dsh-live2d-pet/
  package.json          dsh.client.platform = web -> 双半区包
  cordis.patch.yml      bundle patch:插一行 live2d-pet
  lib/
    index.js            宿主半区:宠物发现 / 引用闭包资产路由 / 运行时分发
    client.js           浏览器半区:手写 __ModuleLoader__ 工厂,无构建步骤
    live2d-vendor.js    pixi.js + untitled-pixi-live2d-engine 的 IIFE(esbuild 产物)
  src/vendor-entry.ts   vendor 分包入口(npm run build:vendor 重新生成)

Vendor 分包懒加载:只有真正挂载宠物时才注入,页面首屏不为它买单。

npm install             # pixi.js / engine / esbuild
npm run build:vendor    # 改动 src/vendor-entry.ts 或升级依赖时

改完 lib/client.js 重启 dsh web(bundle 不做热重载)。回归测试在仓库的 tools/browser-test/:无头 Edge + CDP,在真实 WebGL 里跑 16 个 driver 的完整契约。

cd ../../tools/browser-test && npm install && npm run suite

开发记录不在这个 README 里:踩坑、测量陷阱、帧序、验证写法按主题放在仓库的 .dsh/skills/ 下(cubism-engine / client-state / verification-signals / browser-cdp / docs-and-workflow),入口见仓库根的 AGENTS.md。 用户可见的变化写 CHANGELOG.md。

排查

宠物根节点上挂着诊断读口(window.__dshLive2dPet),常用几个:expressions()(当前钉住的 表情)、slotSelections()(各槽位选了什么)、drawn(id)(这一帧真正写进模型的参数值)、 fidgetTally()(摸鱼抽签统计)、effectiveRelations() / settingsOverrides()(有效关系与 存档覆盖)、ambientDebug() / keptPoseDebug()(氛围回放与姿势保持的内部状态)。

交流群

大肥鱼 pet-live2d 交流群 —— QQ 群号 974641848:装不上、模型不对劲、想投稿自己的宠物, 都欢迎进群说。群二维码在仓库 README 的「交流群」一节。

许可

  • 插件代码:MIT

  • vendor 分包:pixi.js(MIT)+ untitled-pixi-live2d-engine(MIT),可随包分发

  • Cubism Core:Live2D 专有,不随包分发;缺失时由宿主半区从 Live2D 官方 CDN 取一份并缓存到本地

  • DS鲸鱼娘模型:CC BY-NC-SA 4.0(署名 · 非商业 · 相同方式共享),见 pets/ds-whale-girl/LICENSE。

    版权链:上善无形(鲸鱼娘角色原作,原创 OC「溟月」)→ ZipZipPipe(DeepSeek 女仆二创) → 氵六青(本模型)。氵六青已授权本项目转载开源,但该授权不解除基础版权, 所以 NC / SA 依然有效;商业使用需分别取得三人授权。完整说明见 ../NOTICE.md。