DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Villager Hmm — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins

dsh-villager-hmm

Villager Hmm

Plays a vanilla Minecraft villager "hmm" whenever the model hums inside its reasoning chain.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add dsh-villager-hmm@1.0.8
READMECompatibilityVersions

Compatibility and provenance

Villager Hmm is published as dsh-villager-hmm and currently resolves to version 1.0.8. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
npm
Registry updated
9/18/2026

Versions

1.0.8stable
9/18/2026
1.0.3stable
9/18/2026
1.0.2stable
9/10/2026
Show 1 more versionCollapse versions
1.0.0stable
9/10/2026

Related plugins

Loading related plugins…

Latest
1.0.8
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
84.8 kB
Files
8
Surface
web
License
MIT
Source
npm
GitHub
★ 1
Weekly downloads
0
Last push
9/18/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in vision-media.

Tool Describe Image@linxin666/dsh-tool-describe-imageModel-facing describe_image tool for the dsh web GUI: gives a text-only model image understanding by asking a vision-language model at an OpenAI-compatible endpoint to describe one image (local path, http(s) URL, or attachment reference). Hot-pluggable — Modlens@liustack/modlensPlug-in vision for text-only LLMs, powered by the free Antigravity CLIDeepseek Ivideodeepseek-ivideoiPolloWork HyperFrames Video Studio and 27 editable video templates as a native DeepSeek Harness conversation view.Image Gendsh-image-genBring ChatGPT-like image generation to DeepSeek Harness — Gemini, OpenAI, Seedream, DashScope, local ComfyUI & more.

README

dsh-villager-hmm

A DeepSeek Harness plugin. Whenever the model goes "hmm" — inside its chain of thought, or in the reply itself — a Minecraft villager hums back at you.

A villager stands in the top-right corner, bobs on every hit, and carries the controls: pause, volume, which stream to watch, and the matcher itself.

Drag the title bar to move it; double-click the bar to send it back to the corner. The position is remembered in localStorage. It defaults to the top-right rather than the bottom-right on purpose — the composer is full-width, so a bottom-anchored overlay would sit on top of the send button.

┌──────────┬──────────────────────────────────┐
│ villager │ Villager hmm                  - │
│  figure  │ hits 12 · played 12              │
├──────────┴──────────────────────────────────┤
│ Reasoning 1284 chars  Reply 356 chars        │
│ Sounds 2 clips                               │
│ [ Listening · click to pause ] [ Play once ] │
│ Volume ─●─                                   │
│ Source  [ Reasoning only ▾ ]                 │
│ Matcher [ (?<!…) ]   [Apply] [Default]       │
│ Recent   hmm  嗯  唔                         │
└──────────────────────────────────────────────┘

Collapsed, the panel shrinks to nothing but the villager's head (a 36x40 crop of the face plus nose). Clicking the head expands the panel again; it still drags, and double-clicking still resets the corner. It bobs on every hmm, just like the full figure.

The panel follows the interface language: it registers English and Chinese dictionaries with the shared locale service and re-renders when the locale changes. If that service is unavailable it falls back to English rather than failing to render.

Install

dsh plugin --profile web add dsh-villager-hmm

That is the whole install. The package declares dsh.bundle, so dsh plugin registers it as a profile layer by itself — there is no configuration file to edit. Restart the profile when it finishes.

