Skip to main content

dsh-model-tier/packages/dsh-model-tier

24Stars3Forks1Issues0Watchers

Provides model tier routing for DSH: routes auxiliary requests and subtasks to lightweight models by session, while main dialogues and complex tasks use strong-tier models, effective across providers.

Evidence5/5methodologySourceInstallMaintenanceDSH versionSecurity scan
Machine-auditedInstall commandRepo verifieddsh-plugin topicLicenseREADMEAI wiki

ⓘ This plugin is a sub-package of the biociao/dsh-science monorepo — stars and activity count the whole repository.

Language
JavaScript
License
MIT
Branch
main
dsh-plugindsh-plugins

Install

cmdweb profile
$ dsh plugin --profile web add dsh-model-tier

Run the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial

Install via your agent

Install the DeepSeek Harness plugin biociao/dsh-science/packages/dsh-model-tier for me: review the repository at https://github.com/biociao/dsh-science first, then run the install command and verify the plugin loads successfully.

Paste this instruction to the DSH Web GUI assistant — it will install and verify for you.

One-Sentence Description

A session-level model tier routing plugin for DeepSeek Harness: automatically routes auxiliary requests (title/compaction) and sub-tasks in a session to lightweight models, escalates complex tasks to strong-tier models, main conversation follows the tier scheme, and each tier can point to different providers.

Core Features

  • Register a virtual provider "Smart Tiering" in the session model selector, converting multiple tiering schemes into selectable "models", enabling routing per-session via opt-in; unaffected sessions remain completely untouched
  • Auto-decide tiers by request type: auxiliary requests (session title, compaction) go to light tier, sub-tasks go to light tier, main conversation goes to default tier
  • Escalate to strong tier by rules: optional "recent user message exceeds N characters" / "sub-agent chain depth ≥ N" triggers strong tier, automatically routing long inputs and deep-chain reasoning to stronger models
  • Optional LLM pre-classifier: uses a small model to classify tasks as light/default/strong on top of structural rules, cached by (sessionId, message hash), classifies only once per round, falls back to structural tier on failure/timeout
  • Multi-scheme presets + hot reload: settings page can save multiple tiering schemes, config file hot-reloads by mtime, no profile restart needed
  • Cross-provider routing: three tiers can point to different providers/models respectively; when a tier is unconfigured, falls back in order default → light → strong, then passes through global default model

Technical Implementation

  • Language: JavaScript (ESM, Node built-in modules)
  • Key Dependencies: Zero third-party dependencies; only uses node:fs, node:path, node:os, node:url
  • Architecture Pattern: Registers process-level virtual LLM adapter via ctx.llm.registerAdapter(["model-tier"], ...); subscribes to agent/request event for global default model fallback guard; client injects "settings page section" and "chat page bottom dock" via slots.inject
  • Entry Files: engines/model-tier.mjs (routing engine, exports name = "dsh-model-tier", inject = ["llm"]) + engines/model-tier-ui.mjs (settings page HTTP routes) + client/model-tier-ui/src/index.js (settings page + routing metrics UI)

Use Cases

Users who want to simultaneously use strong models from different providers (e.g., DeepSeek, Zhipu) and cheap/local lightweight models, wanting to automatically route models by request type within the same session to save token costs and latency. Suitable for multi-model collaboration (flagship for default tier, local small models for light tier, reasoning-strong models for strong tier) in development, research, and automation workflow scenarios. Claude Code users migrating to DSH can seamlessly reuse the "small model handles auxiliary requests" tiering approach.

Prerequisites & Compatibility

DependencyMin VersionDescription
Node>= 18Declared in package.json engines.node
DSHNot declaredNo dsh version field in package.json, runs on currently released DSH host
PlatformCross-platformNo platform-specific native modules on server; client declares dsh.client.platform: "web"
Native ModulesNoneOnly depends on Node built-in modules (fs/path/os/url)

Installation

dsh plugin --profile web add dsh-model-tier

Configuration Options

ConfigTypeDescriptionDefault
tiers.strongObjectStrong tier {provider, model, reasoningEffort?}, for complex tasks (deep-chain sub-tasks / super long inputs)Unconfigured → falls back to default tier
tiers.defaultObjectDefault tier, main conversation in selected sessions goes through this tierUnconfigured → falls back to light/strong tier
tiers.lightObjectLight tier, for auxiliary requests (title/compaction) + sub-tasksUnconfigured → falls back to default tier
routing.auxiliaryString Arraypurpose list treated as auxiliary requests, auto go to light tier["session-title", "compaction"]
routing.subagentsString"light" means sub-tasks route to light tier; other values don't route"light"
routing.subagentDepthStrongNumber/nullEscalate to strong tier when sub-agent delegationDepth ≥ Nnull (off)
routing.escalateOnCharsNumber/nullEscalate to strong tier when latest user message text length ≥ N (after stripping harness-injected <system-reminder> segments)null (off)
routing.classifyObject/nullLLM pre-classifier: true/{} enables (defaults to light tier model for classification), or explicitly specify {provider, model, timeoutMs?, maxChars?, maxTokens?}; non-thinking model recommendednull (off)
enabledBooleanMaster switch: when off, "Smart Tiering" no longer appears in model selectortrue

