Skip to content
dsh.fish
Bundle

dsh-client-ui-model-search

Searchable, collapsible model selector for the DeepSeek Harness web UI. Replaces the composer model seat with a search box and per-provider group collapse while reusing the official shared model directory.

Source
AndyZHENG0715
License
MIT
Updated
Updated yesterday

Readme

# dsh-client-ui-model-search

A small client UI plugin for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) that makes the web composer's model selector usable at scale:

- 🔍 **Search box** at the top of the model list — filters as you type.
  - Tokenized AND matching: `opencode-go deepseek` finds OpenCode Go's DeepSeek models (hyphens and underscores are treated as spaces).
  - Matches model name, model id, description, provider name, and provider id.
- 🗂️ **Collapsible provider groups** — click a group header to collapse/expand it. A count badge shows how many models a group holds.
- 🌗 **Theme-aware** — uses DSH design tokens (`--dsw-*`), so light/dark follows the active theme.
- 🌐 **Bilingual** — zh-CN and en dictionary via the official `locale` service.
- ♻️ **Non-destructive** — registers on the official `conversation.input.model` seat with `priority: -1`, so the shipped selector stays mounted underneath as a fallback. Uninstall (or stop the plugin) and the native selector returns.

> **Not an official DeepSeek product.** No endorsement, review, or store listing by DeepSeek.

## How it works

The official `@deepseek-ai/dsh-client-ui-model-selection` package owns a per-session `ModelDirectory` service (`ctx.modelDirectories`) shared by the composer model seat and the `/model` popup. This plugin reuses that exact directory — including `select()` — so a picked model lands on the standard `directory.select()` path and stays in sync with `/model`.

## Install

Requires a DSH profile with the web UI.

```sh
dsh plugin --profile <name> add dsh-client-ui-model-search
```

Then restart the profile:

```sh
dsh --profile <name> web
```

Open the model selector in the composer (bottom-right). The search box appears above the model list; group headers are clickable.

### Local checkout

```sh
dsh plugin --profile <name> add ./dsh-client-ui-model-search
```

## Uninstall

```sh
dsh plugin --profile <name> remove dsh-client-ui-model-search
```

Restart the profile: the native selector returns (it was never removed).

## Screenshots

![模型列表:多提供方分组、计数徽标、当前选中模型](screenshot-1-model-list.png)

![分词搜索:输入 opencode flash 同时匹配 OpenCode-Go 与 OmniRoute 下的 Flash 模型](screenshot-2-search.png)

![分组折叠:DeepSeek 展开,其他提供方分组已收起](screenshot-3-collapse.png)

`demo.html` renders the exact menu UI (same CSS classes and mock data) standalone in any browser — open it to take additional screenshots.

## Compatibility notes (DSH is pre-release)

- The package is authored against the official bundle format: `package.json` `dsh.bundle.patch` → `cordis.patch.yml`, plus a `dsh.client` web entry, matching `@deepseek-ai/dsh-client-ui-model-selection@0.1.1-rc.2`.
- `dsh-plugin.json` is a **Community Draft v0.15** manifest ([dsh-std](https://github.com/Yan-Zero/dsh-std), schema validated). It declares a no-op `host` facet because the v0.15 draft has no web-slot contract; the composer-seat contribution therefore rides the official web slot, not a dsh-std contract. When upstream adds a web contract, this can be upgraded.
- If upstream renames `conversation.input.model` or the `modelDirectories` service, this plugin stops taking effect (and the native selector simply stays). That is the documented cost of riding an official seam; the dsh-std adapter path is the mitigation once a web contract lands.

## License

MIT

Install

dsh plugin --profile web add github:AndyZHENG0715/dsh-client-ui-model-search#da64477187a511e90a6841c2a3db536cfda3d2af

Profile: web

Source