← 返回条目

dsh-plugin-gating-hub · 使用说明

中文版:依据官方 README 翻译整理,保留原有结构与命令

Web & Desktop — both supported.

English: README.md | 中文: README.zh.md

DSH Plugin Gating Hub (dsh-plugin-gating-hub)

Renamed from dsh-plugin-hub — old URLs redirect.

Framework-upgrade safety and plugin-version gating for DSH. A failed upgrade rolls back.

A framework changed by any update channel is still guarded. A version the host cannot

take is refused, not installed.

[](https://github.com/deepseek-ai/deepseek-harness)

[](https://awesome-dsh-plugin.com)

[](https://github.com/Noob-stupid/dsh-plugin-gating-hub/stargazers)

[](LICENSE)

[](https://github.com/Noob-stupid/dsh-plugin-gating-hub/commits/main)

[](https://github.com/Noob-stupid/dsh-plugin-gating-hub/actions/workflows/registry.yml)

[](https://github.com/topics/dsh-plugin)

[](https://www.npmjs.com/package/@noob-stupid/dsh-plugin-console)

[](https://www.npmjs.com/package/@noob-stupid/dsh-plugin-console)

[](https://github.com/Noob-stupid/dsh-plugin-gating-hub/releases)[](https://www.dsh.so/artifact/dsh-plugin-hub)

[](https://www.dsh.so/artifact/dsh-plugin-hub/)

Install (npm, one line)

dsh plugin --profile web add @noob-stupid/dsh-plugin-console

Then restart the dsh service → refresh the page → Settings → Plugins → Plugin Console.

Three hard guarantees

runs first (message contract / dependency API / config schema / removed API / loader contract);

then config backup + a full-tree rollback point. A failed install or relaunch **auto-rolls

the tree back**, a 「roll back to previous」 button restores the last version, and plugins the

new framework cannot load are auto-disabled — version check catches fake success, 15-min

timeout + stall detection.

catches changes made by the official desktop updater or a manual pnpm: it auto-runs a

read-only pre-flight, and disables a row only with hard evidence (package unresolvable /

file:// target gone / named in a boot-failure log). @deepseek-ai/ and *protected / core

rows are never auto-disabled**; each auto-disable writes a one-command recovery record.

engines.dsh / @deepseek-ai/* ranges, built-in zero-dependency semver), a repo-size gate

on source channels, and explicit handling of non-registry sources — a bare version is

written back only once the registry really resolves it, otherwise the package is materialized

as link:. Install scripts are never auto-authorized, and pnpm's supply-chain gate is never

bypassed.

Discovery layer on top: a built-in multi-source plugin market & index (500+ plugins /
300+ skills, zero GitHub API calls) — and every source is swappable: install source
(incl. a private intranet registry), search source (URL template + headers), index source
(self-hosted intranet index), Git source (incl. a local file:// bare repo), so plugins can be
installed on an intranet-only or fully offline machine.

Why DSH Plugin Gating Hub

checkpoint (rollback point) → online install (service stays up, page never disconnects) →

version verification → auto-restart. A failed install auto-rolls the whole tree back,

version check catches fake success, 15-min hard timeout + stall detection — the framework is

never left broken. → details

a 「roll back to previous」 button: stop service → restore full tree → relaunch → health check,

state visible throughout.

framework cannot load (enable locked; the server rejects /toggle with 409 — unbypassable);

「Check update → Update & adapt」auto-verifies and unlocks them.

engines.dsh + @deepseek-ai/* ranges, built-in zero-dependency semver engine) decides

whether a plugin version may run on this host, so an upgrade can't silently take plugins out.

plus the static index of dsh-plugin repos (500+ by stars) and a Skills tab (up to 300);

browse, search, one-click install, zero GitHub API calls (served via CDN).

Every source is swappable — private intranet npm registry, custom search source (URL template +

headers), self-hosted index source, Git source (incl. local file:// bare repo) — so an

intranet-only / offline machine can still browse and install.

reads its docs and drafts a safe, confirmable deployment plan (install / config /

start / health-check); server components get an automatic control card.

→ details

Install

# npm release (recommended: prebuilt, no git / build authorization needed)
dsh plugin --profile web add @noob-stupid/dsh-plugin-console

# or install from GitHub source (needs git; allowBuilds authorization on first add)
dsh plugin --profile web add github:Noob-stupid/dsh-plugin-gating-hub

Then restart the dsh service → refresh the page → Settings → Plugins → Plugin Console.

More install options (deploy script / hand it to an AI)

Option 2: deploy script (fallback when network is restricted)

Windows (PowerShell):

git clone https://github.com/Noob-stupid/dsh-plugin-gating-hub "$env:TEMP\dsh-plugin-console" 2>$null; & "$env:TEMP\dsh-plugin-console\deploy.ps1"

Linux / macOS:

git clone https://github.com/Noob-stupid/dsh-plugin-gating-hub /tmp/dsh-plugin-console 2>/dev/null; bash /tmp/dsh-plugin-console/deploy.sh

The script copies the plugin into $DSH_HOME/profiles//node_modules/ and

idempotently appends an enable entry to cordis.patch.yml. Afterwards:

  1. Restart the dsh service (host code changes need a process restart; CLI restarts the

process, the desktop client exits and reopens);

  1. Refresh the page → Settings → Plugins → Plugin Console.

Option 3: hand it to an AI in one sentence

Install the DSH plugin hub (dsh-plugin-hub): run dsh plugin --profile web add @noob-stupid/dsh-plugin-console (npm release); if there is no dsh CLI, clone https://github.com/Noob-stupid/dsh-plugin-gating-hub to ~/.dsh/profiles/web/node_modules/ and register it in cordis.patch.yml (id: plugin-console, name: @noob-stupid/dsh-plugin-console). Restart dsh web afterwards.

Requires: DSH ≥ 0.1.0-rc.6 (web profile, with dsh-client-modules / dsh-host-plugin-inventory).


Highlights

BenefitDetail
🤖AI Empower Give the console a package name or GitHub repo — the local AI reads docs, drafts a deployment plan (install / write config / start service / health check) and executes it safely after your confirmation; server-type components get an automatic control card
🛡️Framework upgrade safety & adapt gate Force-disables plugins incompatible with the new framework (enable locked; 「Check update → Update & adapt」auto-verifies and unlocks); full-tree checkpoint before upgrade, automatic rollback on relaunch failure, one-click rollback to the previous version
🏠Family-bundle cards & safety Same-root subpath exports group into one family card (collapse/expand, batch check-update, one-click unlock-adapted, known-check preview); never-crash safety (pre-enable import probe + patch auto-heal + exports fallback); adapt-gate source-scan hard criterion & migrate detection; deleting a bundle sub-row disables only that row
🚀Server component cardsLeft-side floating card auto-aligned to the main panel: start / stop / status / open Web UI buttons, multi-server dropdown, collapsible
🧩Plugin & skill hubAuto-collected index of dsh-plugin topic repos (500+ by stars) plus a Skills tab (agent-skills ∪ claude-skills ∪ dsh-skill, up to 300) — browse, search, one-click install, no GitHub API calls
🤖Auto-collection CIGitHub Actions reruns build-index every 6 hours (manual trigger available); authors just add the dsh-plugin / agent-skills / claude-skills / dsh-skill topic — no application needed
⚡Instant, rate-limit-freeThe index is served as a static marketplace/index.json via jsDelivr CDN (10-min host cache); terminal users make zero GitHub API calls
🔄Version detection & one-click updateSemver-based; installed entries match npm dist-tags.latest / beta; subpackage mismatch warnings prevent mixed-version breakage
🔀Multi-sourceGitHub / Gitee (direct-repo mode) / custom search sources (URL template + header auth + private http); ⊞ merges GitHub + all custom sources in parallel
🔒Safe by defaultLoopback-only routes; AI fallback behind an explicit cost-consent modal; infrastructure rows are toggle-protected

📑 目录 / Table of Contents


Usage

  1. Restart DSH → open the Web GUI → Settings → Plugins → Plugin Console.
  2. Installed list: toggle plugins on/off (HMR applies within ~1s), search by name/id,

expand details (version, repository, README summary).

  1. 市场: empty query on the GitHub source opens the static index (instant);

type a query to search live. Switch sources via the login pill (GitHub / Gitee / custom);

⊞ merges all sources; ★ filters to dsh plugin add-installable packages.

  1. Skills tab: switch 插件/技能 next to the search box to browse and install skills

(cloned into ~/.dsh/skills//).

  1. Install: click 添加到本地 → the chain runs in the background (safe to leave the page);

「检测更新」/「更新 → vX」 appear automatically for installed entries.


Screenshots · 界面一览

入口挂在官方插件管理页自己的插槽(plugins.bundle.config,key = 包名):装完之后它出现在
「设置 → 插件 → 已安装」里我们这一条下面,用的是官方容器与官方风格 —— 不是 DOM 注入,官方更新也不怕。

1 · 已安装列表里的入口(官方页,点开我们这条即见)

2 · 「升级安全」面板(就地展开:运行模式 / 框架版本 / 回滚点 / 环境指纹 / 补声明 / 契约预检 / 各功能入口)

3 · 框架升级 / 回滚(可选目标版本、常驻的升级进度、一键回滚上一版)

4 · 门控明细(谁被隔离、为什么:升级预扫 or 启动失败隔离,附来源与时间)


Features

Installed plugins (one-click toggle + details)

"Third-party" with a delete entry; click "All" to see the full list (1.5s flash feedback);

disabled: false;

(70+ rows) are marked "Protected" and cannot be toggled — disabling them would break HMR;

node networking is blocked) and warns about subpackages that need syncing (depsOutdated).

Framework one-click upgrade (deepseek-harness card)

available (stable latest preferred; next channel when latest equals the installed

version); clicking runs the full flow: backup config + framework snapshot (rollback point)

→ online install (service stays up, page never disconnects) → version verification →

auto-restart to apply;

progress; the in-panel progress card shows the waiting time;

upgrade), version check catches fake success, 15-min hard timeout, stall detection

(no debug-log updates → auto switch registry), global trap fallback, and 15-min stale-state

cleanup — the framework is never left broken;

debug log, no network requests ever sent); upgrades use corepack pnpm (starts in ~0.4s,

installed rc.8 in 11.5s) against the npmmirror (China) registry, with

dangerouslyAllowAllBuilds so native modules (node-pty/koffi) compile;

relaunch step resolves bin.js at runtime (follows the Junction to the current version)

instead of using a path baked in at script-generation time;

(persisted); in-progress dismissal is session-only and the card returns after a refresh.

Marketplace (multi-source)

sources** (persisted); title, loading text, placeholder and note all follow the source;

owner/repo (Chinese paths and full URLs supported) to find and install a repository;

optional header auth (e.g. Authorization: Bearer ...), and local/private http URLs;

merging results with source labels;

with a dsh.bundle manifest (official) or aggregate repos whose **subpackage carries

dsh.bundle** (subpackage-installable); markers are enriched by the server (curl dual-channel)

with a client-side fallback;

Network environment notes (why a multi-source setup can look "all dead")
- Accelerators/proxies that rewrite hosts kill the direct sources: tools like Steam++ often point
github.com at 127.0.0.1, so the GitHub direct source, raw.githubusercontent.com and
api.github.com all become unreachable — the plugin is not broken. The console now reports this
honestly as "local proxy / certificate interception (…) — an accelerator or proxy was detected,
turn it off and retry" instead of a vague "network unreachable".
- **Free mirrors are unreliable for the git protocol on large packs, while archive/raw are usually
fast: measured on the same ghproxy.net host, archive (plain HTTP) ran at 4 MB/s** while the git
protocol moved 0 B/s. Since this version the git channel has a stall criterion (switch source
after 20 s below 1 B/s) plus its own budget, and falls back to the archive channel (download the
tarball, extract, create the repo — equivalent to a clone) when all git sources fail. No manual
source switching needed.
- To reorder transports, use Source Manager: git sources, archive sources and **index
sources** all support primary→backup plus self-hosted mirrors (internal Gitea/GitLab, local
file:// bare repos).
Download-install channels and dependency forms

Which channel gets used depends on what the package actually is — not on a setting:

ChannelTargetWhen it is usedWritten in the manifest asNeeds plugin-src
① pnpm (registry)npm registryif the package is on the registry, this is the main channel: no
② curl tarball (registry)npm registry tarballraces in parallel with ① (takes over when pnpm is blocked/stuck)same as aboveno
③ GitHub Release assetprebuilt tgz of an upstream releasewhen both registry sources 404link:yes
④ git clonerepository sourceno npm package / no release assetlink:…yes
⑤ archive (tar.gz)codeload / mirrorswhen the git protocol cannot move any byteslink:…yes

In one sentence: **has an npm package → ①/②, write a version, keep the lock clean; no npm package →

fall back to ③/④/⑤, materialize into ~/.dsh/plugin-src/ and write link:.**

Environment reminder: an accelerator/proxy that rewrites hosts makes the direct sources unreachable

(see above), and free mirrors are unreliable for the git protocol on large packs while

archive/raw are usually much faster — the console already switches by itself.

Development installs (link:)

Ordinary installs go through the package manager (pnpm add); that is the baseline, not a feature here.

link: is the separate, explicit route: mount a local directory / plugin you are developing

directly into the profile.

local directory, not a copy — edit the source, refresh the page. No reinstall, no repackaging.

to use a plugin, an ordinary install is simpler.

(link:) and gets a matching entry in pnpm-lock.yaml — so lockfile health checks

and rebuilds never treat it as an orphan, and it survives restarts and instance updates.

what the local directory is missing;

Node's resolution chain never reaches the profile's node_modules. The console links the framework

peers it declares and currently cannot resolve (@deepseek-ai/*) at the plugin root,

pointing at ~/.dsh/profiles/node_modules/@deepseek-ai/. It is a link, not a copy —

both sides share the same realpath, so Cordis service classes and LLM error classes keep their

module identity shared with the host.

path that no longer exists);

does not have is never invented;

— it is skipped and reported;

never touched);

still completes**, and the result honestly says "not ready + what is missing" together with an

action you can run.

Static index market (plugin & skill tabs)

Hybrid architecture: browsing uses the static index (instant, zero GitHub API calls),
searching uses live channels (GitHub search API / multi-source parallel) — they complement
each other: a brand-new repo can be found by live search even before it enters the index.

jsDelivr CDN + 10-min host cache): 500+ plugins by stars, instant, zero GitHub API calls;

agent-skills ∪ claude-skills ∪ dsh-skill repos (up to 300);

dist-tags.latest in the background — cards turn into 「更新 → vX」 buttons;

(frontmatter name wins over repo name; SKILL.md found at repo root or first-level

subdirectory). Installed skills show a grey 「已装」 badge.

Source Manager

The floating "Sources" button (right of the title row, semi-transparent) opens the manager:

private and intranet addresses supported; deletion is protected (install-critical);

header count);

create a third-party app (gitee.com → Data management → Third-party apps, scopes

user_info, projects), fill client_id / client_secret, save, then authorize.


Run mode (managed / observer)

The mode decides who leads framework upgrades — nothing else:

Boot-failure quarantine is not affected by the mode. When the service cannot start, the console locates the culprit from the boot log and disables it (broken presets are renamed to .broken-*; with no clear culprit it falls back to safe mode so the service can start). A console that cannot boot cannot gate anything — so this rescue path always runs.

Auto-disable on confirmed evidence (0.5.32): when the fingerprint-triggered auto-preflight, or a

boot-failure record, provides confirmed evidence (the row's package resolves on none of the

resolution bases, a file:// target truly does not exist, or the boot log names the row), the console

writes disabled: true for those rows itself (no click needed). Safety rails: **only rows with

evidence**; @deepseek-ai/* (framework-owned) and protected/core rows are never auto-disabled;

a safe-boot snapshot is written first, so any auto-disable is one command away from a rollback;

when there is nothing to write, not a single byte is written; every auto-disable leaves a record in

dshHome()/plugin-console/auto-disable.log (time / row id / evidence / restore command).

Prefer "report only, let me click" (enabled by default) — replace `` with your instance

(the default dsh web profile listens on 127.0.0.1:3080):

curl -X POST http:///plugin-console/compat-ack \
  -H 'Content-Type: application/json' -d '{"autoDisableOnEvidence":false}'

*

内容取自仓库 README,未做删改性总结。命令与参数以原文为准。