dsh-model-hub
DeepSeek Harness plugin: provider sign-in, model catalog, and selection routing over a loopback-only /model-hub channel
- Stars
- 1
- Language
- TypeScript
- Created
- Aug 25, 2026
- Updated
- Aug 25, 2026
Introduction
@fhxgs/dsh-model-hub
Unified provider authentication, model catalog, and selection routing for DeepSeek Harness.
@fhxgs/dsh-model-hub delivers a single, full-featured model management layer for DeepSeek Harness (DSH). It packages both a Node.js Host plugin and a lazy-loaded browser Client, serving all operations over a secure, loopback-only /model-hub RPC channel.
Installing this plugin replaces the default fragmented model settings with a unified experience: one settings section, one composer picker, and one /model command.
Key Features
| Feature | Description |
|---|---|
| Provider Sign-in | Complete OAuth / device-code authentication flow directly in the browser with real-time attempt tracking, prompt dialogs, and a 30-minute host timeout. Credentials pass straight into secure storage and are never exposed in logs or state snapshots. |
| Provider Lifecycle | Clean management actions (activate, deactivate, logout, useRecord) guarded by impact confirmation dialogs. No generic settings overrides. |
| Provider Customization | Edit API keys (stored safely via credentials.set), base URLs, protocols, display names, and per-route model mappings. Includes endpoint discovery and custom provider creation. |
| Rich Model Catalog | Extends the native llm.models schema to retain inputModalities, contextWindow, and defaultMaxTokens. Features revision-keyed caching, an 8-request concurrency gate, and per-model error isolation. |
| Curation Policy | Flexible visibility rules (all or explicit include allowlists) applied synchronously across both settings and the composer picker. |
| Session Selection & Routing | In-memory session model selection with { prepend: true } hook priority. Subagents follow a 3-tier routing strategy evaluated at agent/created. Blocks unroutable message sends upfront. |
| Thinking Effort Control | Dynamic slider automatically calibrated to each model's supported reasoning levels (e.g., xhigh/max for gpt-5.6-sol, hidden for non-reasoning models). |
| Fast Mode | Metadata-driven toggle for models declaring accelerated service tiers (e.g., gpt-5.6-sol priority tier). |
| Built-in Providers | Out-of-the-box support for qwen-code (RFC 8628 device-code login via chat.qwen.ai) and codex (OpenAI Codex: authorization code + PKCE loopback login with 7 GPT-5.x models). |
| Bilingual Interface | Native Simplified Chinese and English UI following the harness shell's language preferences. |
| Loopback Security | Every /model-hub endpoint is bound strictly to authority: 'loopback' with strict Zod payload validation and sanitized error responses. |
Installation
[!NOTE]
dsh pluginruns pnpm under the hood (spawnSync('pnpm')), so pnpm must be available in yourPATH. If needed, enable it via corepack:corepack enable pnpm
Add the plugin to your target profile:
dsh plugin --profile web add @fhxgs/dsh-model-hub
Restart the profile after installation (profile composition changes do not hot-reload).
The plugin automatically registers its patch configuration (cordis.patch.yml), enabling @deepseek-ai/dsh-authorization and disabling the default ui-settings-models and ui-model-selection components. No manual configuration editing is required.
To uninstall:
dsh plugin --profile web remove @fhxgs/dsh-model-hub
Uninstalling cleanly restores the official default model settings and picker.
Quick Start
- Open the DSH Web UI on the same machine running DSH (all endpoints require loopback access).
- Go to Settings → Model Hub → Providers. Select your provider and complete the sign-in flow.
- Click Activate on the provider card to enable the route.
- Switch to the Catalog tab to select which models you want visible in your picker.
- In any chat session, pick your model and reasoning effort from the composer bubble or type
/model.
Configuration
The plugin manages its configuration under the model-hub settings namespace:
model-hub:
picker:
mode: include # 'all' | 'include' (default: all models visible)
include: # Active when mode is 'include'
- { provider: kimi-coding, model: k3 }
preferredEffort: high # Optional default reasoning effort level
subagent: inherit # 'inherit' | { provider, model, reasoningEffort? }
- Default behavior: An empty configuration resolves to
{ picker: { include: [] }, subagent: 'inherit' }. - Global default model: Stored in the native
agent-default-modelnamespace. The plugin reads this value but only modifies it when explicitly confirmed by the user. - Built-in provider configs: Stored separately in
model-hub-providersto prevent catalog cache invalidation during policy updates.
Architecture Overview
Both Host and Client components reside in a single npm package:
- Host (Node.js ESM): Manages the
/model-hubRPC channel, settings schemas, built-in provider adapters, and session selection hooks. - Client (Lazy CJS): Loads on-demand in the browser, providing the settings UI, composer picker, and
/modelmodal.
src/
├── index.ts # Host entrypoint: RPC channel, settings namespace, lifecycle setup
├── rpc/ # Single-layer wire envelope, router, and 7 standard error codes
├── auth/ # Authorization attempt bridge and two-axis auth.state projection
├── provider/ # Adapter bindings and lifecycle operations (activate/deactivate/logout/useRecord)
├── provider/native/ # Self-served providers (OAuth flows for qwen-code and codex)
├── catalog/ # Super-set model catalog, curation policy filter, and LRU cache
├── selection/ # Session model selection, effort resolver, and subagent routing rules
├── settings/ # Settings schema definitions
└── client/ # Browser UI components (Settings cards, Composer picker, Attempt modal)
Build outputs are published to lib/index.js, lib/invariant.js, lib/client.js, lib/types/**, and cordis.patch.yml.
Development & Testing
corepack pnpm install
corepack pnpm run build # Generates lib/types (tsc) and runtime bundles (tsdown)
corepack pnpm run verify # Runs bundle purity, patch keys, and sourcemap checks
corepack pnpm run test # Runs vitest test suite
corepack pnpm run smoke:p0 # Cold-installs tarball into an isolated test profile
prepackautomatically runsverifybeforenpm packornpm publishto prevent broken or dirty artifacts.- Packaging smoke test (
smoke:p0) uses an isolated temporary directory (DSH_HOME=$(mktemp -d)) and never touches your local~/.dsh. - Test requirements and validation gates are documented in
scripts/gate-p1.mdandscripts/gate-p3.md. - Release procedures are defined in
scripts/release-checklist.md.
Compatibility
| Requirement | Supported Range |
|---|---|
| Node.js | ^22.19 || >=24 |
| DeepSeek Harness | 0.1.1-rc.2 |
@deepseek-ai/* peer dependencies | ^0.1.1-rc.2 |
@deepseek-ai/cordis | ^4.0.1 |
@earendil-works/pi-ai | ~0.82.1 (peer dependency supplied by host runtime) |
| React | ^18.2.0 (peer dependency) |
Known Limitations
- Loopback Only: All
/model-hubendpoints return HTTP 403 when accessed outside loopback. Non-loopback pages display a read-only badge; model changes must be performed on the host machine. - Native UI Disabled: The official models settings and onboarding steps are disabled while this plugin is active.
- No Background Push Stream: UI updates are driven by forwarded host events and polling during active login attempts.
- Zero-Message Session Selections: Model selections on sessions with zero sent messages do not persist across restarts (matching official DSH behavior).
- Send Blocking Scope: Composer send-blocking is enforced on web UI interactions; headless or SDK clients are validated on the host directly.
- Codex Token Cost: OpenAI Codex token costs report as zero because plan-based subscription pricing differs from standard API token rates.
License
MIT © 2026 FHGS