When all three tiers are unconfigured, no tiering scheme appears in the model selector, so sample config can be safely shipped with the package without polluting environments that don't expect the provider.

FAQ

Q: What's the relationship between this plugin and Claude Code's Opus/Sonnet/Haiku strategy?

A: It's the DSH implementation of the same idea: within the same session, automatically route auxiliary requests (title/compaction) and sub-tasks to light tier, main conversation goes to default tier, complex tasks escalate to strong tier by rules, corresponding to Claude Code's smallModel/--model-small and task complexity judgment.

Q: Will all sessions be automatically tiered after installation?

A: No. The plugin only registers a virtual provider "Smart Tiering" in the session model selector. You need to manually select "Smart Tiering / some scheme" in each session to enable routing. Unselected sessions remain completely unaffected (opt-in per session, no global routing).

Q: Where is the config file saved? Do I need to restart after changes?

A: Saved to $DSH_HOME/model-tier.json (default ~/.dsh/model-tier.json). Routing engine caches by file mtime, changes take effect hot, no need to restart profile or reopen session.

Q: Is LLM pre-classifier (routing.classify) required?

A: No. It's an optional enhancement: when enabled, every user question or sub-task dispatch will use a small model to classify the task as light/default/strong, overriding the structural tier. Defaults to light tier model for classification; failure/timeout/garbage response automatically falls back to structural tier (won't block main request).

Q: Can I use a thinking model for the classifier target?

A: Not recommended. Reasoning content from thinking models also consumes maxTokens quota (default 512, adjustable via maxTokens). In testing, thinking has filled the quota and produced empty strings where classification words couldn't be obtained. README explicitly recommends non-thinking models.

Q: What's the relationship with dsh-science?

A: dsh-model-tier is a companion package to dsh-science. Installing dsh-science automatically brings dsh-model-tier as a dependency; but it's completely independent and can be used in any profile alone via dsh plugin add dsh-model-tier.

Difficulty Level

Beginner — configuration only involves three-tier provider/model YAML, after writing yaml you can see "Smart Tiering" group in model selector and enable it in sessions; advanced features (classifier, deep-chain escalation) have clear switches and defaults.

Known Issues & Limitations

  • Selection window race condition (known limitation): Since platform persists "session model selection" as global default model, engine uses agent/request listener for best-effort fallback; however, sessions created in the extremely short window between "selecting scheme" and "next request" will still inherit the tiering scheme (source: README.zh.md:48-49, engines/model-tier.mjs:651-681)
  • Cross-tier thinking compatibility: When history mixes assistant messages from other tiers (non-thinking / no reasoning capture) producing tool calls, and target tier is a thinking model like DeepSeek that requires reasoning_content return, it triggers 400 INVALID_REQUEST. Engine automatically adds placeholder reasoning content to messages missing reasoning blocks and retries transparently once (generates warn log, but only retries once, doesn't replay already produced content; source: engines/model-tier.mjs:344-369)
  • Classifier cache limit 200 items: Classification results cached by (sessionId, message hash), items evicted by insertion order when limit exceeded; occasional duplicate classification in long-session dense scenarios is normal (source: engines/model-tier.mjs:318-323)
  • Light tier model reasoning effort: Explicit reasoningEffort in tier is forwarded as-is; model's reasoning effort in selector is only forwarded when target model declares support, otherwise host hard-fails with UNSUPPORTED_REASONING_EFFORT; light tier models typically don't support reasoning, auxiliary requests like title/compaction will silently fall back (source: engines/model-tier.mjs:622-639)
  • Unconfigured tier schemes don't go live: If a scheme saved in settings page has all three tiers incompletely configured with provider/model, corresponding tiers fall back in TIER_FALLBACK order, and when still no target available, throws error "No available model" (source: engines/model-tier.mjs:294-303, engines/model-tier.mjs:597-606)

Read the usage guide →

Install steps, key points, FAQ and compatibility for this plugin — auto-derived from indexed fields.

Listing badge

Listed on deepseek-plugin.org
[![Listed on deepseek-plugin.org](https://img.shields.io/badge/listed_on-deepseek--plugin.org-007EC6)](https://deepseek-plugin.org/plugins/biociao/dsh-science/packages/dsh-model-tier)

Paste this markdown into your GitHub README to link back to this listing. The badge only states the listing — not a security endorsement.

← Back to plugin directory