mrdevlorx/dsh-model-garden
A searchable, sortable model picker for the DeepSeek Harness Web UI — provider groups, favorites, models.dev prices, context windows, live per-task token cost and a local-model filter. One-command install: dsh plugin add dsh-model-garden.
项目介绍Project Overview
dsh-model-garden 是 DeepSeek Harness Web UI 的模型选择器插件,用表格视图替换默认模型栏。它支持名称/描述即时搜索、列点击排序、收藏(localStorage 持久化)、按端点识别本地模型、可折叠的提供方分组,并展示每百万 token 的输入/输出价格与上下文窗口;订阅路线通过 PROVIDER_ALIASES 解析参考价,本地模型保持无价。聊天撰写器内嵌推理强度下拉,开始新模型时自动选中其最高档。实时按模型归因的用量与费用、悬停展开的会话成本明细(支持列排序、CSV 导出)均由 host 的 /model-garden/cost* 路由提供。安装只需 dsh plugin --profile add dsh-model-garden 然后重启并硬刷;纯 TUI 环境下插件按设计保持 inert。
dsh-model-garden is a static-profile plugin for the DeepSeek Harness Web UI that replaces the native model seat with a searchable, sortable table picker. It adds instant name/description search, click-to-sort columns, starred favorites, collapsible provider groups, and a Local filter that flags providers by their real endpoint. Prices come from models.dev with subscription routes resolved through PROVIDER_ALIASES, and context windows are read live from the host llm service. A reasoning-effort dropdown sits in the composer, opening models at their strongest level. Per-model usage and cost attribution, plus a hover cost breakdown with sortable step tables and CSV export, are served by the host's JSON routes. Install via dsh plugin --profile add; TUI-only profiles stay inert.
请帮我了解并安装插件:【dsh-model-garden】【https://github.com/mrdevlorx/dsh-model-garden】
把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.
或使用命令行安装(适合开发者)Or use CLI install (for developers)
命令行安装CLI Install
dsh plugin --profile web add dsh-model-garden
把 mrdevlorx/dsh-model-garden 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
dsh-model-garden
A searchable, sortable model picker for the DeepSeek Harness Web UI (dsh web). It replaces the native composer model seat with a table-style picker that adds everything the stock selector is missing:
![]() |
![]() |
Features
- 🔍 Instant search across model names and descriptions
- 📊 Sortable table columns — click
Name,CtxorPriceto sort asc/desc; a third click returns to the provider-grouped view - ⭐ Favorites — star models, toggle favorites-only from the table header; persisted in
localStorage - 🏠 Local tag — providers are flagged local by their real endpoint (baseURL from settings: loopback / RFC1918 / LAN hostnames), never by price guesswork; the Local box next to the search input filters to them
- ▾ Collapsible provider groups — collapse state is persisted per provider
- 💰 Model prices from models.dev (the same source OpenCode uses), shown as
$input/$outputper 1M tokens, cached for 24 h. Subscription routes (all-zero cost in the catalog, e.g. coding-plan providers) resolve a reference price from their pay-as-you-go provider viaPROVIDER_ALIASES, so plan models still show what their tokens would cost at API rates; only true local models stay unpriced - 🧠 Context windows — read live from the host
llmservice (adapter-owned data, works for local providers like llama.cpp / Ollama-style gateways too), with models.dev as fallback - 🎚️ Reasoning effort picker — models that support reasoning levels get a compact dropdown right next to the model name in the chat composer, styled and opening exactly like the model picker (same trigger pill, same floating menu surface, ✓ marks the active level, click outside /
Esc/ selecting closes it). Picking a model always starts it at its strongest reasoning level; the dropdown re-selects the current model with the chosen effort — no clutter inside the picker panel - 💸 Live per-task usage & cost — real provider-reported token usage (from the session log) is always shown while the panel is open (
in / out / cache). Each model's usage is multiplied by its own (reference) price — properly attributed even when a session switched models mid-way — the same math OpenCode uses (usage × price, not a heuristic) - 🧾 Session cost breakdown — hover the
approx costfigure for a popup sized like the picker and parked parallel on its left (1 px gap): a table-style breakdown with per-model totals (steps, In/Out/Cache in their own columns, ≈ cost) and a timestamped step table. Clickable column headers work like Excel / the main list (asc → desc → off, ▲/▼ indicator) on both tables; copy the summary or export the (sorted) step list as CSV (Excel-ready). The invisible hover target spans the cost row all the way to its left edge. Attribution of each step to its model comes straight from the session log (request/contextevents); nothing extra is stored - 🖱️ Detail tooltip that opens beside the panel (never covers the list): description, price, context window, max output, reasoning efforts
- 🎨 Native look — built entirely on the harness design tokens (
--dsw-alias-*); the picker panel, the effort menu, the detail tooltip and the cost popup all share the same surface color and geometry, matching light & dark theme automatically
How it works
The package is a static profile plugin with two halves:
| Half | File | Role |
|---|---|---|
| Client | client.js |
Registers the conversation.input.model slot (priority -1, shadowing the native seat) and renders the picker |
| Host | index.js |
Serves three same-origin JSON routes on the harness webServer service |
Host endpoints
GET /model-garden/cost?session=<sessionId>
→ { inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens, reasoningTokens, steps }
GET /model-garden/cost-history?session=<sessionId>&limit=<n>
→ { steps: [ { time, provider, model, turn, step, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens, reasoningTokens } ] (newest first, capped),
models: [ { provider, model, steps, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens } ],
totalSteps }
GET /model-garden/catalog
→ { "provider::model": { local, context?, maxOutput? } } (cached 10 min)
The cost endpoint aggregates the real usage payloads of assistant/message events from the durable session log — no estimation. The cost-history endpoint additionally attributes each usage step to the model in effect: assistant/message events carry usage but not the model, so it tracks request/context (and request/header) events, which precede the request they describe with { provider, model } — a single pass over the same in-memory events, no extra persistence. The catalog endpoint resolves contextWindow / defaultMaxTokens per model through the host llm service (resolveModelInfo), so local/self-hosted providers report their real limits.
Installation
One command — the official plugin CLI installs the package and mounts it (the package carries a dsh.bundle.patch layer, so the CLI automatically appends it to the profile's bundle stack):
dsh plugin --profile <profile> add dsh-model-garden
Then restart the DSH server and hard-refresh the browser (Cmd/Ctrl+Shift+R).
The host half needs the web stack (
webServerservice). In minimal/TUI profiles without it the plugin stays inert by design — boot is never blocked.
Upgrading from a manual install? Remove the old
model-gardendependency and any manual- insert:row for it from your profile'scordis.patch.ymlfirst — otherwise the plugin mounts twice.
Verify
curl -s http://127.0.0.1:3080/model-garden/catalog | head -c 200
# → {"deepseek::deepseek-chat":{"local":false,"context":...}, ...} (JSON, not HTML)
Manual install (without the CLI)
If you manage the profile with plain npm: add the dependency, list dsh-model-garden in dsh.profile.bundles in the profile package.json, reinstall, restart. The bundle patch inside the package inserts the loader row for you — no cordis.patch.yml edit needed.
Configuration
No configuration is required. Two behaviors can be adjusted at the top of the respective file:
- Hidden provider routes —
HIDDEN_PROVIDER_PREFIXESinclient.js(andSKIP_PREFIXESinindex.js). Some plugins mirror providers as internal routes (e.g. a vision toolkit duplicating every provider asvision-toolkit-<id>); such prefixes are excluded from the picker and the catalog. - Price aliases —
PROVIDER_ALIASES/MODEL_ALIASESinclient.jsmap DSH route ids to models.dev catalog ids. They serve two cases: renamed routes (deepseek-official→deepseek) and subscription routes whose catalog entry is all-zero (kimi-for-coding→moonshotai,alibaba-tp→alibaba-cn,oneprovider→anthropic), giving plan models their pay-as-you-go reference price. - Price cache TTL —
PRICE_TTL(default 24 h) and catalog TTL —CATALOG_TTL(default 10 min).
Favorites, collapsed providers and the price cache live in the browser's localStorage under dsh.modelgarden.*.
Compatibility
Developed and tested against DeepSeek Harness 0.1.0-rc.8 (@deepseek-ai/dsh-host-webserver, dsh-session, dsh-llm, dsh-client-ui-model-selection); first released against 0.1.0-rc.6. The client half is plain React via window.__ModuleLoader__ — no build step, no dependencies.
Credits
- Pricing data: models.dev API (also used by OpenCode)
- Design tokens & slot API: DeepSeek Harness


nexu-io/open-design
ruvnet/ruflo
esengine/DeepSeek-Reasonix
volcengine/OpenViking
Tencent/WeKnora
anywhere-labs/deepseek-harness-desktop
freestylefly/awesome-gpt-image-2