<div align="center">

<img src="https://kiriyuki.com/meme/kit/nekowhale/hero.jpg" alt="Da Fei Yu stickers" width="100%">

<h1>Da Fei Yu Hachimi Stickers · dsh-nekowhale-stickers</h1>

<p><b>A sticker knowledge kit for DeepSeek Harness</b><br>
<sub>Per-sticker usage, description, meme reference and direction · searchable · rendered locally</sub></p>

<p>
<img alt="dsh plugin" src="https://img.shields.io/badge/dsh-plugin-4D6BFE?style=flat-square">
<img alt="MCP" src="https://img.shields.io/badge/MCP-server-111827?style=flat-square">
<img alt="stickers" src="https://img.shields.io/badge/stickers-322-5B8DEF?style=flat-square">
<img alt="templates" src="https://img.shields.io/badge/templates-6-7C9CF5?style=flat-square">
<img alt="version" src="https://img.shields.io/badge/version-1.0.0-blue?style=flat-square">
<img alt="node" src="https://img.shields.io/badge/node-%E2%89%A520-339933?style=flat-square&logo=node.js&logoColor=white">
<img alt="license" src="https://img.shields.io/badge/license-Apache--2.0%20%7C%20CC%20BY--NC%204.0-green?style=flat-square">
</p>

<p><a href="README.md">中文</a> · <b>English</b></p>

<p>
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/16N12.gif" width="80" alt="not enough rice">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/14N01.gif" width="80" alt="freeloader cat">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/3N05.gif" width="80" alt="slacking">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/EX72.gif" width="80" alt="cat world domination">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/5N05.gif" width="80" alt="watching drama">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/EX76.gif" width="80" alt="do I have to die too">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/15N01.gif" width="80" alt="lightbulb moment">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/TT02.gif" width="80" alt="heart">
<img src="https://kiriyuki.com/meme/kit/nekowhale/showcase/2TT10.gif" width="80" alt="stand user">
</p>

<sub>Stickers by <a href="https://space.bilibili.com/103739"><b>可以叫我云大人/雾雪</b></a> on Bilibili, made at <a href="https://kiriyuki.com">kiriyuki.com</a>. Commissions in the same style are welcome!<br>
Sets: <a href="https://kiriyuki.com/showcase?p=%E5%A4%A7%E8%82%A5%E9%B1%BC">大肥鱼</a> · <a href="https://kiriyuki.com/showcase?p=%E5%A4%A7%E8%82%A5%E9%B1%BC%E5%92%8CGPT%E5%A8%98">大肥鱼和GPT娘</a></sub>

</div>

<br>

## ✨ Features

<table>
<tr>
<td width="33%" valign="top">
<h4>📚 Sticker knowledge</h4>
Every sticker is annotated: situation tags, a description of the motion, the meme it plays on, and for the duo set the <b>direction</b> (who does what to whom), so the model barely needs its own vision. About 60 tokens stay in context.
</td>
<td width="33%" valign="top">
<h4>🔍 Mood search</h4>
Scored search over moods and situations with Chinese partial matching; light shuffling against repeats.
</td>
<td width="33%" valign="top">
<h4>🎨 Local templates</h4>
想 / 举牌 / 葱卷 / 上联 / 下联 / 抱: make text stickers locally.
</td>
</tr>
<tr>
<td valign="top">
<h4>🔄 Incremental sync</h4>
Pulls the latest version when the art is updated; lazy downloads by default.
</td>
<td valign="top">
<h4>🎛️ Self curation</h4>
The agent may browse and switch stickers on or off, or keep a small chosen set; your config black / white lists always win.
</td>
<td valign="top">
<h4>🔌 Generic interfaces</h4>
A cordis service <code>stickers</code>, <code>[sticker:name]</code> reply marks, an MCP server, a CLI and a public JSON. No framework lock-in.
</td>
</tr>
<tr>
<td colspan="3" valign="top">
<h4>🐋 Web pet</h4>
The kiriyuki.com 大肥鱼 web pet appears in the corner of the dsh web UI. It runs in a separate cross-origin iframe and never touches dsh sessions; <code>pet: false</code> turns it off.<br>
<b>Double-click the pet for your DeepSeek balance</b>, read with the DeepSeek account signed in to dsh or the API key set there (the account first when both exist). Only on a double-click, dsh on this machine asks deepseek.com; the key and sign-in go nowhere else, and only pages on this machine get the answer. <code>petBalance: false</code> turns it off.
</td>
</tr>
</table>

## 🖼️ Templates

<div align="center">
<table>
<tr>
<td align="center"><img src="https://kiriyuki.com/meme/kit/nekowhale/examples/think.gif" width="160"><br><sub><code>大肥鱼想 下班</code></sub></td>
<td align="center"><img src="https://kiriyuki.com/meme/kit/nekowhale/examples/sign.gif" width="160"><br><sub><code>大肥鱼举牌 今天也要摸鱼</code></sub></td>
<td align="center"><img src="https://kiriyuki.com/meme/kit/nekowhale/examples/couplet.gif" width="160"><br><sub><code>大肥鱼上联 代码一遍过</code></sub></td>
<td align="center"><img src="https://kiriyuki.com/meme/kit/nekowhale/examples/hug.gif" width="160"><br><sub><code>大肥鱼抱</code> + avatar</sub></td>
</tr>
</table>
</div>

## 👥 Characters

