dsh-stickerbook:给 DeepSeek Harness 装一个本地表情包库

前言

在 DSH 里做对话类产品,加表情包是常见需求,但现成的做法通常有两难:要么插件自带图库却结构混乱、许可不清,要么结构清晰却要自己先构建素材、跑不起来。更麻烦的是,不少方案沿用 markdown 图片链接,宿主的 Markdown 渲染器会把相对地址当成工作区文件处理,图片显示「无法预览」。dsh-stickerbook 就是针对这些问题的本地表情包库插件:自带图库、开箱即用,同时把索引、搜索、路由、发送的分层和素材许可边界都写清楚。

一句话定位:这是一个跑在 DeepSeek Harness 上的本地表情包插件,用 157 张中文表情做可搜索图库,用户和助手都能发图,可选原生走 QQ。插件由 Asgoresmilelong 维护,代码在 GitHub 上开源。

它解决什么

插件综合了两个同类插件的取舍:像 dsh-meme 一样开箱即用,自带图库、小图、无需构建,并且带测试;像 dsh-nekowhale-stickers 一样结构清晰,索引、搜索、路由、发送分层,元数据可读可改,许可边界写清楚。

主要解决三点:

  1. 素材问题:不需要自己找图、不必构建,装完就有 157 张「蓝色大肥鱼」表情,且来源和许可都明示。
  2. 发送问题:发图不依赖 markdown 图片,改用 [贴纸: 描述] 纯文本 token,由客户端渲染成图片,这是桌面端唯一稳定的路。
  3. 扩展问题:想加自己的图,丢文件、让 agent 收录、手工编辑都可以,新增图片无需改代码。

核心能力

搜索:按情绪 tag(happy / angry / sad / food 等)或关键词查找,支持中文子串与多词 AND 匹配。

用户发图:输入框左侧的「🙂 表情」按钮打开可搜索的图库面板,点一张就把 [贴纸: 描述] 放进输入框并发送。

助手发图:消息里只存 [贴纸: 描述] 纯文本 token,客户端渲染成图片;工具返回候选,并附可直接复制的 token。

QQ / IM 原生发送:宿主有 companionQq 服务时,action="send" 可直接原生发原图。

加图零配置:把图片放进 packs/<pack>/images/,文件名先当描述,再用 sticker_learn / sticker_update 补描述。

零运行时依赖:宿主侧只用 Node 内置模块(node:fs / node:http),没有数据库、没有原生扩展。

测试:node --test,覆盖搜索、pack 解析、HTTP 围栏、元数据写入、token 格式与列表 API,仓库共 33 个测试。

安装与启用

按官方使用方式,安装命令直接走 CLI,注意不要凭插件名拼接,以下三条均来自仓库文档:

# 本地开发(link 安装,改代码重启即生效)
dsh plugin --profile desktop add link:F:\DSH-\oss\dsh-stickerbook

# 或从 npm 安装
dsh plugin --profile desktop add dsh-stickerbook

# 或从 GitHub 安装
dsh plugin --profile desktop add github:<you>/dsh-stickerbook

官方桌面端请完全退出 DSH 后再执行 CLI,装完重启 DSH。

装好后 agent 会拿到四个工具:

工具 干什么
send_sticker 找图(tag / query)并返回候选;action=send + path 走 QQ 原生发图
sticker_list 只读浏览,带 pack/file 方便维护
sticker_learn 把一张图收进用户图库(默认 mine)
sticker_update 改描述 / 情绪 / 关键词

典型用法

助手发图(Web 端)。三步:工具返回候选,模型把选中的 token 原样写进回复,客户端把 token 换成 /dsh-stickers/... 的 <img>。

  1. send_sticker({ query: "摸鱼" }) → 工具返回候选,每张带一行 [贴纸: 描述]
  2. 模型把选中那张的 token 原样写进回复
  3. 客户端把 token 替换成 /dsh-stickers/... 的 <img>

这里不推荐用 markdown 图片:宿主渲染器会把相对地址当作工作区文件(/api/file),/dsh-stickers/... 或 http URL 都会显示「图片无法预览」。token + DOM 装饰才是稳定方案。

QQ / IM 会话:

  1. send_sticker({ tag: "happy" }) 拿候选(含绝对路径)
  2. send_sticker({ action: "send", path: "<绝对路径>" }) 由插件调用 companionQq.sendImage

