鱼皮AI导航
鱼皮AI导航
  • 主页
  • 社区
  • AI工具
  • AI知识库
  • AI提示词
  • MCP
  • Skills
  • AI学习资源
  • AI资讯
  • GitHub开源
登录/注册

dsh-pet

常驻界面的鲸鱼娘:随智能体状态切换动画,可摸头互动、喂小鱼干养亲密度,从幼鲸一路养成。

娱乐
访问 GitHub
文档README

dsh-pet · DeepSeek Harness (DSH) 桌面宠物伴侣与 Live2D 互动挂件插件

English | 中文

 

 

DeepSeek Harness(DSH)官方 Web GUI 与桌面客户端专属桌面宠物伴侣生态

智能体思考跟随 · Live2D / 精灵图桌宠 · 摸头喂食互动 · 实时状态气泡 · 创意工坊宠物下载

一个注册表驱动的桌面宠物伴侣:内置萌系鲸鱼娘,同时支持从创意工坊一键下载安装任意 Live2D 与精灵图桌宠。

模型思考时你在等待,你的桌面宠物在屏幕上畅游交互。它深度跟随 DeepSeek Harness 官方智能体会话生命周期,在空闲等待、模型思考、调用工具(Bash / 代码编写 / 网页检索)、整理回复、庆祝完成与报告失败时自动无缝切换动画;你还可以随时摸摸头、喂食小鱼干互动,看着专属亲密度与等级不断提升。桌面宠物基于资产注册表驱动而不是硬编码:每只宠物只需一份 pet.json manifest 加一张贴图集(或 Live2D 动作模型包),宿主启动时自动发现并支持热切换。

从桌面应用的经典宠物系统重构演进,完美适配官方 DSH 插件形态(cordis bundle:host 宿主半区 + client 浏览器半区一站式融合)。

功能

功能说明
多宠物注册表宿主扫描内置 assets/、hatch-pet 自定义宠物目录和组合配置条目;每只宠物 = manifest + 图集
设置中选择宠物插件设置卡片列出所有已注册宠物(内置资产 + 用户目录,即已安装集合);切换即持久化,精灵立即更换。卡片位于一级设置分区「宠物」
每只宠物独立命名在悬浮面板改名;每只宠物保存自己的名字(按宠物 id 存储,旧版平铺名字自动迁移)
状态动画官方会话活动 → manifest 定义的 9 态轨道序列;每条轨道播完自身完整时长后切换,整条序列循环
摸头互动点击宠物 → 气泡反馈 + 亲密度 +1(10s 冷却)
喂食悬浮面板 喂食 → 消耗 1 条小鱼干 + 亲密度 +5(30s 冷却)
小鱼干经济库存(上限 20):每工作 30 轮 +1,每 300 分钟(5 小时)+1 —— 获取难度为原来的 10 倍
亲密度每完成一轮 +1;9 级:幼鲸 → 伙伴 → 挚友 → 深海羁绊 → 心有灵犀 → 传说羁绊 → 神话羁绊 → 永恒之契 → 鲸生共渡(上限 999,999,999)
拖动按住拖动宠物换位置;位置持久化
隐藏/召唤悬浮面板位于宠物下方(下方空间不足时上移到状态气泡之上)并提供 隐藏;隐藏后出现 召唤{name} 按钮
妙语库内置默认妙语库(每类事件 10 句)+ 宠物自定义台词;成功文案按持久化成功次数轮换,冷却文案按持久化拒绝次数轮换
状态气泡默认只有一个顶层会话说话——上报 GUI 当前会话时优先它,否则是最近活动的一个——其余会话收进主气泡右上角的 +N 角标,不再叠出一长列;悬停气泡(触屏点按角标)即可向上展开所有会话的气泡,点击任一气泡跳转到对应会话;子代理会话借由其发起会话体现,不占用独立气泡;瞬时互动反馈临时优先。气泡文案按场景准备了大量轮换词库(等待 / 思考 / 整理 / 完成 / 失败……),工具调用按工具族映射俏皮文案并带上真实参数(如 跑跑 npm test),同一场景持续数秒会自动换一种说法
碎碎念会话流式输出期间,宠物会偶尔借该会话自己的气泡说出内心独白——新鲜的碎碎念接管所属会话的气泡并以「」引号标记——与状态气泡共用同一片 DeepSeek 蓝黑玻璃,气泡栈内颜色统一不再色差——不再叠出第二只气泡——分类台词由「正在干什么」触发(思考 / 写回复 / 正在跑的工具族),结果台词只由结构化结果触发(测试工具通过 → 全绿、工具失败 → 报错、回合完成 → 收工)——决不读模型说的话,讨论里提到关键词也不会误触发心境;碎碎念也从不引用真实内容(无工具名、路径、模型原文);分类冷却 9 秒、结果冷却 5 秒,展示 8 秒后气泡恢复状态文案
多会话活动宠物是宿主全局的:最近一次有意义事件驱动精灵动画,同时每个活动的顶层会话用自己的气泡报告各自状态;每个会话(含子代理)完成的轮次都计入亲密度与小鱼干
语音包与面板 DIY宠物目录 voice.json + 全局 $DSH_HOME/pets/.voice.json 覆盖气泡全部文案与悬浮面板(按钮标签/统计格式/按钮显隐);合并优先级 宠物自带 > 全局 > 内置,坏包警告不拒载

