dsh-pet-sayaka: A desktop pet plugin that turns DSH session status into expressions and voice

Introduction

When running long tasks in the DSH Web interface, the interface is silent: you don’t know if the model is currently thinking, if a command is executing, or if it has already errored out; you can only stare at the logs to repeatedly confirm. The dsh-pet-sayaka plugin does something very direct—it listens to the DSH session state and translates it into expressions, short lines, and voiceovers using a desktop pet (Kamishiro Sayaka) in the bottom right corner of the interface. Running code makes it draw its sword, reporting an error makes it sad, success makes it happy, making the execution status visible at a glance.

It is maintained by KOGGUA-EDIT, open source, and under the MIT license. Below is an introduction following the order of “What is this—How states are mapped—How voiceovers are triggered—How to install—How to use”.

What is it

One-sentence positioning: Adds a desktop pet to the DeepSeek Harness Web UI, maps session runtime states to twelve standing illustrations, and pairs them with dialogue bubbles and audio. The maintainer is KOGGUA-EDIT, the source code is in the dsh-pet-sayaka repository on GitHub, and the labeled category is “Fun Cosplay”.

It doesn’t solve a functional problem, but a feedback problem. How long will the command take, did this round actually succeed, or is it stuck right now—you can tell without reading the logs.

The plugin targets the Web端, injecting frontend resources via the DSH plugin system’s bundle mechanism, not going through the function call route.

State Mapping

The plugin maps DSH session states to twelve standing illustrations (assets/pet/<state>.png, 784x720 transparent background), switching is a direct replacement with no fade in/out. The mapping provided by the README is as follows:

Session State Corresponding Expression Illustration Name
Idle Sleeping sayaka-睡觉 (Permanent, occasionally wipes sword when idle)
Thinking Thinking sayaka-思考
Running Code (bash / pwsh etc. command-line tools) Drawing Sword sayaka-拔刀
Run Failed (non-zero exit, isError, timeout, killed, whole round error) Sad for 5 seconds sayaka-伤心
Run Success Happy for 5 seconds sayaka-高兴
Round finished, and no other sessions are running Collapsed for 5 seconds sayaka-累倒
First minute after first run Calm → 1 min → Sleeping sayaka-平常心
During Sleeping / Calm / Thinking, every 14~30 seconds Wiping Sword for 3.5 seconds sayaka-擦剑
First two pokes Ignoring —
Three pokes in 10 seconds Shy for 1 second sayaka-害羞
Five pokes in 10 seconds Angry for 3 seconds sayaka-生气
Ten pokes in 10 seconds Exploded for 6 seconds sayaka-生气2 (Highest priority)
Holding and dragging Dragged away sayaka-拖拽

In implementation, the illustrations are cached and switched directly at runtime. The first eight are versions cut, background removed, and compressed from the original large image (one is 75-95 KB); the last four were added later, quantized to 256 colors, one is 64-79 KB. The 1 MB original images are not included in the repository.

Dialogue Bubbles and Voiceovers

When a state first switches, a monologue bubble pops up: a large rounded rectangle with a white background, dark gray stroke, and 20px border radius, displaying for only 1 second. Long states like Sleeping or Calm won’t keep the text hanging; it only appears during that one second of switching. Bubble width follows the number of words (widest up to 1.7 times the pet’s width), font size scales with the pet’s size.

For example, Thinking displays emmmmm, Drawing Sword displays 武装保卫见泷原!, Happy displays 耶✌️, and Exploded displays 你再戳一下试试!. See the README for the full list of lines.

Lines aren’t just fixed sentences during state switching; they also change responses based on accumulated counts. When the same state is encountered for the Nth time, it switches to a line that sounds more like a response, and the expression and audio are changed if necessary. The rules are written in the QUIPS table in lib/client.js. Adding a line is adding a row, the at field indicates how many times this state has accumulated in the current round:

State Nth Time Line Audio Bonus
Sad 2 又出问题了 quip-sad-2.wav —
Sad 5 气死我了!!! angry.wav Expression switches to Angry for 3 seconds
Sad 9 这点小事才不会让我认输! quip-sad-9.wav Then resets counter
Happy 2 嘿嘿,成了 quip-happy-2.wav —
Happy 5 今天日子真不错 quip-happy-5.wav Then resets counter
Drawing Sword 5 我可不是跑腿的! quip-sword-5.wav Then resets counter
Thinking 3 想不出来… quip-thinking-3.wav Then resets counter
5 pokes in 10 seconds — 别戳了!!! quip-poke.wav Angry for 3 seconds
10 pokes in 10 seconds — 你再戳一下试试,我绝对不放过你! quip-poke2.wav Exploded for 6 seconds

