dsh-ai-model-hub
DeepSeek Harness plugin and library for local AI models: a capability catalog, router, runtime manager, and real engine adapters. The agent names a capability; the hub selects, starts, and calls a suitable model. 适合需要统一调度和运行本地多模态(文本、图像、3D等)模型的人群。
설치
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:Mhmd7-7/dsh-ai-model-hubdsh-ai-model-hub
A modular local AI model ecosystem for DeepSeek Harness (DSH).
DSH is the agent — it reasons, plans, calls tools, and orchestrates workflows. It is not the model runtime. The specialised models (text, image, 3D, audio, video) are external and local, reached through a capability interface. DSH never learns how to launch Stable Diffusion, which Python file starts a mesh generator, or how a given engine manages its process. It only asks:
What capabilities are available?
Everything below that question is this project's job.
┌──────────────────────────────────────────────────────────────────────┐
│ DeepSeek Harness agent reasoning, planning, │
│ ───────────────── tool invocation, workflows │
│ │
│ tools: invoke_model · list_models · list_capabilities · │
│ get_model_status · start_model · stop_model · … │
└───────────────────────────────┬──────────────────────────────────────┘
│ dsh-ai-model-hub DSH plugin
│ (the ONLY DSH-aware code)
┌───────────────────────────────▼──────────────────────────────────────┐
│ ModelHub facade invokeModel({ capability }) │
│ ┌────────────────┬──────────────────┬───────────────────────────┐ │
│ │ Capability │ Model Router │ Runtime Manager │ │
│ │ Catalog │ deterministic │ lifecycle · health · │ │
│ │ registry + │ capability-first │ idle timeout · resources │ │
│ │ validation │ selection │ │ │
│ └────────────────┴──────────────────┴───────────────────────────┘ │
│ ┌──────────────────────────────┬────────────────────────────────┐ │
│ │ Model Adapters │ Artifact Store │ │
│ │ openai_compatible · http_json│ durable, typed, addressable │ │
│ │ comfyui · three_d · │ text/image/audio/video/3D/… │ │
│ │ mock (tests only) │ │ │
│ └──────────────────────────────┴────────────────────────────────┘ │
└───────────────────────────────┬──────────────────────────────────────┘
│ spawn (argv, never a shell string)
┌───────────────────────────────▼──────────────────────────────────────┐
│ Local engines: Ollama · llama.cpp · A1111/Forge · ComfyUI · │
│ TRELLIS · Hunyuan3D · Stable Fast 3D · TripoSR · … │
└──────────────────────────────────────────────────────────────────────┘
Status
Live as a DSH profile plugin. The package installs as one unit — dsh plugin add mounts it, so the hub is composed on every boot — and it serves real local
engines only: Ollama for text, ComfyUI / A1111 / Forge for images, llama.cpp for
a second text engine, and any local image-to-3D Gradio app for meshes. There are no
mock models anywhere in the shipped catalogs and no mock fallback at runtime: a
wrong model name or a stopped engine is a loud error (or a cold start), never
fixture output.
The whole architecture — catalog → routing → runtime → adapter → artifact → chained workflow — is covered by the test suite, which uses an in-process mock adapter as a test double. That adapter is not a model: nothing ships it in a catalog, and no deployment can reach it by accident.
| Phase | Scope | Status |
|---|---|---|
| 1 | Full architecture, DSH plugin, tests | ✅ done |
| 2 | Real local text model (Ollama / llama.cpp / vLLM / LM Studio) | ✅ done — openai_compatible adapter ships |
| 3 | Real local image model (A1111 / ComfyUI) | ✅ done — http_json and comfyui adapters ship |
| 4 | Real local 3D model | ✅ done — three_d adapter ships; see docs/three-d.md |
| 5 | Runtime lifecycle + resource-aware routing | ✅ done — the machine is probed and routed against |
| 6 | Multi-model workflows | ✅ done |
Phase 2 needs no new code: the openai_compatible adapter is implemented, and
config/examples/real-models.example.json contains ready-to-copy Ollama and
llama.cpp entries. Phase 3 is implemented by two adapters, because the two
engine families are genuinely different:
http_json— engines that answer one request with a finished image: AUTOMATIC1111, Forge, andstable-diffusion.cpp'ssd-server. It POSTs the familiar/sdapi/v1/txt2imgbody and decodes the base64 images that come back.comfyui— ComfyUI takes an API-format node graph, not a prompt endpoint. Each explicitly configured workflow declares capabilities, exact input bindings and a typed output selector. The adapter treats graph internals as opaque, edits only declared inputs, queues on/prompt, polls/history, and retrieves the declared output. No checkpoint or saved-workflow enumeration creates providers.
Phase 4 is three_d: one adapter that speaks the shape the local 3D ecosystem
actually has — a Gradio queue API or a JSON HTTP route, one or two calls, a mesh
file at the end — so TRELLIS, Hunyuan3D, Stable Fast 3D, and TripoSR are catalog
entries rather than code. It writes a typed model_3d artifact (GLB, GLTF, OBJ,
STL, or PLY, sniffed from the bytes), and a discoverer verifies a declared engine
against the API surface it actually exposes before publishing anything.
Phase 5's remaining gap is closed: ModelHub now probes RAM, VRAM, free VRAM, and
disk, re-measures on demand, and routes against measured headroom — so a model
that would not fit beside what is already loaded is refused with the shortfall in
the message instead of crashing inside the engine.
All adapters are registered by default. See
docs/adding-a-model.md, docs/three-d.md,
and the protocol templates in config/workflows/.
Install
One command, on a machine that already has Node ≥ 22.6 and DeepSeek Harness:
# into the profile behind `dsh web` — the normal case
dsh plugin --profile web add github:Mhmd7-7/dsh-ai-model-hub
This package is the plugin: it declares dsh.bundle.patch, so dsh plugin add installs it and appends dsh-ai-model-hub to dsh.profile.bundles. The
profile composes that bundle on every boot, which is what makes the plugin
live, not merely installed. No profile file is edited by hand and no
cordis.patch.yml has to be written.
Then restart DeepSeek Harness and ask:
List the available AI model capabilities.
| What you want | Command |
|---|---|
| Another profile | dsh plugin --profile hubtest add github:Mhmd7-7/dsh-ai-model-hub |
| A pinned release | dsh plugin --profile web add github:Mhmd7-7/dsh-ai-model-hub#v0.6.0 |
| A published copy | dsh plugin --profile web add dsh-ai-model-hub |
| A checkout you are editing | node --no-deprecation scripts/install-plugin.mjs --profile web |
The last one links the working tree instead of copying it, so the plugin loads
your sources; run npm run build there first if you edited anything under
src/ or dsh-plugin/.
install.ps1 and install.sh remain one-line wrappers for the first row, and
keep their flags (-Profile, -Ref, -Repository, -SkipDoctor):
irm https://raw.githubusercontent.com/Mhmd7-7/dsh-ai-model-hub/main/install.ps1 | iex
curl -fsSL https://raw.githubusercontent.com/Mhmd7-7/dsh-ai-model-hub/main/install.sh | sh
To remove an installation:
dsh plugin --profile web remove dsh-ai-model-hub
Which DeepSeek Harness versions this runs on
The plugin tracks the DSH 0.x line rather than a single release:
| Supported | @deepseek-ai/dsh* >=0.1.5-rc.2 =0.1.5-rc.2 |
| takes another catalog, and the last section deliberately asks for a capability | |
| nobody serves, to show what a refusal looks like. |
npm run demo:3d needs nothing installed. It starts a stand-in 3D engine inside
the example and runs the whole real path against it — discovery, health,
resource-aware routing, a two-step Gradio protocol, and a .glb written to disk —
then prints every HTTP request the engine saw, to make the boundary concrete. To
point it at TRELLIS instead, swap the stand-in for your catalog entry; the three
capability calls are identical. See docs/three-d.md.
B. Give the capability to the DeepSeek Harness agent
# Installs into the 'web' profile (the one behind `dsh web`), then verifies.
npm run install:plugin
# ...or target another profile:
node --no-deprecation scripts/install-plugin.mjs --profile
Then restart DeepSeek Harness and ask the agent:
List the available AI model capabilities.
Checking an installation
npm run doctor # inspects: is it loadable, and if not, why not
node scripts/smoke.mjs --profile web # acts: applies the plugin and lists what it registered
doctor inspects and reports; smoke actually runs the plugin against a real
cordis context and prints the tools it registered. Use smoke when you want
proof rather than a checklist:
Registered tools:
check_model_health explain_routing get_model_status invoke_model
list_artifacts list_capabilities list_models start_model
stop_model refresh_model_discovery
Catalog: model hub ready: 2 model(s), 2 capability(ies) from …/config/models.json
Note on flags.
npm runforwards flags to the script, but npm 12 parses--profileas its own config flag and fails. Use the directnode scripts/smoke.mjs --profileform for a non-default profile.
If DSH fails to boot after installing
If the harness dies with:
invalid plugin, expect function or object with an "apply" method, received object
then the row cordis.patch.yml inserts is pointing at something that is not a
plugin. In this package that can only happen if the row's name was changed
away from the bare package name: dsh-ai-model-hub resolves to the package's
. export, which is the plugin (lib/dsh-plugin/index.js, exporting
name/inject/apply/Config). The hub library lives behind the
dsh-ai-model-hub/library subpath instead, precisely so the two cannot be
confused.
The row has two names, and they are easy to conflate: id is the row's name in
the composed tree (what a profile's own cordis.patch.yml uses to override or
disable it), while name is the module specifier the loader imports. Keep
name bare — a subpath such as dsh-ai-model-hub/plugin would load the host half
but silently drop the Web UI half, because DSH's client module system only
resolves a row's package manifest from a bare specifier. cordis.patch.yml
documents this in pla