DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Ofm Model Manager — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
O

dsh-ofm-model-manager

Ofm Model Manager

Per-model enable/disable and renaming for every provider in DeepSeek Harness — disabled models disappear from the model picker, custom names replace the built-in ones. · DSH 全体模型管理:逐模型启用/停用与自定义显示名,支持按提供商分组、搜索、筛选与批量操作,改完立即生效(不用刷新页面、不用重启 DSH)。

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:DeepseekDays/dsh-ofm-model-manager#1786769ba8f47250c08c812670b98c771396e716
READMECompatibilityVersions
Model manager panel at the bottom of Settings → Models

Compatibility and provenance

Ofm Model Manager is published as dsh-ofm-model-manager and currently resolves to version 2.0.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
10/6/2026

Versions

2.0.0stable
10/6/2026

Related plugins

Loading related plugins…

Latest
2.0.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
10/7/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in models-usage.

Whale Widgetdsh-whale-widgetDeepSeek balance whale widget in the bottom-right corner of the DSH Web interface: balance/today’s usage/peak-off-peak pricing, customizable bubble click sequence (text/balance/today/peak-off-peak/image/random phrases and parallel weighted selection), per-line styles and fonts, floating quick editinUsage@linxin666/dsh-usageUsage statistics plugin for the dsh web GUI: per-provider balance and coding-plan quota detection plus a live token usage ledger, with a compact price glance card above the sidebar's Settings rowClient Ui Model Capabilities@linxin666/dsh-client-ui-model-capabilitiesPer-model capability declarations (image input and reasoning efforts) for custom pi-ai providers, edited in place on the Models settings cards; writes the official llm-pi-ai settings namespace, no DSH source changes.Codex Subscriptiondsh-codex-subscriptionUse ChatGPT and Codex subscriptions in DeepSeek Harness with OAuth, quota, safe resets, web search, images, and Fast mode

README

dsh-ofm-model-manager

English | 中文

Per-model enable/disable and renaming for every provider in DeepSeek Harness. Adds a panel at the bottom of Settings → Models that toggles each model of each provider and gives it a custom display name.

  • Disable a model → it disappears from the composer's model picker and the /model dialog. A provider whose models are all disabled disappears from the picker as a group.
  • Give it a custom name → the picker shows your name instead of the built-in one. The model id is untouched.
  • Preferences live in the profile and apply immediately — no page reload, no DSH restart.

Model manager panel at the bottom of Settings → Models The panel at the bottom of Settings → Models: search box, status chips and provider filter on top, per-provider groups with per-model switches and custom names below.

A row with a custom name enabled A row with "custom name" enabled — switch, checkbox, name field and "restore default".


Install

One line from GitHub:

sh dsh plugin --profile desktop add github:DeepseekDays/dsh-ofm-model-manager

(use your own profile name instead of desktop if different). Then fully quit DSH, tray included, and start it again — new bundles are read at startup.

From a checkout, node install.mjs does the same with a directory junction and without running pnpm (running pnpm while DSH is live rebuilds node_modules and can interrupt a running session):

powershell node install.mjs # default: desktop profile node install.mjs --profile web # another profile node install.mjs --dry # show what would change node install.mjs --uninstall # remove junction + both manifest entries, keep the folder

It backs up <profile>/package.json before touching it.

What the panel gives you

ControlScope
Search boxexact match on name, custom name, model id, description, provider name
Status chipsAll / Enabled / Region-restricted / Disabled, each with a count
Provider dropdownone route at a time, with its model count

The three are ANDed. Rows are grouped by provider, and each group header shows name · enabled/total plus a group-level switch ("enable all" when everything is off, otherwise "disable all"). Groups collapse; collapsing is render-only and does not change filtering or counts.

Batch buttons act on the current view (the filtered result) and say so in small print underneath — there is deliberately no silent "select the whole catalog".

Each row is effective name + status badge / model id / description, followed by switch → "custom name" checkbox → name field (disabled until the checkbox is on, showing the built-in name). A custom tag marks rows that use a custom name; a wildcard tag marks names that apply to every provider (see below).

Long lists render 40 rows at a time with a "show more (N left)" button, and the budget resets whenever the filter changes — no virtual-scrolling library, this is a hand-written ModuleLoader bundle.

Empty and error states are explicit: nothing listed at all, everything disabled (with a one-click "enable all"), no search results (echoing the keyword), plus a read failure state with a retry and a write failure state that rolls back.

