- Home
- Plugins
- Tools & Capabilities
- dsh-search-model
dsh-search-model
jsoncode/dsh-search-model
DeepSeek Harness Web 客户端插件:接管 composer 的【模型与推理等级】座位,在「模型」子列表首位插入一个大小写不敏感的连续子串模糊搜索框(div>input),实时过滤已配置模型;弹框宽度锁定防抖动。
Install
dsh plugin --profile web add github:jsoncode/dsh-search-modelREADME
dsh-search-model
dsh-search-model is a Web-client plugin for the DeepSeek Harness (DSH). It takes over the composer's Model & reasoning effort menu and adds an instant fuzzy search box at the top of the Model list, filtering every configured model as you type.
- Non-invasive — renders through the slot system only; uninstalling restores the stock UI byte-for-byte
- Case-insensitive substring search — multi-keyword AND, contiguous match
(
glmhitsGLM-4.6, nevergoogle) - Zero-jitter popup — the menu width is measured once on real content and locked while you filter
- Shared state — selections echo between this menu, the composer trigger and
the
/modelcommand palette
Features
- Slot takeover without patching the host: registers into the
conversation.input.modelsingle seat at a lower shadowing priority (priority: -1, lowest renders), replacing the built-in selector with an enhanced clone of the same two-level menu (Model / Effort rows → sub-lists). - Panel-scoped search box: the input appears only inside the Model sub-list (the root two-row view stays stock). It auto-focuses on entry; Esc clears the query first, then leaves the pane, then closes the menu.
- Contiguous-substring matching: lowercased token AND; every keyword must
appear as a contiguous substring of provider display name / provider id /
model name / model id / description. No character-skipping subsequence
matches, so out-of-order input like
glmnever surfacesgoogle. - Live filtering: groups with zero hits are hidden; clearing the query restores the full catalog. A "no matches" empty state replaces the list when nothing matches.
- Popup width lock: when the Model pane opens with the catalog settled and an empty query, the menu's natural content width is measured once and pinned in px — typing cannot resize the card. Leaving the pane / closing the menu / re-entering resets and re-measures. The decorative native 420px max-width cap is dropped (a viewport-safety bound remains), so long model names and descriptions are never clipped by the card itself.
- Data parity with the host: the plugin prefers the core
ctx.modelDirectoriesservice — the exact per-session directory instance the/modelpopup uses — so loading state, failures/retries, reasoning-effort switching and the "current selection" echo all behave identically. If that service is absent (host drift), it falls back to a lightweight built-in directory speaking the samesession.models/session.selectModelwire.
Installation
Requires a DSH installation with the web profile.
# From npm (once published)
dsh plugin --profile web add dsh-search-model
# From a GitHub Release tarball
dsh plugin --profile web add ./dsh-search-model-0.1.2.tgz
# From a local checkout (development)
dsh plugin --profile web add ./
Verify the bundle layer landed, then start / restart the host:
dsh --profile web --dump-config # shows a "# == dsh-search-model" layer
dsh --profile web # restart required to pick up lib/client.js
Installing from source via
github:direct add does not work for this package (there is nopreparescript by design): git installs fetch sources, which have no builtlib/. Download the release tarball instead, or install from npm.
Usage
- Open any session in the DSH Web GUI.
- Click the model chip at the right end of the composer tool row (left of the send button).
- In the Model & reasoning effort menu, open 模型 / Model.
- Type in the search box on top — the list filters instantly (case ignored, multiple keywords AND-ed).
- Pick a hit to select it; the selection syncs everywhere (trigger label,
/model, effort list).
Uninstall:
dsh plugin --profile web remove dsh-search-model
Development
pnpm install
pnpm check # type-check (tsc -b --pretty false)
pnpm build # rm lib && tsc -b && tsdown → lib/index.js (host ESM) + lib/client.js (browser factory)
pnpm watch # rebuild client bundle on change
pnpm verify # simulate the host __ModuleLoader__ boot against lib/client.js
Release flow (maintainers):
pnpm release # check → build → verify → npm version patch → push tag
# the v* tag triggers .github/workflows/publish.yml:
# build → pack → GitHub Release → npm Trusted Publishing
pnpm publish:npm # manual local publish channel (runs the full pre-flight)
Structure
├── src/host/index.ts # Minimal host-half anchor (Loader entry + dsh.client discovery)
├── src/client/
│ ├── index.ts # Plugin module: style injection + conversation.input.model takeover
│ ├── face.ts # Seat inject-face resolution (shared ctx.modelDirectories, fallback directory)
│ ├── SearchModelSelect.tsx # Seat component: two-level menu + panel search + width lock
│ ├── fuzzy.ts # Case-insensitive contiguous-substring matcher (token AND)
│ ├── store.ts # Lightweight snapshot store for the fallback path
│ ├── styles.ts # Style injection (dsm-* classes over host --dsw-* tokens)
│ └── types.ts # Local mirrors of the wire contracts (zero runtime deps)
├── lib/ # Build artifacts (index.js, client.js, types/) — see files[]
├── scripts/verify-client.mjs # Host-seed simulation check for the browser bundle
├── tsdown.config.ts # Build config (node half + __ModuleLoader__ banner wrapper)
├── tsconfig{,.host,.client}.json # Solution + two isolated aggregates
├── cordis.patch.yml # Bundle patch row (plugin referenced by package name)
└── package.json # dsh.bundle + dsh.client(web) manifests
Compatibility
- Built against
@deepseek-ai/*0.1.0-rcreleases; peer ranges accept^0.1.0-rc.6. - All
@deepseek-ai/*imports are type-only — runtime externals stay inside the host seed module table (react,react/jsx-runtime,react-dom,@deepseek-ai/dsh-client-ui-primitives), enforced byverify.
License
MIT © jsoncode
Related plugins
archify (deepseek-harness)
tt-a1i/archify
WeKnora (dsh-weknora)
tencent/weknora
weknora
tencent/weknora
BrowserSkill (dsh-plugin-browserskill)
tencent/browserskill