Dedicated model routes, tools, and system guidance for vision, compaction, reviews, subagents, titles, and image generation.
Install
# from npm (prebuilt)
dsh plugin --profile web add @dsh-plugin/dsh-auxiliary
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:dsh-plugins/dsh-auxiliary
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README

dsh-auxiliary
Auxiliary models for DeepSeek Harness — dedicated model routes, tools, and system guidance for vision, compaction, reviews, titles, and image generation, without touching the main conversation model.
English | 简体中文
dsh-auxiliary is a DeepSeek Harness plugin that layers auxiliary-model capabilities on the harness LLM seam (ctx.llm). It never replaces the main conversation model: each feature is an independent, optional route that kicks in only for its own narrow call category, so you can give expensive or specialized work (vision, compaction summaries, approval reviews, session titles, image generation) its own cheap or capable model.
Feature overview
| Feature | What it does | Where to configure |
|---|---|---|
| Vision understanding | inspect_image tool: read a local image and ask a vision model about it |
Plugin configuration → Vision understanding |
| Image handoff | Chat images survive a text-only main model via describe_image |
Vision understanding card → Image handoff |
| Context compaction | Summaries (purpose: 'compaction') use a dedicated model |
Plugin configuration → Context compaction |
| Compression engine (optional) | Replaces the compaction backend with an explicit compression prompt | engine.enabled in the config |
| Approval model | Reviews from @dsh-plugin/dsh-approve-for-me use a dedicated model | Plugin configuration → Approval model |
| Title model | Session titles (purpose: 'session-title') use a dedicated model |
Plugin configuration → Title model |
| Image-generation model | generate_image tool: create images through an OpenAI-compatible images API |
Plugin configuration → Image-generation model |
| Model capability marks | Checkboxes on your own llm-pi-ai models: version-gated Allow image input / Allow image generation |
Models page → provider → customized settings → model |
All routes are configured in the loader-managed plugin configuration (rendered by loader) and take effect immediately on save — no restart, no rebuild of the conversation.
Installation
Copy the block below and paste it to your DSH agent (the assistant in this web GUI). The agent performs the install and verification for you — no manual npm or profile editing needed:
Install the @dsh-plugin/dsh-auxiliary plugin into the profile I specify (or ask me if I didn't name one). The npm package name is `@dsh-plugin/dsh-auxiliary`; use the GitHub source `github:dsh-plugins/dsh-auxiliary`, or `file:<path>` for local development.
Steps:
1. Add the plugin dependency: `dsh plugin --profile <PROFILE> add @dsh-plugin/dsh-auxiliary` (or the equivalent plugin-manager command for my profile). Since 0.4.1 the package is a bundle plugin (declares `dsh.bundle.patch`), so `dsh plugin add` also appends it to `dsh.profile.bundles` automatically — no manual `cordis.patch.yml` insert needed.
2. The package declares a `prepack` build script. If pnpm fails with `ERR_PNPM_IGNORED_BUILDS`, approve the build in the profile's `pnpm-workspace.yaml` (`allowBuilds`) and retry the add.
3. If this profile previously loaded the plugin through a manual insert row in `cordis.patch.yml` (pre-0.4.1 style), REMOVE that row — the bundle layer now mounts the plugin, and keeping both would mount it twice.
4. Verify `node_modules/@dsh-plugin/dsh-auxiliary` holds a built `lib/` directory (at least `lib/index.js` and `lib/client.js`). If the build artifacts are missing, run `npm run build` in the plugin directory and re-add.
5. Do not start the profile — install and verify only, then report what you changed.
Then open the loader-managed plugin configuration in the web UI to configure the routes, and mark the models you want to use in Settings → Models.
Features in detail
Vision understanding and inspect_image
Configure a provider/model in the Models page first, then pick the pair under Vision understanding (saved as vision.provider + vision.model). tool.enabled independently controls whether the inspect_image tool is registered.
vision:
provider: anvilcraft-ai # any registered provider route
model: mimo-v2.5 # a vision-capable model on that provider
tool:
enabled: true # register the inspect_image tool
maxImageBytes: 10485760 # per-file size cap
timeoutMs: 120000 # cooperative tool-call budget
Once enabled, ask the agent to run inspect_image on a Host-readable path:
Use inspect_image to analyze screenshots/error.png
The tool commits the file through the ctx.attachments seam and asks the selected vision model, returning a text answer (optionally truncated at vision.maxTokens). PNG, JPEG, WebP, and GIF are supported.
Model capability mark: for a user-configured llm-pi-ai model, the Allow image input checkbox in the model's settings writes its canonical input declaration ([text, image] when checked, [text] when cleared). Both inspect_image and the main chat composer read that same capability fact. The declaration cannot add vision to a text-only model — only check it when the upstream endpoint actually accepts images.
Image handoff (chat images with a text-only main model)
When Image handoff (vision.handoff, default on) is enabled with a vision route selected, image delivery is native-first and falls back safely for routes without declared image support:
- A runtime wrapper on
ctx.llm.resolveModelInfoclaims image input for text-only main routes while handoff is active, so the image admission preflight passes (the model catalog and per-model checkboxes are unaffected because they read the settings document directly). The configured auxiliary vision route is never inflated, soinspect_image/describe_imagestill reject a mistakenly selected text-only vision model. - For each request containing images, a listener on the official
llm/streamwaterfall checks the exact request's provider/model through the original capability resolver. Image-capable routes receive the originalImageBlocks unchanged. Text-only routes and routes with undeclared modalities receive durable text references such as[image: {"attachmentId":…,"mediaType":…}]; nested images in tool results are rewritten too. - The system prompt tells a text-only main model to call
describe_imagewith the exact JSON from the reference; the tool reads the stored attachment bytes, asks the selected vision model, and returns a text description.
The rewrite is immutable and request-local, so concurrent native and fallback streams cannot affect one another; aborts, errors, early iterator closure, and plugin disposal retain the host stream semantics. References are plain text and therefore survive restarts, forks, and replays. Both seams are plugin-side; no core package is modified. Disable vision.handoff to restore the original admission and stream behavior.
Skipping injection for vision-capable main models
When Skip when the main model supports images (vision.skipWhenMainModelSupportsImage, default off) is enabled, a session whose main model declares image input gets no inspect_image/describe_image tool schemas and no vision prompt section — the model reads attached images natively. This existing option uses the public generic prompt-assembly context and the host's original resolveModelInfo (captured before the handoff wrapper); the tools stay registered, so an in-flight or replayed call still executes.
This is intentionally separate from image handoff's exact llm/stream route check. Exact per-attempt Auto / Always / Disabled tool and prompt visibility would require Harness core to publish the prepared request route/capabilities to prompt assembly together with a request-lifetime tool restriction contract. That contract is not part of the released public API, so this plugin-only change does not add a dead setting or depend on private agent-loop types.
The released llm/stream contract also describes agent-loop request content as read-only. This release therefore keeps the plugin's pre-existing compatibility shim but makes it capability-aware and concurrency-safe; a fully first-class handoff should follow with a core-owned, session-logged image-reference projection/admission hook so plugins do not have to redispatch rewritten loop requests.
Context compaction
Every summarization call carries the official GenerateOptions.purpose: 'compaction'. The plugin installs an llm/stream waterfall listener that reroutes those calls to the configured pair:
compact:
enabled: true
provider: deepseek-official # e.g. a cheap, fast summarizer
model: deepseek-chat
The listener is always installed and is a pure pass-through until a complete route is configured. Only purpose: 'compaction' calls are rerouted; the main session and every other call category are untouched.
Compression engine (optional): engine.enabled: true replaces the stock compaction backend with a BasicCompactionEngine subclass that drives summarization with an explicit context-compression instruction (see engine.compressPrompt). It reuses the compact route and adds no third model route. It is mutually exclusive with @deepseek-ai/dsh-compaction-basic — the plugin detects the conflict and skips the engine with a warning.
Compaction threshold: set engine.enabled and engine.thresholdRatio in the unified form, so compaction fires automatically once context usage reaches that percentage; the threshold must stay above the retention ratio (engine.retainRatio, 16% by default). The engine refreshes the policy before every pressure check, so no restart is needed after saving.
Automatic review model
Before 0.1.7-rc.2, approve routes approve-for-me review calls. From that release, it routes official @deepseek-ai/dsh-experimental-auto-review calls. Only provider/model are replaced; official policy, inputs, Session attribution, cancellation and decisions remain native. Enable the official plugin and choose its Auto permission mode separately.
approve:
enabled: true
provider: my-provider
model: my-review-model
思考过程机器翻译模型
从 0.2.1-rc.1 起,统一表单增加「思考过程机器翻译」分组:
translation:
enabled: true
# 已配置的提供商 ID
provider: foo
# 该提供商的模型 ID
model: example
启用 @deepseek-ai/dsh-experimental-cot-translation-bundle 后,在翻译菜单选择「DeepSeek Flash · 官方 API」,再通过辅助模型配置选择实际调用的提供商与模型。选择器显示宿主已配置的全部提供商;Bing、Google、DeepSeek 账号的独立翻译入口继续使用原实现。
官方 API 模型沿用原生凭据与模型资格检查,并关闭思考。第三方模型通过宿主 LLM 接口调用,由对应提供商检查凭据并使用其默认推理设置;翻译结果只保留最终文本。请求沿用原生输入限制、超时、取消、输出大小限制和会话持久化,接口调用按所选模型计费。
旧配置省略 provider 时继续使用 deepseek-official。清除选择或关闭替换时恢复官方默认 Flash。缓存按提供商与模型隔离,同名模型不会混用结果;调用记录包含实际提供商与模型。辅助模型或翻译服务卸载后会取消进行中的覆盖请求。
子智能体模型
从 0.1.2-alpha.2 起,DSH 内置子智能体模型授权。请在「内置插件配置 → 子智能体」中启用「允许 Agent 为子智能体选择模型」,选择允许使用的模型并保存。
auxiliary 在该版本及以后不再提供「子智能体模型」设置,也不再覆盖子智能体的模型路由。已有配置中的 subagent 值会被忽略,避免覆盖内置授权下的模型选择。当前 loader 支持的 DSH 版本均在此范围内。
Title model
title:
enabled: true
provider: anvilcraft-ai
model: deepseek-chat
Session titles are issued by the dsh-session-title-llm provider, which has its own deployment-level provider/model config. With this feature enabled, every purpose: 'session-title' call is rerouted to the selected pair, leaving the provider's own config and the main session route untouched. Recognition uses the official GenerateOptions.purpose marker, so it cannot collide with agent-loop, compaction, or approval calls. Like the compaction router, the listener is always installed and passes through until a complete route is configured.
Image-generation model and generate_image
imagegen:
enabled: true
provider: lanqin-gpt # an OpenAI-compatible provider route
model: gpt-image-2
The harness LLM seam only speaks text, so image generation talks to the provider's OpenAI-compatible images API directly. With this feature enabled and a complete route:
- The
generate_imagetool is registered and a system-prompt section tells the main model to call it when the user asks to generate, draw, or create a picture. - The tool reads the provider's
baseURLfrom the resolvedllm-pi-aisettings and resolvesapiKeyEnvthrough the harness credential seam (ctx.credentials.resolve). It callsPOST {baseURL}/images/generationsfor text-to-image orPOST {baseURL}/images/editswhen a reference image is provided. Both requests includeresponse_format: "b64_json". - The tool prefers
data[].b64_json. For results with only a URL, it resolves relative paths against the image API response URL and downloads the image. It saves images under.dsh/generated/in the working directory and returns their paths. The main model can verify the images withinspect_image.
Model capability mark: use a model that supports image generation; the optional Allow image generation checkbox in model settings writes imageGeneration: true into the raw user section of the llm-pi-ai namespace. Mark exactly the models whose upstream endpoint actually generates images.
How it works
The plugin consumes dsh-loader 2.x facades. Config-api owns the form and persistence; model editor enhancements follow the host version in the loader boot description. Feature registrations are reconciled against each updated configuration snapshot.
1. Purpose-keyed model routing
All text routing shares one pattern: install an llm/stream waterfall listener once (always active), inspect the call, and either pass it through untouched or re-enter the seam with a frozen replacement config:
- Recognition uses stable, official markers —
GenerateOptions.purpose('compaction'/'session-title') or the approval call's public contract — so each router can only ever match its own call category. - Rerouting calls
deepFreeze({...options, provider, model})and re-entersctx.llm.stream(); theprovider/modelreplacement is the only change, so timeouts, retries, and fallback stay harness-owned. - Loop protection: the replacement carries the same route marker; an equality check on the config prevents the router from matching its own re-entry.
- Laziness: the listener is a pure pass-through until a complete route exists — enabling the feature later needs no reinstall, and disabling it needs no cleanup beyond removing the listener.
2. Tools and system guidance
Tools are registered with ctx.tools.register(defineTool(...)) and announced to the model through ctx.systemPrompt.section(...):
inspect_image— vision understanding: file path + optional question → attachment seam → vision route → text answer.describe_image— handoff: reads the JSON from a chat[image: …]reference and answers via the vision route.generate_image— image generation: prompt (+size/n) → provider images API (credential seam) → PNG files under.dsh/generated/→ paths.
Each tool is registered only while its feature is enabled with a complete route (reconcile pattern), so the model never sees a tool it cannot use.
3. Configuration and the model catalog
Plugin preferences use config-api independently of host settings and exposeAllNamespaces. Model enhancements edit the official llm-pi-ai data through the loader-normalized connection API. Once the official editors take over, the plugin removes those controls and stops inherited/deferred writes for their fields. Image generation declarations remain available.
4. Credentials, not plain env
apiKeyEnv values are credential-refs, so the image-generation tool resolves the key through ctx.credentials.resolve(credentialRef(...)) — the harness credential seam covers env/file/user-env layers and re-resolves per call (a changed key reaches the next call without a restart). Never process.env.
5. Everything reconfigures live
Each feature is owned by a reconcile*() + disposer pair: on every settings change the plugin re-resolves the config and registers or disposes exactly the pieces whose conditions changed. Saving a route in the web UI takes effect immediately.
Configuration
The Cordis row below can seed initial defaults. Subsequent changes use config-api; an existing config file takes precedence.
- name: '@dsh-plugin/dsh-auxiliary'
config:
vision:
maxTokens: 2048 # inspect_image output cap (provider/model written by the settings page)
handoff: true # text-only main models may reference chat images via describe_image
skipWhenMainModelSupportsImage: false # image-capable main models get no vision tools/prompt injected
tool:
enabled: true # register the inspect_image tool
maxImageBytes: 10485760 # per-file size cap
timeoutMs: 120000 # cooperative tool-call budget
compact:
enabled: false # reroute compaction summaries to an auxiliary model
provider: "" # e.g. deepseek-official (a registered provider route id)
model: "" # e.g. deepseek-chat (a model id on that provider)
approve:
enabled: false # give @dsh-plugin/dsh-approve-for-me's reviews a dedicated model
provider: "" # e.g. deepseek-official (a registered provider route id)
model: "" # e.g. deepseek-chat (a model id on that provider)
title:
enabled: false # route session-title calls to a dedicated model
provider: "" # e.g. deepseek-official
model: "" # e.g. deepseek-chat
imagegen:
enabled: false # register generate_image with a dedicated image model
provider: "" # e.g. lanqin-gpt (an OpenAI-compatible provider route)
model: "" # e.g. gpt-image-2 (marked Allow image generation)
engine:
enabled: false # optional compression engine (mutually exclusive with dsh-compaction-basic)
thresholdRatio: 0.8
retainRatio: 0.16
maxTokens: 8192
compactionRetries: 1
maxOverflowRetries: 1
auto: true
compressPrompt: "..." # custom compression instruction
Unified form and 1.x migration
Requires Node.js 24.9+ and dsh-loader 2.x. Supports its six explicit release families: 0.1.5, 0.1.6, 0.1.7, 0.2.0, 0.2.1, 0.2.2, including prereleases. Before 0.1.6-alpha.2, use Settings → Plugin configuration; from that release, use the plugin detail page.
One collapsed plugin card groups vision, compaction, approval, title, image generation and compression engine settings. Enter provider/model route IDs already configured in the official Models page. Saved changes apply to subsequent requests; hidden fields keep their values.
Preferences live at <profile>/config/dsh-auxiliary/config.json. The old 1.x dsh-auxiliary settings namespace is not automatically imported: copy values manually. Cordis row configuration seeds defaults on first registration; an existing file takes precedence. Manual edits require a plugin reload or restart.
Set provider/model pairs together and keep engine.retainRatio below engine.thresholdRatio. Config-api checks field ranges; runtime cross-field validation reports errors and keeps the last valid running configuration.
Model editor version boundaries
| dsh version | Plugin input editor | Plugin reasoning editor | Image generation flag |
|---|---|---|---|
< 0.1.7-rc.1 |
Enabled | Enabled | Enabled |
>= 0.1.7-rc.1, < 0.2.1-rc.1 |
Official UI | Enabled | Enabled |
>= 0.2.1-rc.1 |
Official UI | Official UI | Enabled |
The named releases are included in each cutoff. Legacy controls live in the model capacity disclosure. Changes wait for the official provider save to finish. Renaming only inherits fields still owned by the plugin for that version. Unload stops observation and deferred writes, removes controls and unmounts React roots.
Notes
- Routing features reroute only their own call category (
purpose: 'compaction'/purpose: 'session-title'/ the approval review contract); the main session route is never touched. engine.enabled: truereplaces the stock compaction backend; do not load@deepseek-ai/dsh-compaction-basicat the same time. The plugin detects the conflict and skips the engine with a warning.- Vision tool arguments:
path(absolute or workspace-relative) and optionalquestion. Supported formats: PNG, JPEG, WebP, GIF. generate_imagearguments:prompt(required), optionalsizeandn(most providers accept onlyn: 1).
Development
npm install # installs dependencies (typescript, @deepseek-ai/* peers)
npm run typecheck # tsc --noEmit
npm test # builds and runs the Node regression tests
npm run build # emits lib/
License
Links
More in this category
Tencent/WeKnora#dsh-weknora★ 37401
Four read-only tools over a WeKnora knowledge base: list knowledge bases, hybrid passage search, reassemble one document's chunks in order, and WeKnora's own cited RAG or ReAct-agent answer with a resumable session id.
DayuanJiang/next-ai-draw-io#dsh-plugin★ 36932
Draws draw.io diagrams in DeepSeek Harness through the next-ai-drawio MCP server: the link in the reply opens a live preview in the right sidebar, you can edit the diagram by hand, and each AI change is a version you can restore. Node.js 18+; npx downloads the MCP server on first use.
superdesigndev/treg★ 7929
Tool catalog for agents: search ~2,600 external endpoints (SEO and SERP, backlinks, social, people and company enrichment, ad libraries, scraping) by the task you want done, read each one's parameters and per-call price, then call it with the credential injected server-side. Ships the skill plus an MCP row that stays disabled until TREG_TOKEN is set.
T-Auto/dsh-ops★ 5798
Provides bash, PowerShell 7, and high-performance Rust tools for DSH on Windows to reduce token usage.
sixtysevenlf/dsh-blender-plugin★ 2081
Lets a DSH agent drive a local Blender over a direct TCP channel with 15 tools: viewport frames, custom-angle renders, Python execution, headless and job offload, transaction rollback, and a planning layer of 228 ops across 34 families.
yjl9903/AnimeGarden#dsh★ 1400
Anime Garden for DSH: search anime torrent resources from 動漫花園, 蜜柑计划, 萌番组 and ANi inside DSH — via chat, a sidebar panel with fansub and type filters, a seasonal calendar, and an in-app floating player.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.