Back to home

LucasleeCN

dsh-client-ui-pet

No description

Stars
0
Language
JavaScript
Created
Aug 16, 2026
Updated
Aug 16, 2026

Introduction

dsh-client-ui-pet

DeepSeek Harness 官方 Web UI 的客户端宠物插件:在界面右下角注入一只可拖拽的桌宠, 参考 Codex Pets 的陪伴式交互与状态叠加层设计。宠物会跟随会话状态切换动作(思考 / 工作 / 完成 / 报错 / 睡觉…),支持点击抚摸、喂食、玩耍等轻养成互动,并提供一个完整的 宠物设置面板window.dshPet 开发者 API

当前内置 1 只宠物——由用户提供的状态图生成的 JPG 宠物(WebP 内嵌,免主机重启):

id宠物说明
deepseek-whale鲸鱼娘(原图)assets/deepseek-whale/ 下 8 个状态 PNG 抠背景、压缩为 WebP 后内嵌生成

手绘 SVG 内置宠(鲸鱼娘 / 橘猫 / 柴犬 / 史莱姆)已按用户要求移除; 如需恢复,取裁剪前的历史 client.js,或通过开发者工作室重新导入任意 SVG / raster 定义。

功能

Codex 式状态陪伴

宠物通过 MutationObserver 感知 Harness Web UI 的真实活动信号:

  • [data-composer-seat] / textarea 中输入 → typing(注视键盘)
  • 出现 button[aria-label="停止生成"] / [data-state="running"]thinking(思考)
  • 出现 [data-streaming]working(忙碌)
  • 运行结束 → done(完成庆祝,心情 +2、亲密度 +1)
  • 出现 [data-error]error(担心,心情 -3)
  • 空闲超过设定时间 → sleep(睡觉 + Zzz 粒子);任何活动或互动会唤醒

轻养成

  • 心情(0-100):随时间缓慢衰减,互动会恢复;低于 30 宠物会主动求关注。
  • 亲密度(0-100):只增不减,记录你们共同工作的羁绊。
  • 互动统计:抚摸 / 喂食 / 玩耍次数。
  • 数据按宠物独立保存到浏览器 localStorage

用户自定义界面

设置面板(宠物工具栏齿轮按钮)包含 5 个页签:

  1. 宠物:图库选择内置 / 自定义宠物;一键四角定位、复位、隐藏。
  2. 外观:昵称、体型滑杆、每个宠物声明自己的调色板(<input type="color"> 换色)。
  3. 行为:状态跟随 / 气泡台词 / 粒子特效 / 自动睡觉开关,入睡时间可选 1/3/5/10 分钟; 每个状态都有手动预览按钮。
  4. 养成:心情与亲密度进度条、互动统计、重置数据。
  5. 工作室:粘贴 JSON 校验并导入自定义宠物、导出当前宠物定义、管理已导入列表。

宠物本身可以直接拖拽;同时提供四角定位按钮,满足 WCAG 2.2 对拖拽操作 必须有单指针替代方案的要求。宠物可聚焦,Enter / Space 抚摸,工具栏按钮均为 44px 触控目标, prefers-reduced-motion 下自动关闭全部动画。

JPG 主图宠物(raster 模式)

不想要手绘 SVG?把一张 JPG/PNG/WebP 交给插件即可作为宠物:引擎会在图片外套上 状态动画(呼吸 / 点头 / 弹跳 / 拖拽 / 睡觉…),气泡、粒子、互动、养成与设置面板全部复用。 JPG 宠物不支持换色(保留原图配色),其余外观选项照常可用。

{
  "id": "my-jpg-pet",
  "name": "我的 JPG 宠物",
  "mode": "raster",                    // 启用图片模式
  "image": "/plugins/dsh-client-ui-pet/assets/my-pet/idle.webp",
  // 可选:为不同状态指定不同图片;缺省的状态回退到 image
  "images": { "sleep": "/plugins/dsh-client-ui-pet/assets/my-pet/sleep.webp" },
  "states": { "idle": { "hold": true } },
  "behaviors": []
}