Then fetch the assets, from the profile directory (where the package's bin is linked):

cd "$DSH_HOME/profiles/web"
npx dsh-villager-hmm-assets

Skip this step and the plugin still loads. It shows its panel and prints the exact command to run — with an absolute path, so it works from any directory — and never fails silently.

Assets

This package ships no Minecraft material. The villager's sounds and textures are fetched on your machine into a per-user cache:

$DSH_HOME/.dsh-villager-hmm/assets/
  idle1.ogg           villager "hmm"
  idle2.ogg           villager "hmm", second take
  hit1.ogg            damage grunt, played when you pet the villager
  hit2.ogg            damage grunt
  hit3.ogg            damage grunt
  hit4.ogg            damage grunt
  villager.png        the 64x64 base skin, cropped into the figure by CSS
  villager-type.png   the villager type overlay — this is what puts the
                      brown robe on, see "The figure" below
  damage.png          the 8x8 damage-indicator heart thrown by the pet
                      interaction, see "Petting" below

The damage clips are named hit*, not hurt*: the game's own sounds.json maps the entity.villager.hurt event onto mob/villager/hit1..hit4, and no hurt*.ogg exists in the vanilla assets.

The panel shows the exact command if the cache is empty. Two sources are supported:

FlagMeaning
(none)Download from a public mirror of the vanilla 1.21.4 client assets
--from <dir>Copy from an asset tree you extracted yourself — the option that matches the game's terms
--base <url>Your own mirror with the same layout
--dir <path>Use a different cache directory
--forceRe-fetch files that are already there
# from an extraction you made yourself
node "$DSH_HOME/profiles/web/node_modules/dsh-villager-hmm/scripts/fetch-assets.mjs" \
  --from "C:/mc-extract/assets/minecraft"

The cache lives outside node_modules, so it survives plugin upgrades. The host half re-reads it per request, so running the fetch script takes effect on a page reload — no harness restart.

Configuration

Defaults live in the row. To override them, replace the insert in your own $DSH_HOME/profiles/web/cordis.patch.yml:

- insert:
    - id: dsh-villager-hmm
      name: 'dsh-villager-hmm'
      config:
        enabled: true
        mode: both      # 'reasoning' (chain of thought only) | 'both'
        pattern: '(?<![0-9A-Za-z])(?:h+m+|mhm+|m{2,})|[嗯唔哼呃]'
        assetDir: 'D:/my-assets'

Everything except assetDir is also editable from the floating panel.

mode defaults to both on purpose: plenty of models expose no separate reasoning channel, and a plugin that silently does nothing looks broken. Switch to reasoning once you have confirmed your model streams reasoning-delta — the panel's Reasoning counter tells you: if it climbs, you have a reasoning channel and can narrow the scope.

The matcher

The default pattern is (?<![0-9A-Za-z])(?:h+m+|mhm+|m{2,})|[嗯唔哼呃].

It uses a lookbehind rather than \b, for two reasons:

  • \b is ASCII-only in JavaScript, so it behaves unpredictably next to CJK characters — 嗯hmm would not match.
  • The CJK branch deliberately has no boundary at all, because those characters are always standalone interjections.

h+m+ covers hm, hmm, hmmm…; mhm+ covers the closed-mouth variant; m{2,} covers a bare mm. None of them fire inside ordinary words — comma, comment, command and ahmm all stay silent.

Write your own in the panel's 匹配式 field and hit 应用. A pattern that does not compile is reported inline instead of being swallowed.

How it works

The host half listens to the agent/assistant-stream event and scans reasoning-delta (and optionally text-delta) chunks against the matcher. The browser half polls that counter over the plugin's own HTTP prefix and plays a sound per hit.

The plugin only consumes. It registers one event listener and one HTTP prefix route; it publishes no service and patches nothing. If the harness stops emitting the event, or the overlay slot disappears, the plugin degrades to doing nothing — it does not take the boot or the page with it.

Two details shape the scanner:

frame.revision is not a stream identity. It increments on every frame. Keying the scan buffer by it resets the buffer on every delta, so the matcher only ever sees one character and never matches. The buffer is keyed by attemptId:turn:step.

The scan is inline, not debounced. Deltas arrive far faster than any debounce window, so every new delta cancels the pending timer before it can fire. Because the matcher keeps a consumed-offset cursor, scanning on every delta is amortised O(n). A match that ends exactly at the buffer end is deferred unless the attempt is finishing, so hm is never counted before the next delta can turn it into hmm.

The figure

The villager is composited in CSS out of the fetched 64x64 atlases. Every crop comes from Mojang's own model — Mojang/bedrock-samples, resource_pack/models/entity/villager.geo.json, whose Bedrock cube list matches the Java villager. The front face of a w x h x d cube with box-UV origin (u, v) is (u + d, v + d) sized w x h, and the model spans y 0..34 with the feet at 0, so the canvas is 16x34 and the head sits on top:

CubeOriginSizeUVFront faceCanvas
head[-4,24,-4]8,10,8[0,0](8,8) 8x104,0
nose[-1,23,-6]2,4,2[24,0](26,2) 2x47,7
body[-4,12,-3]8,12,6[16,20](22,26) 8x124,10
robe[-4,6,-3]8,18,6[0,38](6,44) 8x184,10
arm[-8,16,-2] / [4,16,-2]4,8,4[44,22](48,26) 4x80,10 / 12,10
forearms[-4,16,-2]8,4,4[40,38](44,42) 8x44,14
leg[-4,0,-2] / [0,0,-2]4,12,4[0,22](4,26) 4x124,22 / 8,22

Two of those cubes are easy to miss, and the figure looks wrong without them:

  • The robe is the second body cube. The base skin leaves its pixels fully transparent, because the game paints the robe from the villager type overlay texture at the same UVs. That is why villager-type.png is not decoration: without it the villager wears only the base under-robe.
  • The forearms are the folded arms across the chest, drawn last so they sit over the robe.

The nose hangs one pixel below the chin (y 23..27 against a head ending at 24), which is why the collapsed head's canvas is 11 tall rather than 10.

Every size in the stylesheet is derived from FIGURE_SCALE / FACE_SCALE and the canvas extents computed from the part list, so editing a part cannot leave the stylesheet behind. Coordinates stay integral, which is what keeps the 4x nearest-neighbour upscale crisp.

Petting

Collapsing the panel leaves the villager's head floating on its own, and that head is a pet:

  • Click it — the head flinches, flashes red, grunts, and throws the game's damage particles: minecraft:damage_indicator, the dark-red hearts from textures/particle/damage.png. That sprite is an 8x8 luminance mask with a grey interior, so the burst is brightened and tinted through the same red matrix as the flash rather than pasted in raw (an untinted heart is grey, and one tinted exactly like the villager disappears into it).
  • The ▣ button under it restores the full panel. Petting and restoring are separate controls on purpose: folding both onto the head's click is what made the head unpetable in the first place.

The expanded panel's body reacts to a click the same way, so the villager can be petted in either form. Neither path touches the host: a pet plays a damage clip straight away rather than waiting behind the rate-limited queue that the ambient hmm sounds go through. The burst is derived from the pet counter through a hash rather than Math.random(), because the panel re-renders on every 250 ms poll and a fresh random set each time would make the hearts teleport mid-flight.

The gestures are split deliberately, because a pet is a click and petting twice in a row is a dblclick:

GestureEffect
Click the villagerpet it
Drag the villagermove the panel — 4px of travel before it counts as a drag
Double-click the villagertwo pets, and nothing else
Double-click the bar chromesend the panel back to its default corner

The villager swallows double-clicks instead of letting them reach the bar. Binding the reset to a double-click anywhere on the bar is what made a run of pets jump the panel to the top-right corner; the drag threshold is what stops a pixel of hand shake from being read as a drag, which both pinned the panel to a pixel position and swallowed the pet.

The tint lives inside the @keyframes, never on the class that starts them. An element keeps its class after an animation ends, so a filter declared on .vhm-pet would leave the villager permanently red; and because filter: url() cannot interpolate, the keyframes hold the tint at full strength and then swap to none across two stops 4% apart, which is what makes it read as a flash.

Routes

The plugin owns one HTTP prefix, /dsh-villager-hmm:

RoutePurpose
GET /state?cursor=Ncounters, asset status, and triggers newer than N
GET /config?enabled&mode&patternchange settings at runtime
GET /sound/<n>.oggambient "hmm" audio, read from the cache
GET /hurt/<n>.oggdamage audio for the pet interaction, from the cache
GET /texture.pngthe base villager skin, read from the cache
GET /type.pngthe villager type overlay — the robe, read from the cache
GET /particle.pngthe 8x8 damage-indicator heart, read from the cache

Development

See CONTRIBUTING.md for the test suites, what CI enforces, and the release process.

License

The code is MIT (see LICENSE — kept verbatim, with nothing appended, so GitHub detects it as MIT rather than "Other").

No third-party assets are bundled or redistributed: scripts/fetch-assets.mjs downloads them on your machine, at your direction, into a local cache. See NOTICE for the asset terms. Minecraft is a trademark of Mojang Studios; this project is not affiliated with or endorsed by Mojang or Microsoft.