dsh-models-filter
DeepSeek Harness plugin used to add an input filed to filter the models menu. (with arrow up/down + enter)
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 29, 2026
- Updated
- Aug 29, 2026
Introduction
dsh-models-filter
A DeepSeek Harness profile bundle that adds a filter input at the top of the model-list pane of the composer model menu. The root Model/Effort pane and every other part of the menu stay exactly as shipped.
[!CAUTION] This plugin has been fully vibe-coded with GLM-5.3-FLASH (Ox Alpha).
It was a simple exercise to try out the LLM during its free test phase.
(Everything came straight from the LLM — code, comments, readme, etc.)
I don't have any experience writing DSH plugins, so I can't vouch for the code quality.
[!WARNING] I'm not a big fan of how the CSS classes are used inside the plugin, especially the const
C = {}map, because in future versions of DSH the class hash prefix may change and this will break the plugin.
So this plugin is actually dependent on DSH's 0.1.1-rc.2 version.
[!NOTE] Post on X (with a short video showing the plugin in action)
Install
From a local checkout:
dsh plugin --profile web add ./dsh-models-filter
Or straight from GitHub (any pnpm-compatible spec works):
dsh plugin --profile web add gh:<user>/dsh-models-filter
# or:
dsh plugin --profile web add git+https://github.com/<user>/dsh-models-filter.git
Then restart the profile (dsh web) so the new bundle layer composes in.
lib/ artifacts are committed, so installs never need a build step and no
pnpm allowBuilds entry.
Uninstall with dsh plugin --profile web remove dsh-models-filter, or disable
just this row without removing the package by adding to the profile's own
cordis.patch.yml:
- id: models-filter
disabled: true
What you get
- Opening the menu shows the unchanged Model / Effort cells — no filter there.
- Entering Model shows the list pane with the filter row on top,
autofocused; typing filters case-insensitively by model name, id,
description, or provider name/id; emptied groups drop out;
×orEscclears and restores the full list in place. - Combobox keyboard navigation:
ArrowDown/ArrowUpmove a highlight across the visible rows (wrapping at the ends) while focus stays in the filter input — the highlight ridesaria-activedescendant.Enterselects the highlighted row;Escapecascades clear query → back a pane → close. Typing resets the highlight to the first visible row. - Two-tier emphasis: the pre-selected row carries a stronger layered fill so it reads clearly in both themes; mouse hover keeps the lighter shipped hover fill and never moves the pre-selection.
- Deterministic scrolling: wrapping to the first row snaps to top; otherwise the pre-selected row is revealed minimally, always fully below its sticky group title; already-visible rows cause no scroll.
- Selections flow through the shipped shared per-session
ModelDirectory(ctx.modelDirectories), so/model, the composer trigger, selection state, and the composer's model-unavailable block stay exactly in sync.
How it respects the existing design
- The menu renders with the shipped stylesheet's own class names
(
_7KE1Ra_*, content-hash classes from the deployment'sdsh-client-ui-model-selectionbuild). Trigger, Model/Effort cells, provider group titles, options, selected check, loading/error/warning strips: all are the product's real markup and real styles. A copy of the shipped stylesheet is kept inshipped.cssfor provenance. - The only new CSS rules are the
dshmf-*classes for the added row and its highlight state, written from the same design tokens and idioms: 10px control radius, caption tone placeholder, subtle borders, hover fill, and the trigger's 2px focus ring. They ship as one deduped<style data-plugin-css>tag owned by the plugin fiber. - All menu strings come from the shipped
modellocale namespace; the filter row registers its own tinymodels-filternamespace (en + zh).
Package layout
| File | Purpose |
|---|---|
package.json | The dsh manifest: bundle.patch + client declaration. |
cordis.patch.yml | Bundle patch layer: inserts the discovery host row. |
lib/index.js | Host half (GENERATED from src/index.ts) — a deliberate no-op marker plugin (see below). |
lib/client.js | Browser half (GENERATED from src/client.ts) — committed lazy-CJS bundle served at /plugins/dsh-models-filter/client.js. |
src/client.ts | Readable TypeScript source of the client half: the factory body plus the type declarations the build erases. |
src/index.ts | TypeScript source of the host half. |
scripts/build.mjs | Transpiles src/*.ts into the committed lib/*.js (types erased, comments kept). |
tsconfig.json | Strict tsc --noEmit configuration for pnpm typecheck. |
shipped.css | Extracted shipped stylesheet kept for class-fidelity provenance. |
How it wires into a profile
Three declarations make the package a real bundle rather than a plain dependency:
"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }—dsh plugin addreconciles installed dependencies againstdsh.profile.bundles; declaring a patch is what turns this package into a profile layer instead of printing the "declares no dsh.bundle" warning.- The patch inserts one loader row (
id: models-filter,name: dsh-models-filter). The web client-module scan discovers browser bundles by walking activated loader entries and matching each entry's name against installed packages declaringdsh.client— without this row the client half would never join the boot graph. The host half itself is a no-op marker; all behavior lives client-side over services the web surface already mounts (slots,locale,modelDirectories,sessions). "dsh": { "client": { "platform": "web", ... } }+exports["./client"]— once the entry activates, the scan resolves this manifest and adds the bundle to thewindow.__DSH_BOOT__graph. The vendored client Loader then imports it like any shipped client plugin: the factory runs once, returning{ inject, apply }; Cordis fiber governance (service waiting, stop/update disposal) applies unchanged.- The seat is shadowed at
priority: -1, never replaced. The composer's model seat is a single slot that admits one registration per priority — the shippeddsh-client-ui-model-selectionseat holds priority 0, so this bundle registers one priority lower (lower renders) and the shipped entry stays registered but dormant. Unloading or disabling this plugin disposes its-1entry and the shipped seat takes back over with no gap.
Development
Sources are TypeScript; the committed lib/ artifacts are generated from them
by transpilation (type annotations erased, comments and runtime code kept
verbatim), which is why installs never run a build and the package has zero
runtime dependencies.
pnpm install # runtime deps: none — devDependencies (typescript) serve build/typecheck only
pnpm typecheck # tsc --noEmit over src/ (strict)
pnpm build # regenerate lib/client.js + lib/index.js after editing src/*.ts
link:-style installs (add ./dsh-models-filter) symlink the checkout, so a
rebuild plus a profile restart picks edits up immediately. Commit regenerated
lib/ files before publishing.
Known deviation
On a rejected selection the shipped component raises a transient Toast; this plugin leaves the menu open instead. Load errors keep the shipped inline Retry strip.
License
Author
@odelbos (with GLM-5.3-FLASH)