image / images 只接受三种来源(其余会被校验拒绝):data:image/...;base64http(s)://、或 / 开头的同源路径。把图片放在本包 assets/<宠物>/ 目录下, Host 半侧会自动把它们发布到 /plugins/dsh-client-ui-pet/assets/<宠物>/<文件> (Host 半侧代码更新后需要重启一次 Harness Web 才会生效)。

免重启内嵌路线(当前 deepseek-whale 用的就是它):

python scripts\make-raster-pet.py assets\<宠物id> --name "宠物名" --embed
node scripts\embed-pet.mjs assets\<宠物id>\<宠物id>.embed.definition.json

第一条命令抠背景 / 缩放 / 压缩为 WebP 并内联成 data:image/webp;base64; 第二条把定义嵌入 lib/client.js 的内置宠物列表。同步 client.js 后刷新页面即可。

开发者完全自定义:dshPetDefinition

动作、行为、表现全部由定义数据驱动。定义是一个 JSON 对象:

{
  "id": "pudding-ghost",          // /^[a-z0-9][a-z0-9_-]{1,39}$/i
  "name": "布丁幽灵",
  "version": "1.0.0",
  "author": "you",
  "description": "示例宠物",
  "size": { "min": 64, "max": 240, "default": 112 },
  "colors": [
    { "key": "primary", "label": "身体", "default": "#c084fc" }
  ],
  // 内联 SVG 标记。颜色用 var(--dsh-pet-c-<key>, 默认色) 引用,
  // 这样设置面板的换色器会自动生效。
  "svg": "<g class=\"p-body\">…</g>",
  // 只作用于本 SVG 的 CSS:关键帧 + 状态选择器。
  // 引擎会把 data-state 同步到 .dsh-pet-root 分组和 svg 元素上。
  "style": ".dsh-pet-root[data-state=\"idle\"] .p-body { animation: pet-bob 3s infinite; } …",
  "states": {
    "idle":  { "label": "空闲", "hold": true },
    "happy": { "label": "开心", "durationMs": 1800 }
  },
  "behaviors": [
    {
      "trigger": "activity:done",   // 或数组;见下方触发器表
      "state": "happy",
      "bubbles": ["完成啦!"],
      "effect": "sparkles",         // 内置:hearts/sparkles/food/note/zzz/drop/star
      "mood": 2,                    // 心情变化
      "affinity": 1,                // 亲密度变化
      "hold": false,                // true = 事件持续期间保持状态
      "cooldownMs": 0
    }
  ],
  "interactions": {
    "pet":  { "state": "happy", "effect": "hearts", "mood": 5, "affinity": 1 },
    "feed": { "state": "happy", "effect": "food",   "mood": 12, "affinity": 2 },
    "play": { "state": "happy", "effect": "sparkles", "mood": 8, "affinity": 2 }
  },
  "bubbles": { "idle": ["我在这里~"] }
}

约定与扩展点:

  • states 必须包含 idledurationMs=0 + hold:true 表示常驻状态。
  • style 里的选择器使用 .dsh-pet-root[data-state="<状态>"] .部分类名 为不同状态绑定关键帧。
  • 表情切换:在 svg 中放置 <g class="dsh-pet-expr" data-expr-default><g class="dsh-pet-expr" data-expr="happy">,在 style 中按状态切换 display
  • effects 可扩展自定义粒子({ id: { svg, durationMs } })。
  • 开发者定义的 SVG / CSS 会经过消毒(移除脚本、事件属性和 javascript:)。

内置触发器:activity:typingactivity:thinkingactivity:workingactivity:doneactivity:errorsleepwakebirthmood:lowinteraction:petinteraction:feedinteraction:play; 另外可随时通过 window.dshPet.trigger("your:custom-trigger") 触发自定义行为。

开发者 API

