Back to home@masknull

dsh-fetch-models-search

DSH plugin: adds a search box to the Fetch available models candidate dialog in DSH settings (browser-side DOM enhancement). DSH 插件:为「获取可用模型」候选弹窗增加搜索过滤。

Stars
0
Language
JavaScript
Created
Aug 26, 2026
Updated
Aug 26, 2026
GitHub repo

Introduction

dsh-fetch-models-search

English | 中文

License: MIT

Add a search box to the Fetch available models dialog in DSH settings → Models — filter the candidate model list as you type.

A pure browser-side DSH plugin. It injects a search input above the candidate list opened by Fetch available models and filters rows in real time (case-insensitive substring match on the model id). It does not modify or patch any component code — it is a self-contained DOM enhancement that degrades to a no-op when the dialog is not present.

Features

  • 🔍 Search box injected at the top of the candidate model picker; type to filter instantly.
  • 🧱 No component modifications — built entirely on stable DOM structure, no CSS-hash class selectors.
  • ♻️ Survives React re-renders: a MutationObserver (frame-coalesced via requestAnimationFrame) re-applies the current filter whenever the candidate list is rebuilt.
  • ✓ Filtering never touches checkbox selection or the Select all / Deselect all semantics.
  • 🧹 Fully reversible: only display toggles and one injected style element; uninstall restores the page exactly.
  • 🌐 Localized: search placeholder and "no matches" hint follow the page language (zh ⇒ Chinese).
  • 🪶 Zero runtime dependencies: the bundle does not import any @deepseek-ai module at runtime and ships its complete __ModuleLoader__.load closure factory wrapper.

Installation

Install from GitHub into the web profile:

dsh plugin --profile web add github:masknull/dsh-fetch-models-search

Or, from a local checkout:

dsh plugin --profile web add link:D:\.dsh\plugins\dsh-fetch-models-search
# or from the package directory itself:
dsh plugin --profile web add .

Restart DSH Desktop / the dsh service after installing. The client-module graph (window.__DSH_BOOT__) is composed at startup; a page refresh alone will not pick up a newly added plugin bundle.

Usage

  1. Open Settings → Models.
  2. Expand a pi-ai provider card and click Fetch available models.
  3. The picker opens with a search box above the candidate list. Type part of a model id to narrow the list; clear it to show all candidates again.
  4. Selection behaviour (checkboxes, Select all / Deselect all, Add selected) is unchanged.

How it works

  • Targeting: the picker is a ui-primitives Modal rendered via createPortal into document.bodyrole="dialog" + aria-modal="true". Its unique structural fingerprint is a <ul> whose <li> children contain input[type=checkbox] (other dialogs, e.g. the delete-confirmation dialog, have no such list). No CSS-module hash class names are used, so the anchor is immune to theme/language changes.
  • Injection: a search <input type="search"> is inserted immediately before the candidate <ul>; a <style> element with --dsw-alias-*-token styling is injected once into <head>.
  • Filtering: rows keep their DOM nodes; non-matching ones get display: none. A "no matching models" hint appears when the query yields nothing and disappears when cleared.
  • Lifecycle: apply(ctx) registers the observer and hands a cleanup back through ctx.effect; the plugin unload restores everything (observer disconnected, style removed).

Uninstall

dsh plugin --profile web remove dsh-fetch-models-search

Package layout

PathPurpose
cordis.patch.ymlbundle patch — inserts the fetch-models-search loader row
lib/index.jshost half — empty apply (the row must exist host-side; the browser half is discovered via the dsh.client declaration)
lib/client.jsbrowser half — search-box injection + filtering
scripts/verify.mjsjsdom end-to-end verification (18 assertions)

Development & verification

node scripts/verify.mjs

The script loads lib/client.js through a simulated window.__ModuleLoader__, builds a dialog DOM isomorphic to the real picker, and asserts: correct dialog targeting (no false positives on other dialogs), injection, filtering, checkbox isolation, filter persistence across re-renders, no-match hint, re-open re-injection, and lifecycle cleanup.

Limitations

  • Applies only to the Fetch available models picker; manually edited model rows are not involved.
  • Matching is a case-insensitive substring match on the candidate id text only (no fuzzy / regex).
  • Select all / Deselect all still targets all candidates (original behaviour unchanged by the current filter).

License

MIT