Requirements and compatibility

  • A DSH that provides the settings.models.footer slot and @deepseek-ai/dsh-client-ui-primitives@ (tested against ``deepseek-ai/dsh` 0.2.0-rc.2).
  • Declares dsh.bundle in package.json, so it installs with plain dsh plugin add.
  • No kernel files are modified. The plugin wraps ctx.llm.listModels() at runtime and restores it on unload (reference-counted).
  • Coexists with dsh-provider-toggle (provider-level switching). Both wrap the same own property on the llm instance; providers-level unloading deletes it, so this plugin re-installs its wrapper on the next config read whenever the own property has disappeared entirely — and deliberately does not stack a second wrapper when someone else merely wrapped it again.
  • Unaffected by plugins that inject models deeper down (e.g. pi-ai getModels): filtering happens at the listModels exit, so injected models are managed and displayed like any other.
  • Runtime dependencies: none.

Preference keys

provider|modelId only that model on that route modelId no separator = every provider (wildcard)

Why this shape: model ids repeat across providers (deepseek-v4.1-flash exists under several), so a bare-id key silently disabled all of them — v2 keys carry the provider. Bare ids from v1 config read as wildcards, so v1 configuration keeps working with zero migration. One field with one element type keeps the schema trivial, and the pipe is a plain character that YAML does not need to quote, so keys stay readable inside cordis.patch.yml.

Exact key beats wildcard key, so "rename for everyone" and "rename this one specifically" can coexist. The panel only ever writes exact keys; wildcards come from v1 config or a hand-edited file, and are shown as a wildcard tag in the UI.

Development

sh node test/all.mjs

Four offline suites — no DSH, no network, no browser:

FileCovers
test/manager.test.mjspure logic: key format, wildcard/exact precedence, route claim, catalog merge, three states, search, TTL cache
test/host.test.mjsapply() against a fake ctx: does a disabled model really leave the catalog, is the panel's read-only endpoint still served, broadcast, trust gate, shared patch slot with provider-toggle
test/client.test.mjsloads client.js through the ModuleLoader protocol and really renders the panel with a minimal React stand-in: grouping, counts, collapsing, empty states, batch scope, partial rendering, write shape and rollback
test/manifest.test.mjsmanifest consistency: package name, bundle, slot, field names, separator, self-containment

The suites re-implement the expected behaviour (they replicate DSH's groups.filter(group => group.models.length > 0) rather than calling the code under test) so they cannot pass by agreeing with themselves.

Troubleshooting

SymptomCause / fix
Panel does not appearthe bundle was not loaded — check dsh.profile.bundles in the profile package.json, then fully quit DSH (tray included) and start again
"cannot read this plugin's settings namespace"same as above; also check that the entry id in cordis.patch.yml matches the injected namespace
The switch seems to do nothingthe wrapper was removed when another plugin unloaded. It is re-installed on the next config read; restart DSH if it persists
No name fieldthe host half is still v1 (no names field in the namespace) — fully restart DSH
Picker did not change after renamingwait for the 500 ms write debounce, then look for a failed settings.mutate in the console
Panel flickers while typingfixed (see limit 8). A browser-half hot reload is enough; if it persists, look for this plugin's listener failed or settings/conflict
Start from scratchdelete the config of the id: dsh-ofm-model-manager entry in the profile's cordis.patch.yml

Known limits

  1. Disabling affects the catalog, not routing. A session already using the model keeps working; new sessions simply cannot pick it. That is the kernel's behaviour and this plugin does not change it.
  2. Renaming only changes the display name, never the model id — config, session logs and credential references keep the original id.
  3. Provider-level switching is not taken over: that is dsh-provider-toggle's job. Both can be installed and active at once.
  4. Settings are written as one whole volatile form, so preferences are last-writer-wins; two tabs editing at once get a settings/conflict (the panel reports it and rolls back rather than dropping data silently).
  5. Wildcard keys are a global broadcast — tagged in the UI so "I changed one model, why did everything change" cannot happen unnoticed.
  6. Partial rendering instead of virtual scrolling: more than 40 rows need "show more"; filtering is the intended tool for long catalogs.
  7. The read-only endpoint lives under /api/ofm-model-manager (longer prefix than the kernel's /api, and the web server prefers the longest prefix, so it runs ahead of connection's own admission check) — hence its own equivalent trust gate (loopback host, cross-site fetch refused, same-origin Origin/Referer), preferring the connection service's admission check when the composition provides it.
  8. Renaming does not lock or repaint the panel: name writes use a separate path that never sets busy (otherwise every row's checkbox would grey out and back while you type), and only fields the UI actually renders trigger a repaint (RENDER_KEYS in client.js). Accounting-only fields are excluded — add new fields to RENDER_KEYS or their updates will silently not repaint (there is a case pinning this).
  9. On hot-reload the pending debounced write is flushed before the old instance hands over (clearTimeout then an immediate flushNames()), so what you typed in the last 500 ms survives an HMR swap instead of being written from stale state.

The Chinese README (README.zh.md) documents the implementation in more depth: how the catalog is filtered, why disabling the last model of a route removes the whole group, the read-only endpoint's trust gate, the optimistic-update and rollback path, and the transition state between a hot-reloaded browser half and a not-yet-restarted host half.

Files

index.js host half: catalog filtering + read-only endpoint + state client.js browser half: the Settings panel src/manager.js pure logic: key format, catalog merge, cache, search src/trust.js trust gate for the read-only endpoint cordis.patch.yml bundle declaration install.mjs install / uninstall / dry run test/ offline suites assets/ screenshots used by this README

License

MIT — see LICENSE.