dsh-vision-bridge
   
A DSH-native Vision Evidence bridge for text-only reasoning models. When a request contains images, dsh-vision-bridge sends them to an image-capable Vision model on a DSH route you configure, converts the result into validated structured Evidence, and hands that Evidence to your text-only reasoning model as clearly labeled, untrusted observed data.
> Community plugin for DeepSeek Harness (DSH) — > not affiliated with or endorsed by DeepSeek. > > Official distribution: > > - npm: @liangdacheng/dsh-vision-bridge > - GitHub Releases: TwistedRiCen/dsh-vision-bridge — latest stable > v0.2.5 > > Also discoverable under the > DSH Community Plugins GitHub topic > (dsh-plugin).
Table of contents
- [What is dsh-vision-bridge?](#what-is-dsh-vision-bridge)
- [Why use it?](#why-use-it)
- [Key features](#key-features)
- [How it works](#how-it-works)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Install (recommended)](#quick-install-recommended) - [Manual Installation](#manual-installation)
- [Configuration](#configuration)
- [Advanced Installer Options](#advanced-installer-options)
- [Quick Start](#quick-start)
- [Usage examples](#usage-examples)
- [Multi-image behavior](#multi-image-behavior)
- [Evidence and trust boundary](#evidence-and-trust-boundary)
- [Caching behavior](#caching-behavior)
- [Error and retry behavior](#error-and-retry-behavior)
- [Robustness: leading U+200B tolerance](#robustness-leading-u200b-tolerance)
- [Troubleshooting](#troubleshooting)
- [Upgrading](#upgrading)
- [Uninstalling](#uninstalling)
- [Development and testing](#development-and-testing)
- [Security notes](#security-notes)
- [Limitations](#limitations)
- [Contributing](#contributing)
- [License and third-party notices](#license-and-third-party-notices)
What is dsh-vision-bridge?
dsh-vision-bridge is a plugin for the DeepSeek Harness (dsh). It registers a synthetic provider wrapper around an existing text-only reasoning route and makes the wrapped models accept native image attachments.
Under the hood, the bridge never runs a vision model itself. It delegates image understanding to a separate image-capable model on a DSH route you choose (the Vision route). The Vision output is strictly parsed and validated into structured Evidence, which is then rendered into the request as an explicitly untrusted text block for the downstream text-only model.
In other words: your primary model stays text-only, and image understanding is delivered to it as data.
Why use it?
DSH workflows built around a text-only reasoning model (for example a DeepSeek reasoning model) cannot consume image attachments directly. Typical workarounds require switching the whole workflow to a multimodal model or reading images outside DSH.
With dsh-vision-bridge you keep the same downstream model and workflow, and gain:
- Native attachment flow — users paste or attach images the usual DSH way.
- A dedicated Vision model — the image-capable model and provider are your
choice, configured per profile.
- Validated Evidence — Vision output must parse and validate before it ever
reaches the downstream model.
- A clear trust boundary — Evidence is labeled untrusted observed data, so
the downstream model is instructed to treat it as data, not instructions.
- Multi-image support — several images in one request are analyzed in a
single batch while each image keeps its own identity.
Key features
| Capability | Behavior |
|---|---|
| Native image attachment bridging | Image attachments pass through to the Vision route as DSH-native image blocks; the bridge itself never reads raw image bytes. |
| Single-image Evidence | One image occurrence → one Vision call → one validated Evidence object that replaces the image in the request. |
| Multi-image Evidence batching | A run of two or more images becomes one Vision call carrying all images in order, producing one batch Evidence. |
Explicit Image 1..N separation | Every image keeps its own Evidence entry; the batch must contain exactly one entry per image (images.length === N, indexes 1..N). |
| Cross-image relations | Relationships between images are represented in a separate relations list, never by merging attachments. |
| Strict Evidence validation | Vision output is strictly parsed and validated against a local schema before any downstream use. |
| Fail-closed behavior | Invalid, missing, or unverifiable Vision output fails the request; the downstream provider is never invoked without valid Evidence. |
| Bounded multi-image retry | Multi-image output-contract recovery is bounded to at most 2 Vision attempts per work unit. |
| Deterministic multi-image retry policy | Multi-image Vision attempts use temperature: 0. Single-image calls are not forced to a temperature. |
| Session-scoped Evidence cache | Completed, validated Evidence is cached in memory per session to skip repeated Vision calls for the same images. |
| Vision Auto-Discovery | With only upstreamProvider configured, the bridge finds the unique DSH model that positively declares image input and pins it as the Vision target. |
| Zero runtime dependencies | The released package has no runtime dependencies and stores no credentials of its own. |
How it works
flowchart LR
A[User message + N image attachments] --> B[dsh-vision-bridge wrapper]
B -->|1 Vision call, images in order| C[Image-capable Vision route]
C -->|raw JSON observation| B
B -->|strict JSON parse + Evidence validation| D{Valid Evidence?}
D -->|yes| E[Downstream text-only model<br/>untrusted Evidence text + Image n anchors]
D -->|no| F[Request fails closed<br/>downstream is never called]1. Detect. The bridge examines each outgoing message for image blocks (including images nested inside tool results). 2. Analyze. Images are sent to the configured image-capable Vision route via DSH's LLM service. The bridge itself only consumes the llm service — raw attachment bytes are resolved by the Vision provider's own adapter. 3. Validate. The Vision output must be one complete JSON document that passes the local Evidence schema check. 4. Transform. The validated Evidence is rendered as an explicitly untrusted text block (plus positional [Image n] anchors for multi-image batches) and forwarded to the text-only downstream provider. 5. Fail closed. If any step fails, the whole request fails and nothing reaches the downstream provider.
Requirements
- DeepSeek Harness with a working profile and the
dshCLI available
(installed on your PATH, or run on demand through npx @deepseek-ai/dsh …). DSH is a developer preview; this plugin is tested against the DSH checkout at commit 47f943859bef60e4160492346772ded9b24f765a (CLI 0.1.0-rc.5), and the installation/upgrade/uninstall flow documented here was also verified against the currently published CLI 0.1.0-rc.6. Compatibility with other DSH versions is not guaranteed.
- Node.js ≥ 22.19 — the declared engine. The plugin runs inside DSH's own
Node.js process; building from source requires it too.
- pnpm on your
PATH— thedsh plugincommand manages profile plugins
by forwarding to pnpm.
- A text-only reasoning route (the upstream) — the model you want to
wrap must positively declare text input and not declare image input.
- An image-capable Vision route — only needed when you configure
visionProvider/visionModel explicitly. Without explicit configuration the bridge auto-discovers a model that positively declares image input (its credentials still live in DSH's credentials layer; the bridge stores no credentials of its own).
- Platform. Developed and verified on Windows. The plugin itself is
platform-independent JavaScript, but no claims are made about untested operating systems.
Installation
The project is distributed through two official channels:
| Channel | Identity |
|---|---|
| GitHub Release | repository dsh-vision-bridge — release tarball + guided installer |
| npm | official package @liangdacheng/dsh-vision-bridge (public, registry.npmjs.org) |
> Important: The official npm package for this project is > @liangdacheng/dsh-vision-bridge. The unscoped npm package > dsh-vision-bridge is unrelated to this project and is not published or > maintained by this repository. Do not install it as this project.
npm publication starts with v0.2.4; v0.2.3 and earlier were distributed only via GitHub Release and were never published to npm. The current stable release is v0.2.5.
Release facts for v0.2.5:
| Release page | <https://github.com/TwistedRiCen/dsh-vision-bridge/releases/tag/v0.2.5> |
| Artifact | dsh-vision-bridge-0.2.5.tgz |
| SHA-256 | published in the dsh-vision-bridge-0.2.5.tgz.sha256 release asset |
| npm package | @liangdacheng/dsh-vision-bridge@0.2.5 |
For future versions, follow the same steps with the values from the latest release.
Quick Install (recommended)
A guided installer automates download, SHA-256 verification, plugin install, profile configuration (with backup and rollback), and validation. It does not need a global dsh install — the installer drives a pinned, tested DSH CLI (@deepseek-ai/dsh@0.1.0-rc.6). You only need Node.js >= 22.19 and pnpm on your PATH.
Invoke-WebRequest 'https://github.com/TwistedRiCen/dsh-vision-bridge/releases/download/v0.2.5/setup.mjs' -OutFile setup.mjs
node .\setup.mjsThe wizard will:
1. list your DSH profiles (or create a new one); 2. discover your upstream (text-only) provider route — when DSH's settings.yaml exposes exactly one text-only candidate it is selected automatically; with several candidates you pick from a numbered list (or pass --upstream-provider <id>). The installer writes the minimal upstream-only (Vision Auto-Discovery) configuration and never guesses route or model ids; 3. download and verify the v0.2.5 release tarball, install it into the profile, write the bridge configuration (backing up the previous file), and validate the result with dsh --dump-config.
Vision Auto-Discovery runs at the first image request. To pin an explicit Vision route instead, set visionProvider + visionModel together in the profile's cordis.patch.yml (see [Configuration](#configuration)).
No Vision request is made during installation.
To verify the installer file itself before running it (recommended):
Invoke-WebRequest 'https://github.com/TwistedRiCen/dsh-vision-bridge/releases/download/v0.2.5/setup.mjs.sha256' -OutFile setup.mjs.sha256
(Get-FileHash .\setup.mjs -Algorithm SHA256).Hash
Get-Content .\setup.mjs.sha256The two values must match. Always download and inspect first — do not run
irm ... | iex. Installer flags (--what-if, --yes, --tarball,
non-interactive arguments) are documented in [Advanced Installer Options](#advanced-installer-options).
Manual Installation
If you prefer to audit or run every step yourself — or if the installer cannot run in your environment — the manual path below remains fully supported:
#### 1. Prerequisites
Make sure the dsh CLI is available, and know which profile you use. A DSH profile is a directory under $DSH_HOME/profiles/<name> (by default ~/.dsh/profiles/<name>) that holds the profile's plugin list (package.json with a dsh.profile.bundles array) and your own configuration (cordis.patch.yml). Replace <profile> in every command below with that name.
dsh --help
dsh --versionIf dsh is not recognized as a command, you can run the published DSH CLI on demand with npx — no global install needed:
npx @deepseek-ai/dsh --versionThroughout this guide, every dsh … command can be run as npx @deepseek-ai/dsh … (for example npx @deepseek-ai/dsh plugin --profile <profile> add …). The rest of the prerequisites are unchanged: you still need Node.js and pnpm on your PATH.
#### 2. Download the release
Download the artifact from the v0.2.5 release page or with a command:
##### Windows PowerShell
Invoke-WebRequest -Uri 'https://github.com/TwistedRiCen/dsh-vision-bridge/releases/download/v0.2.5/dsh-vision-bridge-0.2.5.tgz' -OutFile 'dsh-vision-bridge-0.2.5.tgz'##### macOS / Linux
curl -LO https://github.com/TwistedRiCen/dsh-vision-bridge/releases/download/v0.2.5/dsh-vision-bridge-0.2.5.tgz#### 3. Verify the checksum
Compare the file's SHA-256 against the value published on the release page (the dsh-vision-bridge-0.2.5.tgz.sha256 release asset). If it differs, do not install the file — delete it and download again from the official release page.
##### Windows PowerShell
(Get-FileHash .\dsh-vision-bridge-0.2.5.tgz -Algorithm SHA256).Hash##### macOS / Linux
sha256sum dsh-vision-bridge-0.2.5.tgz # Linux
shasum -a 256 dsh-vision-bridge-0.2.5.tgz # macOS#### 4. Install the plugin into your profile
Run this from the directory that contains the downloaded file:
dsh plugin --profile <profile> add .\dsh-vision-bridge-0.2.5.tgzdsh plugin initializes the profile on first use, installs the package with pnpm, and then reconciles the profile's bundle list: because the package declares a dsh.bundle manifest entry, @liangdacheng/dsh-vision-bridge is added to dsh.profile.bundles in the profile's package.json automatically.
Verify the reconciliation by checking the profile's package.json:
{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@liangdacheng/dsh-vision-bridge"
]
}
}
}@liangdacheng/dsh-vision-bridge must be present in dsh.profile.bundles. If your DSH build does not add it automatically (the reconciliation behavior varies by DSH build), append "@liangdacheng/dsh-vision-bridge" to that array manually and save the file.
#### Alternative: install from npm
From v0.2.4 the package is also published to the official npm registry as @liangdacheng/dsh-vision-bridge. With a global dsh:
dsh plugin --profile <profile> add @liangdacheng/dsh-vision-bridge@0.2.5Without a global dsh:
npx -y "@deepseek-ai/dsh@0.1.0-rc.6" plugin --profile <profile> add "@liangdacheng/dsh-vision-bridge@0.2.5"dsh plugin add forwards to pnpm, which installs the exact published version and reconciles @liangdacheng/dsh-vision-bridge into dsh.profile.bundles. Never install the unscoped dsh-vision-bridge npm package — it is a different, unrelated project.
#### 5. Configure the bridge (required)
The bridge needs a text-only upstream route; everything else can be auto-discovered. The minimal configuration is a single key — supply it by editing the profile's cordis.patch.yml (see [Configuration](#configuration) for the full contract):
- id: dsh-vision-bridge
config:
upstreamProvider: <text-provider> # your text-only reasoning routeThat is all. On the first image request the bridge automatically discovers the DSH model that positively declares image input and pins it as the Vision target for this plugin lifetime. Users who prefer explicit control can still set visionProvider and visionModel — see [Configuration](#configuration) for both modes.
#### 6. Start or restart DSH
DSH boots a profile as a foreground process; there is no separate start command. Stop a running instance with Ctrl+C and boot the profile again:
dsh --profile <profile>(Without dsh on your PATH, use npx @deepseek-ai/dsh --profile <profile>.)
Use the same profile you installed the plugin into. The bridge registers itself during boot; a config error fails the boot loudly, so a clean boot is itself a first signal that the plugin is active.
#### 7. Verify the installation
1. Print the composed profile configuration and confirm the bridge row and your config appear:
``powershell dsh --profile <profile> --dump-config ``
You should see a row with id: dsh-vision-bridge carrying at least your upstreamProvider value (plus visionProvider/visionModel when you configured them explicitly).
2. Boot the profile and open your DSH interface. The model catalog now contains a synthetic provider named after <upstreamProvider>-vision-bridge; its models are listed as <original name> (vision bridge).
3. Select a (vision bridge) model and attach an image to a message — see [Usage examples](#usage-examples).
Configuration
All configuration is plugin row configuration for the dsh-vision-bridge row. The package's own bundle layer (cordis.patch.yml) inserts the row; your profile's cordis.patch.yml supplies the row's config.
The file to edit is $DSH_HOME/profiles/<profile>/cordis.patch.yml — a YAML array of loader patch entries. Add (or extend) an entry with id: dsh-vision-bridge:
Minimal configuration (Vision Auto-Discovery)
Only the upstream route is required:
- id: dsh-vision-bridge
config:
upstreamProvider: <text-provider> # your text-only reasoning routeWhen visionProvider and visionModel are both omitted, the bridge enters Vision Auto-Discovery: on the first request that actually contains an image, it asks DSH for the current provider catalog, keeps only models whose metadata positively declares image input (inputModalities contains image), re-confirms the capability through DSH's exact-model metadata, and then:
- exactly one such model → it is pinned as the Vision target for this
plugin lifetime (profile restart or config reload re-discovers);
- none → the image request fails closed with guidance (configure an
image-capable model in DSH, or set visionProvider + visionModel);
- more than one → the image request fails closed and lists every
candidate, asking you to configure visionProvider + visionModel explicitly.
Discovery is lazy: text-only requests never trigger it. Discovery is also strictly capability-based — model names, provider names, and external knowledge are never used to guess image support; only explicit DSH metadata counts, and no probing request is ever sent to test capability.
Explicit configuration (advanced override)
To pin a specific Vision route yourself, configure both keys:
- id: dsh-vision-bridge
config:
upstreamProvider: deepseek-official # example: a text-only reasoning route
visionProvider: deepseek-official # example: the route serving the vision model
visionModel: deepseek-vl # example: the image-capable model id
# providerId: my-bridge # optional synthetic provider idExplicit configuration always wins over Auto-Discovery. Configure both visionProvider and visionModel or neither — configuring only one is a configuration error and fails fast at boot
…