<table>
<tr>
<td width="140" align="center"><img src="https://kiriyuki.com/meme/kit/nekowhale/id-photo-blue.png" width="120" alt="Da Fei Yu"></td>
<td><b>大肥鱼 design</b> is based on the characters by <a href="https://space.bilibili.com/4168597">ZipZipPipe</a> and <a href="https://space.bilibili.com/4456176">上善无形</a>; <b>GPT娘 design</b> is based on <a href="https://space.bilibili.com/4168597">ZipZipPipe</a>.<br>
<b>大肥鱼 (Da Fei Yu)</b>: the DeepSeek whale as a girl, dark blue hair with an ahoge and a maid headdress.<br>
<b>GPT娘 (GPT-chan)</b>: ChatGPT as a girl, the white character of the duo set, a white-haired dragon girl with dragon horns and an OpenAI hair ornament.<br>
<sub>Duo stickers record their direction in <code>dir</code>, e.g. <code>大肥鱼→GPT娘</code>.</sub></td>
</tr>
</table>

## 🚀 Install

```sh
dsh plugin --profile web add dsh-nekowhale-stickers
```

Then restart `dsh web`. On dsh 0.2 you can also enter `dsh-nekowhale-stickers` under **Plugins → Add plugin** in the web sidebar. A local `.tgz` from `pnpm pack` works too.

## ⚙️ Configure

Easiest: in the dsh web UI sidebar open **Plugins → 大肥鱼表情包** (dsh 0.1.x: **Settings → Plugins → 大肥鱼表情包**), change options and Save. They apply immediately, no restart.

Defaults can also go in the profile's `cordis.patch.yml`; values saved in the web UI override them:

```yaml
- id: nekowhale-stickers
  config:
    promptMode: hint        # skill | hint | index | off
    frequency: normal       # rare | normal | often
    blacklist: [tag:舌吻]   # id, file stem, code, name, or pack: / tag: / emotion: / group: rules
```

| Key | Default | Meaning |
|---|---|---|
| `packs` | both sets | sets to serve |
| `autoSync` | `lazy` | `startup` mirror all in background · `lazy` download on first use · `off` offline |
| `persona` | `self` | `self`: the agent is 大肥鱼 and the stickers are its own expressions (fits DeepSeek); `neutral`: a third-party pack |
| `promptMode` | `skill` | how much stays in the prompt; `index` lists enabled stickers, meant for a small allowlist |
| `agentCuration` | `true` | let the agent curate with `sticker_manage` |
| `templates` / `banwords` | `true` | templates; the website's word filter |
| `returnImageToModel` | `false` | attach the picture for the model to see (image tokens) |
| `pet` | `true` | show the 大肥鱼 web pet in the web UI; `false` turns it off |
| `petHeight` / `petBubbles` | `211` / `true` | pet size (height in pixels), speech bubbles (off saves about 1.5 MB) |
| `petBalance` | `true` | double-click the pet to show your DeepSeek balance; `false` turns it off |

## 🧰 Tools

| Tool | Purpose |
|---|---|
| `sticker_search` | find stickers, one line each: `name｜emotion｜tags｜direction` |
| `sticker_send` | returns a Markdown image line to paste into the reply; an emotion word picks a random one |
| `meme_render` | render a template |
| `sticker_manage` | browse, info, enable / disable, mode, credit, sync |

## 🤝 Use from other plugins and frameworks

Four generic interfaces:

- **cordis service** (other dsh plugins, e.g. a QQ bridge): `inject: ['stickers']`, then `ctx.stickers.search()` / `.file()` / `.url()` / `.render()`.
- **Reply marks**: in plain-text replies write `[sticker:name]`, or an emotion such as `[sticker:开心]` for a random one; a bridge splits the reply with `parseReply()`. NapCat / OneBot shows a GIF as a sticker only with `sub_type: 1` on the image segment.
- **MCP** (LangBot, NoneBot / AstrBot LLM plugins, Claude / Cursor style clients, ...):
  ```json
  { "command": "npx", "args": ["-y", "dsh-nekowhale-stickers", "mcp"] }
  ```
  Tools return a local path and a public URL; the host sends the file.
- **Data and CLI** (any language): [`meta/nekowhale.json`](meta/nekowhale.json) (live at `https://kiriyuki.com/meme/kit/nekowhale.json`), or
  ```sh
  npx dsh-nekowhale-stickers search 摸鱼
  npx dsh-nekowhale-stickers index
  npx dsh-nekowhale-stickers render 大肥鱼举牌 今天也要开心 -o sign.gif
  ```

You can also build your own integration on top of this repository.

## 🛠️ Develop

```sh
pnpm install && pnpm build
node tools/dev/smoke.mjs /tmp/data      # run every tool against a fake ctx
```

- `tools/annotate/`: labelling pipeline, frame contact sheets → per-sticker vision annotation → `build_meta.py` → `meta/nekowhale.json`.
- `tools/art/`: scripts that compose the hero and showcase images (background plate + real sticker frames + Live2D portrait); the resulting images are hosted by kiriyuki.com.

## 📄 License

Code is licensed under [Apache-2.0](LICENSE): you may modify it; modified versions, or republished software with the same features, must keep the [NOTICE](NOTICE), i.e. credit this repository's address and link the sticker author.

The knowledge data (`meta/` and more, see [LICENSE-ASSETS](LICENSE-ASSETS)) is licensed under CC BY-NC 4.0: you may redistribute them, but you must keep the original author's link and website, and you may not charge for them or use them for other commercial purposes.

Base character designs and templates by **可以叫我云大人/雾雪**; the web pet is provided by kiriyuki.com.