宠物契约

一只宠物 = 一个目录 + 一份 pet.json manifest + 一张图集。除此之外什么都不需要——不用改任何宿主或客户端代码。

▼
jsonc
复制代码
{ "id": "whale-girl", // 唯一的小写 kebab id "displayName": "鲸鱼娘", // 显示在设置选择器与面板上 "description": "一只软萌治愈的鲸鱼娘。", // 可选 "spritesheetPath": "spritesheet.webp", // 图集,相对 manifest 所在目录 "cell": { "width": 192, "height": 208 }, // 可选;默认 Codex 契约 "columns": 8, // 可选;默认 8 "spriteVersionNumber": 1, // 可选;2 表示 11 行 v2 图集(9 行动画行 + 2 行视线跟随行) "frames": [6, 8, 8, 4, 5, 8, 6, 6, 6], // 可选的每行帧数 "tracks": { // 可选的每轨节奏覆盖 "idle": { "durations": [400, 400, 500, 400, 400, 500] } }, "sequences": { // 可选的每场景轨道序列(每条至少 5 项) "thinking": ["running", "running-right", "running", "running-left", "waiting"] }, "remarks": { // 可选妙语(每个槽位一行或多行) "pet": "摸摸水獭的头~", "feed": ["小鱼干真香", "再来一条~"] } }
  • 图集是 8 列 × 9 行网格(默认 192×208 单元格);行序固定:0 idle、1 running-right、2 running-left、3 waving、4 jumping、5 failed、6 waiting、7 running、8 review。未使用的格子保持全透明。v2(Codex)图集在 manifest 里声明 "spriteVersionNumber": 2,共 11 行——同样的 9 行动画行外加末尾 2 行视线跟随行;插件渲染这 9 行动画行、忽略视线行。
  • 可选 remarks 块覆盖宠物在 pet(摸头)/ petCooldown / feed(喂食)/ feedCooldown / noTreats(缺粮)事件上的气泡台词。每个槽位接受一句或一组台词;声明过的槽位只替换该槽位的内置默认池。成功与冷却池使用对应的持久化成功或拒绝次数,noTreats 则独立轮询。社区贡献就是这样给自家宠物配上专属妙语的。
  • frames 记录每行用到的列数(缺省按 hatch-pet 契约表 [6, 8, 8, 4, 5, 8, 6, 6, 6]);tracks 按动画覆盖每帧时长(按该行帧数循环补足)、loop 与 fallback(默认:全部循环;jumping 与 failed 停在最后一帧后回到 idle)。
  • sequences 可选地把活动场景(idle / waiting / thinking / tool / review / done / failed)映射到至少 5 条动画轨道。每项按 tracks 中的时长播完所有帧后进入下一项,整条序列循环;未声明的场景保持标准单轨播放。

清单 v2(宠物中心,#623)

宠物目录的 pet.json 在 v2 中显式声明渲染器:

  • petManifestVersion: 2(缺省 = v1,按 sprite2d 兼容读并给出迁移提示);
  • renderer:"sprite2d"(上文图集契约)、"live2d" 或 "frames2d";
  • license(v2 必填):资产授权标识——社区宠物必须携带来源声明;
  • 渲染器专属块:sprite2d(spritesheetPath/cell/columns/atlasRows/frames/tracks)、live2d(model/motions/expressions/hitAreas/scale/translate)或 frames2d(dir/defaultFrameMs/tracks/phases——目录式帧序列)。

校验纪律:结构 fail-closed(未知字段或未知渲染器直接拒载并给出诊断),sequences/remarks 内容维持 warn-and-drop。机器可读 schema 见 contracts/pet-manifest-v2.schema.json,权威校验器为 src/manifest-v2.ts。迁移 v1 清单:node scripts/dsh-pet-migrate-v2.mjs <dir> --write(默认 dry-run;保留 pet.json.v1.bak)。

宠物的来源(后注册的来源在同 id 冲突时覆盖前者):

  1. 内置:本包 assets/<dir>/pet.json。
  2. legacy 自定义宠物:${CODEX_HOME:-~/.codex}/pets/<pet>/pet.json —— hatch-pet 流水线把产物放在这里,孵化的宠物无需任何接线即可出现在选择器里。
  3. 宠物中心用户目录:$DSH_HOME/pets/<id>/——推荐安放位(见下方 CLI)。
  4. 组合注入:嵌入应用通过 PetConfig.pets 传入的 manifest 条目。

用 CLI 校验并安装宠物目录(零构建、零发布):

▼
sh
复制代码
node scripts/dsh-pet validate <dir> # 清单 + 资产 + Live2D 引用闭包 + voice.json node scripts/dsh-pet install <dir> # 校验通过后拷入 $DSH_HOME/pets/<id>/ node scripts/dsh-pet install <dir> --force # 覆盖同名已安装宠物

非法条目永不覆盖可用宠物:它们被跳过(设置页不再列出它们;用 node scripts/dsh-pet validate <dir> 查看目录被拒的原因)。注册表在宿主启动时构建一次;新增或修改宠物后重启 dsh web 生效。

语音包与面板定制(voice.json,宠物中心 M4,#677)

气泡里的状态/工具/碎碎念文案与悬浮面板的按钮/统计文案,都可以被一只宠物(或你本人)整体替换——宠物不再只能换图,还能换「话」与「面板」。载体是宠物目录内的可选 voice.json(随宠物分发),以及全局覆盖文件 $DSH_HOME/pets/.voice.json(不改宠物目录即可换词)。

▼
jsonc
复制代码
{ "voicePackVersion": 1, // 可选;缺省视为 1 "status": { // 状态池:键 = 场景 id,逐键覆盖内置池 "done": ["搞定收工~", "交差!下一位"] }, "tools": { // 工具池:键 = 工具族;允许 {tool} / {hint} "shell": ["跑跑 {hint}", "敲回车!{hint}"] }, "toolRemaining": ["后台还有 {n} 位小助手"], // 允许 {n} "whispers": { // 碎碎念:按键替换内置池 "categories": { // 分类池;显式空数组 = 静音该分类 "thinking": ["让我想想……"], "running": ["正在跑,我盯着"] }, "results": { // 结果池(测试全绿 / 报错 / 完成) "pass": ["全绿!"] } }, "panel": { // 悬浮面板(每槽未声明时回落插件 i18n 文案) "labels": { "feed": "投喂", "hide": "藏起来", "rename": "起名字", "confirm": "好的" }, "stats": { "rank": "好感 {rank}", "treats": "鱼干 ×{n}", "points": "{points} 分" }, "actions": ["feed", "rename", "hide"] // 子集(按规范顺序);省略 = 全部;[] = 只显示统计行 } }
  • 合并优先级(逐槽):宠物自带 voice.json > 全局 .voice.json > 内置文案。status/tools/whispers 逐键合并、panel 逐槽合并,任何层缺失的槽位回落下一层。
  • 占位符白名单:tools 允许 {tool} / {hint};toolRemaining 允许 {n};panel.stats 允许 {rank} / {n} / {points};status、碎碎念与面板标签不允许任何占位符(含非法占位符的行被警告丢弃)。
  • 上限(warn-and-drop):每池 64 行以内、每行 160 字符以内;面板标签 40 以内、统计 80 字符以内。
  • 坏包不影响宠物:voice.json 不是合法 JSON 或根不是对象 → 警告并整体忽略;其余问题逐槽警告丢弃。node scripts/dsh-pet validate 会把结构错误判为安装失败、内容问题列为警告。
  • 语义细节:status/tools 的空池回落内置文案(场景行始终有话说);whispers 的显式空数组是静音(关掉该通道);面板 actions 为空数组 = 三个按钮全部隐藏;未覆盖的按钮/统计继续使用插件双语字典。旧的 whispers.generic / whispers.rules 字段已不再支持,会被忽略并给出警告。

Live2D 宠物(renderer: live2d)

Live2D 宠物经 PixiJS/WebGL 渲染:MIT 许可的 pixi.js + untitled-pixi-live2d-engine 栈以按需加载的 vendor 分包随插件内置,纯 sprite 用户永不下载、永不解析它。本插件永不内置、永不代下 Cubism Core 运行时——Live2D 专有许可不允许再分发。启用 Live2D 宠物:

  1. 自行从 Live2D 官方渠道获取 Cubism SDK for Web(你自行同意其许可),取得 live2dcubismcore.min.js;
  2. 放到 $DSH_HOME/pets/.runtime/live2dcubismcore.min.js——插件把它连同自带的 vendor 分包一起提供给页面;
  3. 安装 Live2D 宠物(含 pet.json v2、renderer: "live2d" 与模型文件的目录)。

core 缺失时,Live2D 宠物在渲染位置给出安装指引卡;sprite2d 宠物不受影响。法律提示:本插件属 Live2D 术语下的「可扩展性 APP」——你公开发布基于可加载用户模型的衍生作品时,可能不论规模都须与 Live2D 签订发行许可;发布前请自行评估义务。

Live2D 清单把七个活动相位映射到模型的动作组:

▼
json
复制代码
{ "petManifestVersion": 2, "id": "my-live2d-pet", "displayName": "My Live2D Pet", "license": "CC0-1.0", "renderer": "live2d", "live2d": { "model": "model/my-pet.model3.json", "motions": { "idle": "Idle", "thinking": "Think", "failed": "TapBody" }, "hitAreas": ["Body"] } }
  • model:相对宠物目录的 .model3.json 路径。模型引用的一切文件(moc、贴图、动作、物理、姿态、表情)都必须放在目录内——宿主恰好只服务这个引用闭包。
  • motions(必填,且必须含 idle):相位 → 动作组。未映射的相位与模型缺失的组一律回退 idle;组内有多条动作时随机播放一条。官方 Cubism 示例模型只带 Idle 与 TapBody 两个组。
  • expressions(可选):相位 → 表情名,叠加在动作之上。
  • hitAreas(可选):点击落在列出的命中区时播放模型的 TapBody 组,播完回到当前相位的动作组。任何点击仍计入摸头——交互经济与 sprite2d 一样由 chrome 掌管。
  • scale / translate(可选):模型自动适配显示盒;scale 在适配结果上乘算(默认 1,范围 (0, 10]),translate 以中心为基准做像素偏移。

模型授权:Live2D 官方示例模型(Hiyori、Haru 等)仅供评估、禁止再分发——只发布你有权的模型(原创作品或宽松授权的模型)。

Frames2d 宠物与玩法(renderer: frames2d)

frames2d 宠物不用图集,直接交付目录式帧序列:thumb/<track>/<frame>.webp,帧时长取文件名 _<ms> 尾缀或轨道的 frameMs 列表(默认 200ms,范围 16–5000)。清单把七个活动相位映射到轨道;drag 轨道跟随外壳的拖拽手势;非循环轨道播完进入 fallback(默认 idle 轨道),入睡/睡熟这类"引子 + 循环"拆分(sleep-intro → sleep)就是纯清单数据。

frames2d 块还可声明 skins(皮肤):可选的 { id, label, idleTrack } 数组。选中某皮肤后,宠物"回待机"的目标(idle 相位、未映射相位、以及一切回 idle 的 fallback)都切到该皮肤的 idleTrack——休息外观随皮肤切换,而玩法轨道(shy/work/sleep…)仍挂在默认资产上。每个皮肤还可声明 clickActions——仅对该皮肤生效的概率掷骰点击反应({ track, probability, phrases? }):皮肤激活时点击按声明顺序依次掷骰,命中则播一次命中轨道,未命中回落普通点击加成(绝不落入默认触摸分区)。

frames2d 宠物可声明 gameplay 块——从 miku 桌宠泛化而来的可选玩法层:属性条(stats,按分钟衰减,另有打工中与空闲变体)、统一的小鱼干货币(玩法收入与商店支出都走宠物面板那条小鱼干库存,上限 20 条:work 成功、passiveIncome 与彩票奖品发放小鱼干,商品也以小鱼干标价扣款,无独立钱包页)、加权 idleDirector(每 intervalMs 掷骰演出小动作,连续落空 maxMiss 次必演)、hitBox 内的 touch 触摸分区(分支掷骰:效果 + 轨道保持 + 台词气泡)、work 打工循环(宿主裁决 tick,成功/失败结果轨道)、sleep 睡觉循环(惰性恢复)、modes 命名模式(work/sleep 之外的模式各有自己的菜单按钮、label / activeLabel 与可选的周期属性恢复)、roam 随机漫游(慢周期掷骰后按四个方向之一走随机距离,位移由浏览器半侧负责,落点与拖拽同一条持久化路径)、passiveIncome 被动收入,以及 shop 商店(商品可带效果或分档抽奖)。所有掷骰与记账由宿主权威裁决(POST /api/pet/gameplay/*),状态按宠物持久化在 pet.json,沿用小鱼干经济的惰性结算纪律。浏览器半侧为声明了该块的宠物自动渲染玩法菜单卡(属性条、每个已声明模式一个按钮、皮肤选择、商店网格)。精灵显示尺寸范围为 32–1024 px。

Miku 宠物(stushansusu 涂山苏苏以 MIT 贡献;初音未来角色权利归 Crypton Future Media,受 Piapro 角色许可约束——见 THIRD_PARTY_NOTICES.md)是 frames2d 玩法的参考实现。它只经创意工坊分发(不打进 npm 包):从工坊宠物列表安装后落在 $DSH_HOME/pets/miku/。

状态装饰(decoration.json,宠物中心 M5,#567)

宠物状态气泡里的文字之前可以有一个小的状态装饰(内置:喷水鲸鱼),由 ActivityPhase 流驱动换帧。装饰与宠物相互独立:独立描述符、独立 id、独立目录,换宠物不换装饰。入口资产只收 PNG/WebP 单行精灵条带(不收 SVG/CSS);气泡自身的 role=status/aria-live(或会话气泡按钮语义)永远保留,装饰 aria-hidden;prefers-reduced-motion 时停在帧段首帧,资产加载失败只消失装饰、文字照常。

▼
jsonc
复制代码
{ "decorationManifestVersion": 1, "id": "whale", // 唯一小写 kebab id "displayName": "喷水鲸鱼", // 可选 "license": "MIT", // 必填:资产授权(社区装饰必须携带来源声明) "entry": "whale-frames.png", // PNG/WebP 单行条带,相对本目录 "cell": { "width": 64, "height": 48 }, "columns": 4, // 条带帧数(1..16) "frameMs": 160, // 常量帧时长;或用 "durations": [..] 逐帧覆盖 "loop": true, "phases": { // ActivityPhase 七态 -> 帧段(含端点);"hide" = 不显示;缺省 = hide "idle": "hide", "waiting": { "from": 0, "to": 1 }, "thinking": { "from": 0, "to": 3 }, "done": { "from": 2, "to": 3 }, "failed": { "from": 3, "to": 3 } } }
  • 结构 fail-closed(未知字段、越界尺寸、非 PNG/WebP 入口直接拒载并进诊断),帧段内容 warn-and-drop。机器可读 schema 见 contracts/status-decoration-v1.schema.json,权威校验器为 src/decoration.ts。
  • 来源:内置 assets/decorations/ + 用户目录 $DSH_HOME/pets/decorations//(同 id 覆盖内置)。资产经 /api/pet/decoration// 路由,containment 与白名单与宠物资产同构。
  • 开关:设置 → 宠物 → 状态装饰(默认开)。内置鲸鱼素材派生自 DeepSeek wordmark(MIT),完整声明见 THIRD_PARTY_NOTICES.md。

公告气泡(pet.announce)

宿主侧的兄弟插件可通过 pet cordis 服务推送一条结构化公告(ctx.pet.announce({ source, kind, title, ... }));客户端半区将其渲染为一只专用、特别设计的气泡,挂在会话气泡栈顶部——独立玻璃样式与色调描边(ok/warn/low)、余额与今日消费类金额胶囊、套餐百分比窗口带微型计量条、展示重置时间。载荷经有界校验(src/announce.ts):未知字段丢弃、超长文本截断、TTL 收敛到 1 秒 - 2 小时(默认 10 秒;周期型发布方按自身轮询节奏声明 TTL,常驻气泡因此跨轮询连续,上限仍保证失活来源的气泡至多一个刷新周期内消失),畸形公告静默丢弃。公告仅存内存:最新一条生效,过期即不再渲染,不触碰 pet.json 与台账。刻意不提供 HTTP 面——按跨插件协作规则,API 就是进程内服务。

内置宠物

注册表 id选择器名称来源
blue-throated-bee-eater蓝喉蜂虎贡献者以 Apache-2.0 贡献的伙伴插画(12 张同角色 AI 立绘素材,配色取蓝喉蜂虎皮肤同源;由 docs/archive/blue-throated-bee-eater-pet/gen-pet.py 组装,各轨道独立姿态:栖枝/飞行/正面悬停/挥翅/降落/垂头/歪头/昂首;饲料以「小蜜蜂」命名)
dorodoro由 stushansusu 以 MIT 许可证贡献的 frames2d 玩法宠物:11 条轨道 / 802 帧 42ms webp 序列——呼吸待机、打工三件套、睡觉、洗澡模式(心情 +3/秒)、随机漫游用的四向爬行、三个待机小动作(cola / orange / tongue)与仅拖拽期间播放的挣扎循环。Doro 是《胜利女神:妮姬》桃乐丝的非官方同人二创/梗衍生形象,角色及相关权利归 SHIFT UP 所有——仅限个人非商业使用,与官方无隶属或背书关系(见 THIRD_PARTY_NOTICES.md)。
jyn女仆鲸鱼娘frames2d 玩法宠物(stushansusu 以 MIT 贡献):带打工/睡觉/触摸玩法与三款可选皮肤(暗夜鎏金 / 蓝海霓裳 / 冰晶公主)的女仆鲸鱼同桌宠,每款皮肤各带一个概率掷骰点击动作;暗夜鎏金另将专属休息循环换入睡觉玩法
jyn-foxtail鲸鱼娘·狗尾巴草由 stushansusu 以 MIT 贡献的 frames2d 玩法宠物:剪纸风格的鲸鱼娘,13 条 3.00s 帧序列轨道(idle / tease / eat / heart / face / work / work-success / work-fail / sleep / sleeping / snack / sneeze / yawn),带点击、打工、睡觉与四个待机小动作玩法;previews/ 下每条轨道一张静态 webp 封面
ouo-nekoOUO NekoPessimist0906 以 MIT 许可证贡献的粉色樱花猫耳伙伴
whale-girl鲸鱼娘(原版)仓库原有的鲸鱼娘图集
whale-girl-refined鲸鱼娘(精致版)以鲸鱼娘设计方向为基础,经 AI 辅助二次创作、修复和细节精修的衍生版本

Miku 宠物有意不随包内置:它是 frames2d 玩法宠物,经创意工坊按需安装(见上文 frames2d 一节)。星夜人偶(Starry Doll)(Theater-ahyeon 以 CC-BY-NC-SA-4.0 贡献)同样仅经创意工坊分发:sprite2d 哥特星夜人偶,从单张插画抠像后以剪纸变换生成动画(呼吸、蹦跳、挥手、沮丧、review 态放大镜道具),从创意工坊宠物列表安装后落在 $DSH_HOME/pets/starry-doll/。Doro 宠物(内置)同样是《胜利女神:妮姬》桃乐丝的非官方同人衍生形象;角色及相关权利归 SHIFT UP 所有,素材仅限个人非商业使用——见 THIRD_PARTY_NOTICES.md。

精致版参考了 DreamSkin 的「DeepSeek-鲸鱼娘」主题。历史来源记录标注原主题作者为 powerdog996,并标注主题为 MIT:DreamSkin、仓库来源记录。此处用于记录素材来源与衍生关系;精致版不表述为原作者的官方作品,也不重新定义原始美术作品的授权范围。

人气宠物

dsh-market.com 创意工坊宠物分类里人气最高的三只宠物,按网站默认的「按人气」排序。每只都是「一个 pet.json 加素材」,由上文契约渲染——无需任何按宠物编写的代码:

宠物渲染器作者来源
鲸鱼娘(精致版)(whale-girl-refined)sprite2ddsh-web内置图集 assets/whale-refined/
Miku(miku)frames2dstushansusu(MIT)仅经创意工坊分发,安装到 $DSH_HOME/pets/miku/;初音未来角色权利归 Crypton Future Media,适用 Piapro Character License
女仆鲸鱼娘(jyn)frames2dstushansusu(MIT)内置 assets/jyn/
鲸鱼娘(精致版)Miku女仆鲸鱼娘
鲸鱼娘(精致版)Miku女仆鲸鱼娘

精灵宠物使用由 hatch-pet 流水线生成的 8 列图集,单元格为 192×208。经典图集包含 9 行动画;v2 图集额外增加 2 行,共提供 16 个观察方向。女仆鲸鱼娘改用目录式帧序列,因此它的其它玩法状态是各自独立的预览文件:

害羞工作工作成功睡眠
害羞工作工作成功睡眠

架构

▼
text
复制代码
dsh-pet/ |-- src/ | |-- index.ts # host 半区:插件入口(构建注册表、设置区、路由) | |-- registry.ts # 多宠物契约:manifest 扫描 + 归一化(内置 + 自定义宠物) | |-- service.ts # PetService:宠物选择 + 状态机 + 亲密度 + 配置 | |-- state.ts # 宠物状态机:会话活动投影 → 9 态动画 | |-- remarks.ts # 妙语库:内置默认池 + 每宠物覆盖 + 计数选取 | |-- affinity.ts # 亲密度账本(纯函数 + 冷却) | |-- treats.ts # 小鱼干库存账本 | |-- persist.ts # 持久化($DSH_HOME/pet.json:选择 + 名字 + 互动计数) | |-- routes.ts # /api/pet/* JSON API + /pet/<id>/* 静态资源路由 | `-- client/ # 浏览器半区 | |-- index.ts # 全局挂载(createRoot → body)+ 注册表拉取 + 轮询 + 接线 | |-- PetDockEntry.tsx # 全局浮层入口(document.body,始终显示) | |-- PetSprite.tsx # 由定义驱动的浮层精灵(portal + rAF + 拖动) | |-- PetSettingsCard.tsx # 设置卡片:宠物选择器 + 显示布局 | |-- sequences.ts # 完整轨道场景序列计时 | |-- spritesheet.ts # 图集几何辅助 + 轨道裁剪 | `-- pet.module.css |-- assets/whale/ # 内置原版鲸鱼娘(manifest + 图集 + 预览) |-- assets/whale-refined/ # 内置精致版鲸鱼娘注册表变体 |-- assets/ouo-neko/ # 内置 OUO Neko v2 宠物(11 行图集 + 预览) |-- assets/blue-throated-bee-eater/ # 内置蓝喉蜂虎宠物(9 行图集 + 预览) `-- cordis.patch.yml # bundle 补丁:插入宠物插件行

数据流

▼
text
复制代码
官方会话事件(turn/step/chunk/tool)----\ > PetService(宿主)<-- 注册表(内置 + 自定义宠物) 可选兼容 activity/status ------------------/ | /api/pet/* JSON 全局 React 根(createRoot → document.body)<-- 2s 轮询 -- pet-client(浏览器) | PetSprite 浮层(portal + rAF)
  • 状态来源:宿主把官方 turn/start、step/start、assistant/message、tool/call、tool/result、turn/end 事件与实时 agent/assistant-stream 增量投影为 waiting/thinking/tool/review/done/failed 状态。可选兼容 activity/status 事件仍作为输入。
  • 注册表:宿主把每份 manifest 归一化为完整渲染定义(几何、每行帧数、每轨时长),经 /api/pet/pets 下发;浏览器半区用该定义渲染任意条目,不携带任何宠物专属代码。
  • 选择与命名:petId 存于插件自身的配置——宿主据此 profile 条目生成 Pet 设置页;每只宠物的名字存于 pet.json 的 names,通过悬浮面板对当前宠物改名编辑。旧版安装的平铺 name 自动迁移到鲸鱼娘名下。
  • 显示:visible、size、right、bottom 与 bubbleScale 存在 pet.json,在设置卡片里编辑。气泡字号跟随精灵自身的尺寸(默认 160px 宠物对应 12px),bubbleScale 在此结果上再乘一个倍率,并限制在 10–24px——缩小的宠物不会顶着读不清的字(issue #1549)。
  • 多会话语义:API 与浏览器挂载都是宿主全局的,不暴露前台会话身份。并行会话各自保留投影状态:最近一次有意义事件驱动精灵动画,同时每个活动的顶层会话在独立气泡里报告自己的阶段(state 视图的 sessions 列表,最多保留最近 12 个)。子代理会话仍参与动画、计奖与单一显示气泡,但不占独立气泡位——N 个对话不会变成"N + 子代理数"的气泡堆。每个会话完成的轮次仍独立计奖;销毁会话移除它的气泡,销毁当前显示会话则回退到最近仍在活动的会话。
  • 挂载点:document.body(全局 React 根,始终显示:无会话 / 新会话 / 会话中都可见——旧挂载点 conversation.composer.dock 只在活动会话里渲染,新会话里宠物消失);组件内部用 createPortal 渲染全局浮层。根容器随插件 fiber 生命周期走:fiber 销毁时卸载 React 根、移除容器并停止轮询与设置订阅;热重载或重复注入的新 bundle 接管页面级单挂载槽,页面始终只有一个 [data-dsh-pet-root](issue #785)。
  • 渲染:CSS 精灵(background-position)逐帧动画;帧时长和可选场景序列来自下发定义。悬浮面板锚定在宠物下方,间隙由指针桥接覆盖;当视口下方空间不足时,面板翻转到宠物上方并抬升到状态气泡栈之上,两者互不遮挡。
  • 通信:浏览器 ↔ 宿主走同源 /api/pet/* JSON 端点(state/pets/interact/set-visible/set-config/set-name/set-pet);每只宠物的图集从 /pet/<id>/<spritesheetPath> 加载——插件自给自足地提供自己的 API 与资源(与 dsh-remote-web-ui 的 /api/pair 同一模式)。

安装

安装聚合全家桶 @linxin666/dsh-web-all(全部插件与皮肤一次到位),或单独安装本插件:

▼
sh
复制代码
### 从 npm 安装(推荐) dsh plugin --profile web add @linxin666/dsh-pet@latest ### 从仓库安装(开发调试) git clone https://github.com/zhu1090093659/dsh-web.git cd dsh-web pnpm install && pnpm -r build dsh plugin --profile web add link:$(pwd)/packages/dsh-pet

安装后重启 dsh web——你选择的宠物出现在界面右下角。link 模式下改代码后 pnpm build 并刷新页面即可,无需重装。

开发

▼
sh
复制代码
pnpm build # tsc -b(类型+声明)&& tsdown(node 半区 + 浏览器 bundle) pnpm test # vitest 单元/组件测试(注册表 / 事件投影 / 状态 / UI / 账本) pnpm prepare # 仅转译构建(不做类型检查,供消费者安装) pnpm typecheck # 仅类型检查

浏览器 bundle 走 window.__ModuleLoader__.load 契约;React/cordis 等从 loader 模块表解析(external);CSS Modules 由 lightningcss 以内联 <style data-plugin> 编译进 bundle。

精灵图与动画轨道校准

两套内置鲸鱼娘图集使用同一份 9 态 × 8 列契约:assets/whale/ 是原版,assets/whale-refined/ 是精致版。每张图集均为 1536×1872(8 列 × 9 行,192×208 单元格)。每行帧数、节奏与场景轮换写在各目录的 pet.json 中;未覆盖的宠物沿用 hatch-pet 契约节奏和标准单轨场景映射(行序:0 idle / 1 running-right / 2 running-left / 3 waving / 4 jumping / 5 failed / 6 waiting / 7 running / 8 review)。

OUO Neko 使用扩展 v2 契约:图集为 1536×2288,在相同 9 行动画之后增加 2 行、共 16 帧观察方向。其清单声明 sprite2d.atlasRows: 11,渲染器把最后 16 个单元格作为顺时针观察方向循环。

安全模型

  • 全部 /api/pet/* 与 /pet/<id>/* 路由默认仅限 loopback(插件家族共享围栏:loopback 套接字 + Host 头 + 浏览器同源标记):未配对的局域网客户端在任何宠物状态或图集下发前即收到 403 forbidden: loopback-only。同时装了 dsh-remote-web-ui 时,有效的已配对设备 cookie 是额外放行路径(与 api/gate 检查同一枚 cookie);未配对与已撤销设备仍 403。宠物插件不硬依赖远程插件。
  • 资产服务对宠物目录与目标文件双双做 realpath 解析;symlink 越界一律拒绝(403)。文件读入内存前按类限大小(清单 64 KB、图像 20 MB;超限 413)。
  • Live2D 模型按闭包放行:仅清单、声明的主资产与 .model3.json 引用到的文件(引用先经穿越/绝对路径/URL 形态筛查)。
  • 插件从不下载可执行文件,也从不内置 Live2D Cubism Core。
  • 清单结构 fail-closed:未知字段或未知渲染器直接拒载,而不是加载一只半坏的宠物(拒载原因可用 node scripts/dsh-pet validate <dir> 查看)。

数据遥测

浏览器半区每个 UTC 日向 dsh-market.com 发送一次匿名安装心跳:仅含一个 localStorage 随机 ID 与本包名,无其他数据。服务端只存储该 ID 的加盐哈希,不存 IP,且只暴露聚合计数。完整契约见 docs/telemetry.md。

许可证

BSD-3-Clause

娱乐

快捷安装

复制到终端去安装插件

dshplugin--profilewebaddgithub:zhu1090093659/dsh-pet

温馨提示

装插件等于在本机跑第三方代码,权限与你相同,能读文件、用凭据、访问网络,工具审批管不到。请只装可信来源,并尽量锁定 commit。

站长:程序员鱼皮 老鱼简历 商务合作 增值电信业务经营许可证
2026 鱼皮AI导航 | 沪ICP备19026706号-6
站长:程序员鱼皮 老鱼简历 商务合作 增值电信业务经营许可证
2026 鱼皮AI导航 | 沪ICP备19026706号-6
🔥热门工具
朱雀AI检测朱雀AI检测
朱雀AI检测助手朱雀AI检测助手
LovartLovart
老鱼简历老鱼简历
WritePass官网WritePass官网
面多多面多多
CursorCursor
星月写作星月写作
零感AI零感AI
墨得问题墨得问题
dsh 插件推荐
dsh-codex-pet
DSH Web 页内宠物,提供多会话任务提醒,可打开任务、停止当前轮次,并处理受支持的审批和问答请求。
dsh-tavern-v2
酒馆管理面板:多角色卡、多世界书、多预设与会话级隔离,记忆总结、角色关系网、剧情选项一键发送,另有 NSFW 模式。完整效果需同时安装伴生插件 dsh-muv-engine 与 dsh-muv-table,用于渲染状态栏、剧情选项与变量表格。
dsh-web-ui#packages/dsh-pet
常驻界面的鲸鱼娘:随智能体状态切换动画,可摸头互动、喂小鱼干养亲密度,从幼鲸一路养成。
dsh-petdex-pet
DSH Web 界面里的桌面宠物:右下角悬浮、可拖拽,随智能体活动切换精灵动画;设置页可管理大小、启停切换、图库搜索与一键安装宠物。内置 4 个全职猎人主角宠物包。
dsh-dice-game
🎲 骰子大作战 — 六种经典骰子玩法(吹牛、猜红点、猜红蓝、猜大小、猜单双、猜顺子),单人 vs AI + PeerJS 联机,全量中英双语,侧边栏入口打开游戏面板。