dsh-client-ui-pet
🐟 Salted Fish Pet — a Cordis-based web-client UI plugin for the DeepSeek Harness Web UI. Injects a draggable, feedable salted fish mascot + full-viewport engineer wallpaper into the shell.overlay slot. Pure front-end (React + CSS Modules), zero server-side.
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 18, 2026
- Updated
- Aug 19, 2026
Introduction
@tangyuewei/dsh-client-ui-pet
咸鱼宠物(Salted Fish Pet) —— 为 DeepSeek Harness Web UI 打造的桌面宠物插件。一只悬浮在右下角的咸鱼吉祥物,叠加全视口工程师主题壁纸。纯前端展示插件,无服务端行为。
简介
ui-pet 是一个基于 Cordis 的客户端 UI 插件(platform: 'web')。它向 DeepSeek Harness(DSH)Web Shell 的 shell.overlay 槽位注入两部分内容:
- 咸鱼宠物:一只可拖拽、可喂食、会随机吐槽的咸鱼吉祥物;
- 工程师壁纸:全视口壁纸(不区分深浅色,丢入
wallpapers/即可入候选),透过透明主题背景显示。
两部分通过模块级共享状态(visibility.ts)联动:点击「隐藏咸鱼」会同时收起宠物与壁纸。
演示