It resets when reaching the last tier, so it’s “get angry every five errors,” and the next five errors will get angry again, not just the first time.

Regarding audio, each state has a recording (assets/pet/<state>.wav) that plays with the state; situational lines have dedicated recordings (assets/pet/quip-*.wav). State recordings aren’t played every time; each state tracks a separate counter: +1 every time you enter the state, play once after accumulating 5-8 times, reset, and then roll a new random interval of 5-8. The casual morning.wav says the first sentence after every startup, not replaying on page refresh; if the browser blocks autoplay, it will catch up on the first click/key press. Shy speaks every time it is poked, not accumulating counts; dragging and consecutive pokes have their own dedicated recordings. Only one plays at a time; if the previous one isn’t finished when the next starts, it is cut short directly; two lines won’t overlap.

If you don’t want this interval, there is a “Speak on every change” switch in the “sayaka” section of the settings page: turning it on stops counting, and Drawing Sword / Happy / Sad / Thinking / Sleeping / Calm will play a segment directly on every change (Shy, Angry, Dragged already have their own dedicated lines, so they won’t repeat). The “Audio” switch in the same section can turn off all sounds with one click, while the expressions move normally.

Installation and Usage

Install from npm (recommended):

dsh plugin --profile web add dsh-pet-sayaka

Or install directly from GitHub:

dsh plugin --profile web add github:KOGGUA-EDIT/dsh-pet-sayaka

After installation, the Web service needs to be restarted once to take effect: DSH title bar “⋯” → “Restart Web Service”, then refresh the page, and you can see the desktop pet in the bottom right. The reason is that the manifest of browser plugins (which plugins have frontend bundles) is scanned when the Web service starts, and the list is fetched from the server when the page loads.

When developing locally, the README also introduces a non-packaging wiring method: source code is placed in a fixed directory, and a tools/install.mjs script is used to write the plugin into the profile’s dependencies, add to dsh.profile.bundles, and create a link (or junction) in node_modules pointing to the source directory. The script has --status / --uninstall parameters, is idempotent, and running it repeatedly is fine. When using source code for development, changes or preference changes require restarting the Web service to take effect; the same applies to installation and uninstallation.

Uninstall via CLI:

NODE="$LOCALAPPDATA/Deepseek Harness EAC/dsh-desktop/vendor/node/node.exe"
BIN="$LOCALAPPDATA/Deepseek Harness EAC/dsh-desktop/node_modules/@deepseek-ai/dsh/lib/bin.js"
"$NODE" --use-system-ca "$BIN" plugin --profile web-desktop remove dsh-pet-sayaka

It is worth noting that this uninstall command is copied from the author’s Windows local path in the README; when changing machines, adjust according to your own DSH_HOME and profile name. Every version has a tag and a packaged tgz attached in the Releases page.

Scenarios and Notes

Suitable for DSH Web users who need to monitor long tasks for a long time and value runtime feedback, especially in scenarios like solo development where you don’t want logs taking up the whole view. It only reads session states for visual mapping and does not change command execution logic or affect the normal invocation of the plugin itself.

A few points to note:

  1. After being loaded by the plugin system, it runs with the permissions of the current dsh Web process and can access the sessions and tool events loaded by that profile. Before installing, you should open the source code to verify and confirm there is no extra request behavior or local data exfiltration.
  2. The license is MIT, author attribution is KOGGUA-EDIT; if you want to replicate the illustrations and audio, you need to confirm the copyright of the materials yourself; the repository only contains compressed images and wav files.
  3. It targets the Web interface, injecting via frontend bundle, so if you install it on a profile without a Web service, you won’t see anything.
  4. Both bubbles and voiceovers can interrupt attention; for those who need a quiet environment, it is recommended to turn off “Audio” in the settings page first, or only keep the state face switching.

Conclusion

The value of dsh-pet-sayaka is not in adding another feature, but in adding a perceptible visualization layer to the silent session: running commands makes it draw its sword, finishing makes it collapse, errors make it switch to sad, and repeated errors change the lines. For people staring at the Web UI to run tasks, it saves trouble compared to repeatedly checking logs. The directory page is https://www.skillhub.cn/plugins/KOGGUA-EDIT/dsh-pet-sayaka, and the source code is at https://github.com/KOGGUA-EDIT/dsh-pet-sayaka.

羽毛球分组比赛记分
小程序二维码

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

Xiaoye