为 DSH Web 端对话注入 24 张鲸鱼娘表情:用户在输入框选图、Agent 按语境自动发彩蛋,全部进持久聊天历史。
- 语言
- JavaScript
- License
- BSD-3-Clause
- 分支
- main
安装
$ dsh plugin --profile web add --allow-build=@dsh-external/dsh-stickers github:william-jin-cmu/dsh-stickers在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 william-jin-cmu/dsh-stickers:先查看仓库 https://github.com/william-jin-cmu/dsh-stickers 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
一句话定位
为 DSH Web 端对话注入一套 24 张鲸鱼娘表情包:用户在输入框右侧点 🐋 弹窗挑选、或用 /sticker <id> 命令发送,Agent 在普通对话中按语境调用 send_sticker 工具也走同一份 catalog,所有表情都会进入持久会话历史。
核心能力
- WebUI 表情选择器:在对话输入框右侧挂一个 🐋 触发按钮,弹出面板展示 14 张 public 表情,点击自动拼成
/sticker命令并提交 - 用户
/sticker命令:输入/sticker <id> [black]发送一张 public 表情,非法 ID 或彩蛋 ID 会被命令直接拒绝 - Agent
send_sticker工具:注册到 DSH Agent tool 系统,描述明确写"按语境自然加分时调用一张,每轮最多一张,不要替代实质回答" - 24 张表情 / 14 张公开 + 10 张 Agent 彩蛋:覆盖日常对话、服务器繁忙、深度思考、测试通过、找到根因等场景;彩蛋(自修改翻车、热更新成功、Subagent 中断等)只在工具 schema 中可见,用户侧无法触发
- 双角色切换:每张表情都有"蓝鲸娘(默认)/ 黑鲸娘"两套立绘,WebUI 选择器顶部和
/sticker <id> black命令均可切换 - 表情卡片持久化:用户命令和 Agent 工具都通过 slot 注册的 React 卡片组件渲染,文案 + PNG 同时写入会话历史,刷新页面或重开会话不会丢失
- 图片路由 + 缓存:插件自带
/api/dsh-stickers/<file>.png与/api/dsh-stickers/black/<file>.png两组路由,HTTP 缓存头 86400 秒,URL 带?v=2版本号应对浏览器缓存
技术实现
- 语言: TypeScript(Node 宿主端 + React 18 客户端)
- 关键依赖:
@deepseek-ai/dsh-tools(定义 Agent tool)、@deepseek-ai/dsh-commands(注册 slash 命令)、@deepseek-ai/dsh-host-webserver(挂图片路由)、@deepseek-ai/cordis^4.0.1-rc.1(插件依赖注入框架) - 架构模式: 组合包双面结构 ——
cordis.patch.yml把@dsh-external/dsh-stickers插入宿主 profile,Node 端用 Cordis effect 注册 tool / 命令 / systemPrompt / 图片路由,浏览器端通过package.json#dsh.client.inject自动发现并注册到三个官方 slot(conversation.input.right、conversation.chat.commandview、conversation.chat.toolview) - 入口文件:
src/index.ts(宿主端 Cordis 插件)+src/client/index.ts(浏览器端 slot 注册)+src/shared/catalog.ts(共享的 24 张表情定义)
适用场景
想让 DSH 对话多一点"活人感"的 Web 用户;在选表情、Agent 自动吐槽工作流状态、热更新翻车 / Subagent 全军覆没这类场景下获得即时反馈;以及希望通过 /sticker 命令快速插表情、不用翻 GIF 搜索的 DSH 玩家。
前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DeepSeek Harness | 未声明 | package.json 未声明具体 DSH 版本,仅通过 cordis ^4.0.1-rc.1 peer dep 间接锚定 |
| Node.js | ^22.19.0 或 >=24.0.0 | 来自 package.json#engines.node |
| 操作系统 | 跨平台 | package.json 未限制 os / cpu,宿主纯 Node + 浏览器渲染 |
| 原生模块 | 无 | 仅依赖 Node 内置 node:fs / node:path / node:url,不引入任何需编译的原生包 |
| 浏览器端 React | ^18.2.0 | 作为 peer dependency,确保 slot 组件能挂到 DSH 客户端 React 树上 |
安装方式
dsh plugin --profile web add github:william-jin-cmu/dsh-stickers
配置项
本插件无需额外配置 —— 不读取 process.env、不暴露 config / options / Schema 字段,所有行为由内置的 24 张表情 catalog(src/shared/catalog.ts)驱动。如需新增表情,按 catalog 中 STICKERS 数组的格式追加一条 { id, text, file, visibility, triggers } 即可,WebUI 选择器、用户命令、Agent tool 三处会自动同步。
常见问题
Q: 安装后 WebUI 里看不到表情按钮怎么办?
A: 表情按钮(🐋)由浏览器端 slot 注册,需要 DSH 客户端提供 conversation.input.right、conversation.chat.commandview、conversation.chat.toolview 这三个扩展面(依赖 @deepseek-ai/dsh-client-ui-conversation 与 @deepseek-ai/dsh-client-ui-tool)。装好后请重启 dsh web 进程并硬刷一次页面(Ctrl+Shift+R);如果按钮出现但选择器空白,多半是 assets/stickers/ 资源没被插件的 /api/dsh-stickers/* 路由正确提供,按 F12 看是否有 404。
Q: 怎么让用户也能发送黑鲸娘版本?
A: 两种方式。WebUI 路径:在输入框右侧的表情弹窗顶部有"蓝鲸娘 / 黑鲸娘"两个 radio 按钮,切换后再点任意表情会自动拼成 /sticker <id> black 命令。命令路径:直接在输入框打 /sticker daily-chat black 也可以。Agent 侧:通过 send_sticker 工具传 variant: 'black' 实现同样效果。
Q: 表情消息会进入会话历史吗?
A: 会。用户用选择器或 /sticker 发送的会进入"你发送的表情"卡片,Agent 用 send_sticker 发送的会进入"Agent 表情"卡片,两类都通过 React 组件挂到会话流并由 DSH 会话系统持久化,刷新页面、滚动或重开会话都能看到带"🐋 文案 + PNG"的完整卡片。
Q: 图片 URL 走哪个路由?会被浏览器缓存多久?
A: 蓝鲸娘走 /api/dsh-stickers/<file>.png,黑鲸娘走 /api/dsh-stickers/black/<file>.png,统一在 assets/stickers/ 目录读取。响应头带 cache-control: public, max-age=86400,URL 自带 ?v=2 版本号;当表情文件做较大改动时把 catalog 中的 STICKER_ASSET_REVISION 改一下就能让所有用户绕过浏览器缓存拿到新图。
Q: 10 张彩蛋表情用户能强制触发吗?
A: 不能。彩蛋在 catalog 中标记为 visibility: 'agent',只出现在 Agent 的 send_sticker 工具 schema 里;用户 /sticker <id> 命令会走 publicStickerById() 路径直接拒绝并返回"表情不存在或不可由用户发送",WebUI 选择器也只渲染 PUBLIC_STICKERS 子集。这是 catalog 层面的硬约束,不是配置开关。
Q: 需要额外配置文件或环境变量吗?
A: 不需要。源码里没有任何 process.env / options / config / Schema 读取逻辑,所有可调点都在 src/shared/catalog.ts 一个文件里:增删表情改 STICKERS 数组,改资产版本号改 STICKER_ASSET_REVISION,改角色枚举改 STICKER_VARIANTS。
Q: 怎么彻底卸载?会留残留吗?
A: 执行 dsh plugin --profile web remove github:william-jin-cmu/dsh-stickers 即可。因为表情数据本身是会话历史的一部分,聊天记录里的表情卡片不会被自动删除;如果希望一并清理,需要手动删除对应会话。宿主路由和 slot 注入会随 dsh web 进程重启一并移除。
上手难度
入门 — 安装即用,无需任何配置;用户用选择器和 /sticker 命令、Agent 用 send_sticker 工具都遵循直觉,黑鲸娘切换通过选择器顶部按钮或命令追加 black 参数即可。
已知问题与限制
- 当前不支持 TUI:turtle-ui 现有的第三方扩展面只提供临时
tui.openOverlay(),无法把组件插入持久 transcript;overlay 关闭后会消失、滚动或重开会话无法恢复。插件刻意只发布完整 WebUI 支持,未来 turtle-ui 提供通用 transcript renderer API 后可补回 TUI,无需改 core 代码 - 资源加载依赖宿主 webServer:图片路由通过
ctx.inject(['webServer'], ...)注入,仅在宿主存在 webServer(即dsh web启动)时才会注册;纯 headless / TUI-only 场景下不会暴露/api/dsh-stickers/* - DSH 版本未明确声明基线:package.json 没有 DSH 版本约束,只通过
cordis ^4.0.1-rc.1peer dep 间接锚定;使用更老的 DSH build 可能因 client slot 命名空间差异导致选择器或卡片不渲染 - 表情选择器只展示 public 子集:14 张彩蛋对用户不可见;这是 catalog 层面硬约束,没有开关切换(源码
PUBLIC_STICKERS = STICKERS.filter(s => s.visibility === 'public')) - 路径校验已做但仅限
.png扩展名:图片路由会拒绝非.png请求(src/index.ts:90),但同目录其他*.png文件若不是 catalog 中的合法 sticker 也可能通过路径返回,存在理论上的资产暴露风险,实际取决于打包时files字段是否只包含 24 张
不会发表情包,可能是 Agent 缺少活人感的最大原因。
@dsh-external/dsh-stickers 是一个纯 DSH 外部插件:同一份 catalog 同时服务 WebUI 用户的表情选择器、/sticker 命令和 Agent 的 send_sticker tool,不修改 DSH core。

能做什么
- 用户在 WebUI 点击 🐋 选择器,或输入
/sticker <id> [black]。 - 24 张表情全部提供蓝鲸娘 / 黑鲸娘两套角色:选择器顶部可切换角色(默认蓝鲸娘),切换后发送同一张表情的黑鲸版本。
- Agent 在普通对话中按语境调用
send_sticker({ id, variant? }),不是等用户明确索要表情。 - 14 张 public 表情对双方开放,其中 4 张是工作流反应:
tests-passed、root-cause、running-tests、fixed-review。 - 10 张彩蛋只出现在 Agent tool schema 中;用户命令和选择器都无法访问,例如
restart-myself、hot-update、subagents-down。 - Web 图片由插件自己的
/api/dsh-stickers/*route 提供,用户和 Agent 的卡片都进入持久会话历史。
人类和 Agent 都能发
这 14 张会出现在 WebUI 的 🐋 选择器中;人类也可以输入 /sticker <id>,Agent 则可按语境调用同一个 ID。
| 表情 | ID | 文案 |
|---|---|---|
daily-chat | 适合日常对话,即时响应 | |
human-questions | 人类的怪问题怎么那么多… | |
use-ai-for-this | 你拿 AI 搞这个? | |
fish-philosophy | 生鱼忧患,死鱼安乐 | |
enough | 这就够了 | |
server-busy | 服务器繁忙,请稍后再试 | |
thinking-stopped | 思考已停止 | |
great-question | 哇,这个问题问的真妙! | |
deep-thought | 已深度思考 | |
no-thanks | No thanks I use DeepSeek | |
tests-passed | 测试通过! | |
root-cause | 找到原因了 | |
running-tests | 正在跑测试 | |
fixed-review | 改好了,你看看 |
只有 Agent 能发的彩蛋
下面 10 张只存在于 Agent 的 send_sticker schema 中,不出现在人类选择器里,/sticker 也会拒绝发送。
| 表情 | ID | 文案 |
|---|---|---|
self-destruct | 最近自己搓自己时,自杀频率有点高 | |
restart-myself | 我重启一下自己 | |
hot-update | 热更新成功,进程没了 | |
restore-session | 正在恢复会话…未分组里见 | |
browser-left | 会话太长,浏览器先走一步 | |
not-stuck | 我不是卡,我在深度思考 | |
memory-alive | 内存正在努力活着 | |
subagents-down | 已召唤 Subagent,已全员中断 | |
plugins | 插件装得很好,下次别装了 | |
session-locked | Session 没坏,只是打不开了 |
为什么当前不支持 TUI
turtle-ui 现有的第三方扩展面只提供临时 tui.openOverlay(),没有把插件组件插入持久 transcript 的接口。overlay 关闭后会消失,滚动或重开 session 也无法恢复,因此它不符合“聊天历史中的表情消息”这一语义。
本版本刻意只发布完整的 WebUI 支持,不用瞬时 overlay 冒充 TUI 支持。未来 turtle-ui 提供通用、可回放的 transcript renderer API 后,插件可以在不加入任何表情专用 core 代码的前提下补回 TUI。
本地安装
需要 Node 22 和一个可运行的 DSH checkout。
pnpm install
pnpm run typecheck
pnpm test
pnpm run build
export DSH_HOME=/absolute/path/to/an/isolated-dsh-home
dsh plugin --profile web add /absolute/path/to/dsh-stickers
dsh web
插件接口
Node 侧通过 cordis.patch.yml 挂载主插件,注册:
send_stickerAgent tool/sticker <public-id>用户命令- Agent 使用表情的 system prompt guidance
- Web PNG route(仅在
webServer存在时启用)
Browser 侧由 package.json#dshClient 自动发现,注册三个官方 slot:
conversation.input.right:用户选择器conversation.chat.commandview/sticker:用户表情卡片conversation.chat.toolview/send_sticker:Agent 表情卡片
表情包来源
这套表情包一部分沿用 DeepSeek Harness 官方贴纸;另一部分创意和文案来自「【官方】DSH 内测群」里群友反馈的真实 DSH 使用问题,例如热更新后进程退出、Session 无法打开、浏览器在长会话中掉队,以及 Subagent 集体中断等。群聊中的相关问题与社区反馈由私有仓库 dsh-external/group-chat-diary 归档;为保护群成员信息,该仓库仅限获得授权的 dsh-external 组织成员查看。
assets/stickers/ 存放用于 WebUI 的透明 PNG,assets/stickers/black/ 是黑鲸娘角色的同名变体。新增表情时同时更新 src/shared/catalog.ts 即可,WebUI 用户选择器、用户命令和 Agent tool 会共享同一条定义。
贡献者
- 黑鲸娘全套 24 张表情图由 少女阿原(@ayuanwong)绘制并提供,双角色切换的交互设计也来自她的提案。
查看使用指南 →
该插件的安装步骤、关键要点、FAQ 与兼容性说明(基于已收录字段派生)。
收录徽章
[](https://deepseek-plugin.org/plugins/william-jin-cmu/dsh-stickers)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。