window.dshPet.version                 // 插件版本
window.dshPet.listPets()              // [{ id, name, version, builtin }]
window.dshPet.registerPet(def, opts)  // 注册自定义宠物(opts.persist=false 仅本次会话)
window.dshPet.unregisterPet(id)       // 删除自定义宠物
window.dshPet.getDefinition(id?)      // 深拷贝当前/指定宠物定义
window.dshPet.selectPet(id)
window.dshPet.setState("happy", { hold: true, bubbles: false, text: "…", effect: "hearts" })
window.dshPet.trigger("interaction:pet")
window.dshPet.importPet(json, opts)   // 接受 JSON 字符串或对象
window.dshPet.exportCurrentPet()      // 返回格式化 JSON 字符串
window.dshPet.current()               // { id, state }
window.dshPet.getState()              // 当前状态名
window.dshPet.on("state", handler)    // "state" | "trigger" | "select" | "register" | "unregister"

安装

该插件是标准 dsh.client 双面包:Host 半侧为空 Loader 入口,Browser 半侧注入全部 UI。

方法 A:profile bundle(推荐)

编辑 <DSH_HOME>/profiles/web/package.json

{
  "dependencies": {
    "dsh-client-ui-pet": "file:D:/Softwares/CodeSoftWares/Agents/dsh-client-ui-pet"
  },
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-client-ui-pet"
      ]
    }
  }
}

安装依赖后重启 DeepSeek Harness Web(已打开的页面刷新即可)。

方法 B:手动插入 Loader 行

  1. 将插件目录复制到 <DSH_HOME>/profiles/web/node_modules/dsh-client-ui-pet

  2. 编辑 <DSH_HOME>/profiles/web/cordis.patch.yml

    - insert:
        - id: ui-pet
          name: 'dsh-client-ui-pet'
          config:
            enabled: true
    
  3. 刷新 Harness Web 页面(或重启 Web)。

验证:右下角出现 DeepSeek 鲸鱼娘,点击可抚摸,悬停出现工具栏,齿轮打开设置面板。

目录结构

dsh-client-ui-pet/
├─ package.json
├─ cordis.patch.yml
├─ LICENSE
├─ README.md
├─ lib/
│  ├─ index.js                # Host 半侧(assets 静态资源路由)
│  └─ client.js               # Browser 半侧(引擎 + 内置鲸鱼娘 + 面板 + API)
├─ assets/
│  ├─ README.txt              # 图片放置说明
│  └─ deepseek-whale/         # 鲸鱼娘(原图)素材 + 生成的 WebP + 定义 JSON
├─ scripts/
│  ├─ make-raster-pet.py      # JPG/PNG → 抠背景 → WebP → 定义 JSON
│  ├─ embed-pet.mjs           # 把 --embed 定义写入 client.js 内置列表
│  ├─ prune-builtins.mjs      # 移除手绘 SVG 内置宠(保留 raster 槽)
│  ├─ verify-live.mjs         # CDP 真机探针(8787)
│  └─ verify-raster-live.mjs  # CDP raster 注入探针
├─ test/
│  └─ client.test.mjs         # node:vm 假 DOM 自动化测试(17 个用例)
├─ preview/
│  ├─ index.html              # 独立预览页(可模拟 Harness 活动信号)
│  ├─ raster-demo.html        # JPG 宠物渲染验证页(?pet=<id>&embed=1)
│  ├─ server.mjs              # 本地静态服务器(npm run preview)
│  ├─ preview.png             # 手绘版预览截图
│  └─ deepseek-whale.png      # 鲸鱼娘(原图)预览截图
├─ examples/
│  └─ pudding-ghost.json      # 自定义宠物定义示例(可直接导入工作室)
└─ .github/workflows/
   ├─ check.yml
   └─ release.yml

开发

npm run check    # 语法检查 + 自动化测试
npm run preview  # 打开 http://127.0.0.1:4173/preview/ 独立预览

预览页可模拟「停止生成」按钮、[data-streaming][data-state="running"][data-error] 与 composer 输入,用来观察宠物状态切换;URL hash 可直接切状态,如 /preview/#happy

隐私

纯浏览器端插件:不读取 API Key,不修改模型输入,不上传任何数据。 设置、养成数据和导入的自定义宠物只保存在本机浏览器 localStorage

License

MIT