Skip to content
dsh.fish
Bundle

dsh-fetch-models-search

Adds a search box to the 'Fetch available models' candidate dialog in DSH Settings — pure browser-side DOM enhancement, no component modification. 为「设置→模型→获取可用模型」候选弹窗增加搜索过滤,纯浏览器半增强,不改任何组件代码。

Source
masknull
License
MIT
Updated
Updated 4 days ago

Readme

# dsh-fetch-models-search

[English](README.md) | [中文](README.zh.md)

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

> 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:

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

Or, from a local checkout:

```sh
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.body` — `role="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

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

## Package layout

| Path | Purpose |
|---|---|
| `cordis.patch.yml` | bundle patch — inserts the `fetch-models-search` loader row |
| `lib/index.js` | host half — empty `apply` (the row must exist host-side; the browser half is discovered via the `dsh.client` declaration) |
| `lib/client.js` | browser half — search-box injection + filtering |
| `scripts/verify.mjs` | jsdom end-to-end verification (18 assertions) |

## Development & verification

```sh
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](LICENSE)

Install

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

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source