用户发图:点输入框左侧的「🙂 表情」,搜索或直接点一张,插件会把 [贴纸: 描述] 放进输入框并发送。

加图

三种方式,按方便程度排列。

方式一,直接丢文件,最快:

packs/blue-whale/images/新表情.gif

重启 DSH 或等下一次工具调用重新扫描后就能搜到;描述先用文件名,之后用 sticker_update 改。

方式二,让 agent 收录:

sticker_learn({ path: "D:\\pics\\生气猫.gif", caption: "生气猫:再问就咬你", emotion: "angry", tags: "猫 生气 咬人" })

文件会被复制到 ~/.dsh/sticker-packs/mine/images/,原图留在原地。

方式三,手工编辑 stickers.json:

{
  "version": 1,
  "items": [
    {
      "file": "images/生气猫.gif",
      "caption": "生气猫:再问就咬你",
      "emotion": "angry",
      "tags": ["猫", "生气", "咬人"],
      "use": "被问烦了的时候"
    }
  ]
}

stickers.json 是可选文件,没有它也能用,文件名就是描述。图库格式如下:

packs/
  blue-whale/
    pack.json        # { id, name, description, author, source, license, version }
    stickers.json    # { version: 1, items: [{ file, caption, emotion, tags, use }] }
    images/          # 图片(gif/png/jpg/webp),可以有子目录

用户图库放在 ~/.dsh/sticker-packs/<pack>/,与插件包分开,升级插件不会丢。

配置

在 profile 的 cordis.patch.yml 里给这一行加 config::

- id: stickerbook
  name: dsh-stickerbook
  config:
    route: /dsh-stickers      # 图片路由前缀
    packs:                    # 覆盖默认扫描根(相对包目录或绝对路径)
      - packs
      - D:\my-stickers
    allowLan: false           # 默认只允许回环地址取图
    allowedHosts: []          # 反代域名白名单
    maxBytes: 20971520        # 单图上限 20MB

环境变量 DSH_STICKERBOOK_ALLOW_LAN=1 等价于 allowLan: true。

HTTP 围栏只认 Host 头(不是 Origin),默认仅回环地址;反代或 LAN 必须显式放行。

设计取舍

元数据在磁盘上:packs/** 是唯一真相,内存索引是派生的;改一条描述不需要迁移或重建数据库。

发图用 token + 客户端装饰:消息里只存 [贴纸: 描述] 纯文本,客户端换成 <img>;宿主的 Markdown 渲染器不认本地或 HTTP 图片地址,这是桌面端唯一稳定的路。

工具少而清晰:发送、浏览、添加、编辑四件事,避免一个巨型设置面板。

适用场景与注意

适合想在 DSH 对话里加表情包、又不想自己构建素材的开发者:需要本地可搜索图库、用户可选图发送、必要时走 QQ 原生发图的,可以拿它当起点;想长期维护大量自有图库的,也可以借鉴它的分层和许可拆分。

有几点要提前知道:

  1. 插件以当前 dsh 进程权限运行,安装前应检查源码与许可证,不要看到目录站收录就直接装。
  2. 代码是 MIT 许可,作者 Asgoresmilelong;但 packs/blue-whale/images/ 下的 157 张表情不是插件作者的原创,全部来自 B站 @赤风RED,素材许可是 CC BY-NC 4.0(署名 + 非商业性使用)。转载或分发必须保留「赤风RED」署名与来源链接,商用需另行获得赤风RED许可;MIT 只覆盖代码,不覆盖这批素材。
  3. 仓库自带的 157 张「蓝色大肥鱼」是 460MB 原始 GIF 压缩到 45MB(240px、12fps、128 色)后的版本,压缩脚本在 tools/prepare-pack.mjs,重新打包时可复用。

结尾

dsh-stickerbook 的价值在于把「自带图库 + 稳定发图 + 清楚许可」三件事一次做对:装完即用,token 渲染绕开了 markdown 图片的限制,素材的来源和商用边界也明示清楚。如果要做同类功能,它的四工具划分、磁盘即元数据的约定和许可拆分都值得参考。

  • 目录页:https://www.skillhub.cn/plugins/Asgoresmilelong/dsh-stickerbook
  • GitHub:https://github.com/Asgoresmilelong/dsh-stickerbook
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