演示内容:默认 yu7 毛玻璃背景与咸鱼 → 打开壁纸面板 → 切换 Porsche 718 → 📌 置顶(背景图全屏置顶)→ 取消置顶 → 切换 Macan S(深色系壁纸亦可选,深浅色不限制)。
功能特性
咸鱼宠物
- 固定锚点:默认吸附在视口右下角(
MARGIN = 20px内边距)。 - 拖拽移动:按住鱼身拖拽,自动钳制在视口可见区域内;窗口缩放导致越界时自动重新锚定。
- 点击喂食:点击鱼身恢复饱腹度 +25(上限 100),触发「开心」心情与随机台词。
- 饱腹度系统:每 30 秒自然衰减 1 点;饿到 0 会自动切换到「有 Bug」心情。
- 8 种心情:开心 🐟、晕乎乎 🐡、燃烧 🔥、睡着 😴、有 Bug 🐛、续命 ☕、起飞 🚀、摔桌 😡。
- 气泡台词:每种心情附带程序员笑话 + 开发技巧提示,自动 3 秒消失。
- 闲置自动唠叨:8–15 秒随机触发一次随机心情与台词。
工程师壁纸
- 多壁纸候选:7 张图(Porsche 718/ Yu7 ×3 / Macan S / Su7 ×2)由
scripts/build-wallpapers.mjs自动缩放到 1920px JPEG 并 base64 编码进bg-images.generated.ts,丢图即可加入候选。 - 不区分主题:所有壁纸在任何主题下均可选(不再按浅色/深色分组),用户自由挑选;选择全局共享一个 id,写入
localStorage(dsh-ui-pet.wallpaper)。 - 运行时切换:右下角 🎨 按钮(
WallpaperPicker)弹出全部壁纸的缩略图面板,点击即切换;支持 📌 置顶(背景图全屏置顶、面板保持打开可对比,取消置顶返回原状)。 - 默认壁纸:召唤咸鱼时默认使用
yu7.jpg(未做任何选择时)。 - 丢图即生效(开发时):跑
npm run watch后,往src/client/wallpapers/丢入图片会自动重编码并重建,无需手动执行npm run bundle。 - 透出机制:通过 CSS 变量将主题背景基色设为透明(
--dsw-alias-bg-base: transparent),壁纸从body透出,无需额外 DOM 节点或 z-index 争用。 - 玻璃拟态列:侧边栏与中间列采用半透明 +
backdrop-filter: blur + saturate的毛玻璃效果,壁纸色调模糊透出,导航与正文保持可读,呈现现代科技氛围;通过[class$="sidebarCol"]/[class$="centerCol"]结尾选择器命中上层层级(仅依赖 CSS Modules local 名后缀,不依赖哈希前缀),深浅主题分别适配透明度(浅色 centerCol 不透明度 0.74 + 22px 模糊以保障文字可读)。 - 鼠标跟随:
mousemove(passive)实时写入--bg-mx/--bg-myCSS 变量,为鼠标跟随光晕(见Background.tsx的EngineerBackground)提供定位。
召唤 / 隐藏
- 顶部导航栏「Session log」按钮左侧内联一个 召唤咸鱼 / 隐藏咸鱼 按钮(由宠物组件动态定位)。
- 点击一次隐藏宠物同时移除背景壁纸,恢复原主题背景。
- 再次点击召唤,宠物与背景同步恢复。
架构定位
| 层级 | 说明 |
|---|---|
| 包类型 | 纯客户端 UI 插件(platform: 'web') |
| 宿主端行为 | 无(src/index.ts 仅导出空 apply() 以满足 Cordis Loader) |
| 浏览器端入口 | exports["./client"] → src/client/index.ts |
| 槽位注册 | shell.overlay,条目 id: 'uiPet'(宠物组件) |
| 壁纸挂载 | 在 src/client/index.ts 的 apply() 内直接作用于 body,非独立槽位 |
| 共享状态 | visibility.ts 模块级 store 同步宠物与背景的显隐 |
目录结构
src/
├── index.ts # 宿主端入口(空 apply)
├── invariant.ts # 插件不变量占位
├── client/
│ ├── index.ts # 浏览器端插件:壁纸 + 毛玻璃 + 槽位注册
│ ├── SaltedFishPet.tsx # 咸鱼宠物 React 组件
│ ├── WallpaperPicker.tsx # 右下角 🎨 浮动按钮 + 缩略图选择面板
│ ├── visibility.ts # 宠物/背景共享显隐状态
│ ├── bg-images.ts # 壁纸 API:WALLPAPERS + localStorage 持久化 + 事件总线
│ ├── bg-image.ts # 旧版单壁纸常量(BG_IMAGE,遗留)
│ ├── Background.tsx # 工程师壁纸组件(EngineerBackground,遗留)
│ ├── SaltedFishPet.module.css
│ ├── Background.module.css
│ ├── WallpaperPicker.module.css
│ └── wallpapers/ # 壁纸源图目录:丢图 + npm run bundle 自动加入候选
│ ├── porsche-718.jpg
│ ├── mcan-s.jpg
│ ├── yu7-3.jpg
│ ├── yu7.jpg
│ ├── yu7-gt.jpg
│ ├── su7-1.png
│ └── su7.png
└── css-modules.d.ts
scripts/
└── build-wallpapers.mjs # prebuild:扫描 wallpapers/ → sips 缩放 → base64 → bg-images.generated.ts
安装方式
方式 A:npm 发布版(npx @deepseek-ai/dsh web 用户)
如果你是通过 npx @deepseek-ai/dsh web 运行 DeepSeek Harness(未 clone 源码),请使用 DSH 自带的 profile 插件管理命令安装本插件,不需要 clone 仓库或运行 install.sh(install.sh 仅适用于源码场景):
npx @deepseek-ai/dsh plugin --profile web add @tangyuewei/dsh-client-ui-pet
前提:本机需安装
pnpm(dsh plugin add本质是在 profile 目录内执行pnpm add)。
该命令做的事情:
- 首次运行会自动初始化持久化 profile 目录
~/.dsh/profiles/web(与 npx 缓存无关,重开终端 / 重跑 npx 依然生效); - 在该目录内执行
pnpm add @tangyuewei/dsh-client-ui-pet安装插件及其 peer 依赖; - 因插件声明了
dsh.bundle.patch,包名会自动追加进 profile 的dsh.profile.bundles清单; - 之后
npx @deepseek-ai/dsh web启动时,DSH 会按 bundle 顺序叠加插件的cordis.patch.yml,在shell.overlay注入咸鱼宠物与壁纸。
安装完成后重新启动 npx @deepseek-ai/dsh web,即可在右下角看到咸鱼宠物与工程师壁纸(可通过 Settings → Plugins 确认插件已启用)。
如需卸载:
npx @deepseek-ai/dsh plugin --profile web remove @tangyuewei/dsh-client-ui-pet
方式 B:从源码编译 DeepSeek Harness
以下步骤适用于从 DeepSeek Harness 源码启动的场景。克隆官方仓库后确保能正常 pnpm dsh web 启动。
步骤一:将插件放入 client 目录
cd $DSH_HOME/packages/client/
git clone https://github.com/tangyuewei/dsh-client-ui-pet.git
clone 后目录名即为
dsh-client-ui-pet,无需重命名,也无需在插件目录内单独构建;构建由步骤二的一键脚本统一完成。
步骤二:运行一键安装脚本
cd dsh-client-ui-pet
bash install.sh
脚本自动完成注册、安装依赖与构建,逐步输出进度,任一步失败会打印 [ERROR] 提示并中断(退出码非 0),无需手动编辑任何文件:
- 校验环境:检查
git/node/pnpm可用,并校验 DSH 源码目录结构完整; - 自动定位 DSH_HOME:默认取脚本所在目录的上三级(
dsh-client-ui-pet→packages/client→packages→$DSH_HOME);若 DSH 源码不在该位置,可用环境变量覆盖:DSH_HOME=/path/to/dsh bash install.sh; - 注册依赖:在
packages/bundle/web-app/package.json的dependencies中添加@tangyuewei/dsh-client-ui-pet: "workspace:^"; - 注册插件条目:在
packages/bundle/web-app/cordis.patch.yml的- insert:块末尾追加插件条目(id 与 name 从插件自身package.json/cordis.patch.yml自动读取,无需手动同步); - 安装依赖并构建:回到
$DSH_HOME依次执行pnpm install与pnpm run build。
脚本幂等:注册条目已存在时会自动跳过,重复运行安全;修复问题后可随时重跑。
步骤三:启动
pnpm dsh web
插件加载后可在浏览器中看到右下角的咸鱼宠物与工程师壁纸。可通过 Settings → Plugins 确认 @tangyuewei/dsh-client-ui-pet 已启用。
自定义配置
| 文件 | 可修改内容 |
|---|---|
src/client/SaltedFishPet.tsx | MOODS(emoji/tag)、SPEECH 台词库、饱腹度衰减间隔、闲置触发间隔、鱼尺寸(PET_W/PET_H)与边距(MARGIN) |
src/client/bg-images.ts | 壁纸 API:全局选择(theme-agnostic)、localStorage 持久化、事件总线 |
src/client/wallpapers/ | 壁纸源图目录,丢入图片即可自动加入候选(prebuild 缩放 + base64 编码,见下方「添加 / 更换壁纸」) |
src/client/index.ts | 透明背景变量名、鼠标跟随变量、壁纸应用逻辑、玻璃拟态列、用户选择事件总线 |
src/client/WallpaperPicker.tsx · WallpaperPicker.module.css | 浮动 🎨 按钮 + 全部壁纸缩略图弹窗(运行时切换、置顶) |
src/client/SaltedFishPet.module.css · Background.module.css | 宠物 / 气泡 / 饱腹度条样式、动画关键帧 |
常见调整示例
修改饱腹度衰减速度(SaltedFishPet.tsx):
// 原:每 30 秒 -1
setHunger(h => Math.max(0, h - 1))
}, 30000)
// 改:每 60 秒 -1
}, 60000)
添加 / 更换壁纸
把图片丢到 src/client/wallpapers/,文件名作为 id(如 yu7.jpg → id yu7):
# 开发(推荐):一次性启动,之后丢图自动重编码 + 重建
npm run watch
# 或一次性构建
npm run bundle # = node scripts/build-wallpapers.mjs && tsdown
prebuild 脚本会用 sips(macOS)把每张图缩放到 1920px 宽 + 转为 JPEG,base64 编码到 bg-images.generated.ts(gitignored,每次构建自动重新生成),然后 tsdown 把新内容打进 lib/client.js。完全不需要手动跑 base64 编码。
壁纸显示名在 scripts/build-wallpapers.mjs 顶部的 META 映射中维护(不再区分深浅主题,全部壁纸对所有主题可见):
const META = {
'porsche-718': { name: 'Porsche 718' },
'yu7': { name: 'Yu7 · 公路' },
'mcan-s': { name: 'Macan S' },
// ...
}
更换默认壁纸(src/client/bg-images.ts):修改 DEFAULT_WALLPAPER_ID 为任意壁纸 id 即可(默认 yu7)。
运行时切换:右下角 🎨 按钮 → 全部壁纸缩略图面板(深浅色不限制)→ 点击即切换并写入 localStorage(dsh-ui-pet.wallpaper),刷新与重启后保留。
兼容性说明
- 仅 Web 平台:
package.json声明dsh.client.platform: 'web',无 Node / CLI / ACP 入口。 - 零依赖服务:不消费任何 Cordis 服务(仅依赖
slots槽位注入),纯 React 组件 + 模块级 store。 - 样式隔离:CSS Modules(
SaltedFishPet.module.css、Background.module.css),无全局污染。 - 主题联动:依赖 DSH Web Shell 的
body[data-ds-dark-theme]属性切换。
已知限制
- 无持久化:宠物位置、饱腹度、心情、显隐状态均为会话级内存,刷新即重置。
- 无配置面板:所有参数需改源码重新构建,未暴露给用户设置。
- 壁纸候选统一管理:所有候选壁纸(不区分深浅色)以 base64 内嵌于
bg-images.generated.ts(prebuild 自动生成),无外部请求;如需动态加载需自行改造。 - 召唤按钮定位依赖 DOM 查找:通过查找「Session log」按钮定位,若 Shell 结构变更可能失效。
- 无障碍支持有限:宠物交互区标注
role="button"与tabIndex,但缺少完整 ARIA 属性与键盘操作。 - 光晕为遗留实现:鼠标跟随光晕样式定义在未挂载的
Background.tsx(EngineerBackground),当前壁纸路径不渲染光晕。
许可证
MIT