DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Villager Hmm — DeepSeek Harness 插件(DSH Plugin)
← Plugins

dsh-villager-hmm

Villager Hmm

每当模型在其推理链中发出“嗯”声时,播放原版 Minecraft 村民的“嗯”声。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add dsh-villager-hmm@1.0.8
README兼容性版本

兼容性与来源证明

Villager Hmm 以 dsh-villager-hmm 发布,当前版本为 1.0.8。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/9/18

版本

1.0.8stable
2026/9/18
1.0.3stable
2026/9/18
1.0.2stable
2026/9/10
查看其余 1 个版本
收起版本
1.0.0stable
2026/9/10

相关插件

正在加载相关插件…

最新版
1.0.8
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
84.8 kB
文件数
8
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 1
周下载
0
最近提交
2026/9/18
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录

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.

相关插件

继续浏览 vision-media 分类下经过校验的插件。

Tool Describe Image@linxin666/dsh-tool-describe-image面向模型的 describe_image 工具,用于 dsh Web GUI:通过在兼容 OpenAI 的端点调用视觉语言模型,为文本模型提供图像理解能力,以描述一张图像(本地路径、http(s) URL 或附件引用)。可热插拔 —Modlens@liustack/modlens面向仅支持文本的 LLM 的插件视觉能力,由免费的 Antigravity CLI 提供支持Deepseek Ivideodeepseek-ivideoiPolloWork HyperFrames Video Studio,以及 27 个可编辑视频模板,以原生 DeepSeek Harness 对话视图呈现。Codexdsh-codexChatGPT OAuth、Codex 模型、搜索、read_image URL 支持,以及适用于 DeepSeek Harness 的 gpt-image-2 生成