jackxiao-hub
dsh-plugin-tree
No description
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-plugin-tree 🌳
DSH(DeepSeek Harness)Web GUI 客户端插件:把 设置 → 插件 页面升级为依赖分层的插件明细树,并附带一张可交互的依赖关系图。依赖即前置条件——一眼看清插件之间的上下层关系,直接启停、检查更新。
A DSH web client plugin that turns the Settings → Plugins page into a dependency-layered plugin tree, plus an interactive dependency graph. Dependencies are prerequisites: see at a glance how plugins stack on each other, toggle them, and check for updates.
切换语言 / Language: 中文 · English

中文
功能
- 🌳 依赖分层树:按最长依赖链自动分层(L0 基础库 … L5 领域服务,更深层显示
L{n}),层可折叠并显示插件数;无匹配条目的层自动隐藏 - 🏷️ 来源标识:每个插件显示 官方/第三方 + 随 dsh 安装 / npm 安装 / 本地链接 / workspace / 静态文件
- 🔍 搜索 + 三轴独立筛选:按模块名/描述搜索;启用状态 / 来源(默认第三方)/ 安装方式三个筛选轴取交集
- 📋 节点详情:版本、来源、描述、状态,以及依赖/被依赖列表;第三方插件详情内可直接 停用/启用(即时生效 + 持久化到
cordis.patch.yml,重启保留) - 🔗 依赖/被依赖 chips:边框颜色表达状态(绿=已启用、灰=未启用、红=挂载失败、灰虚线=静态),背景色表达来源(官方=淡蓝、第三方=淡黄);按唯一 entry id 判定——同名条目(同一包多个 Loader 行)各自显示各自的状态,点击各自跳到对应行
- ⬆️ 检查更新 / 更新:只检查 npm 安装的第三方插件(
pnpm outdated并发检查,60 秒缓存);有新版时行内出现"更新"按钮(pnpm add <pkg>@latest),安装后提示重启生效 - 🕸️ 依赖树(图):工具栏一键切换分层依赖图——节点按依赖层级排布,静态文件节点过滤;边框=状态(绿/灰/红/虚线)、填充=来源(淡蓝/淡黄),角落有图例;箭头指向前置依赖
- 🔎 1:1 像素渲染,缩放 / 全屏灯箱(页面内全屏遮罩,ESC 退出)/ 空白处拖拽平移 / 进入时横向自动居中
- 🎯 悬停隔离链路:悬停节点只显示其上下游全链路(向上=前置依赖链、向下=被依赖链,两分支互不跨越、遇环停止),其余节点连线隐藏;点击节点钉住链路,再点空白解除
- 📌 全屏节点详情浮层:全屏时点击节点在节点旁弹出详情(优先下发、触边缘自动翻转/收拢),不触发被遮罩盖住的页内详情
安装方法
$DSH_HOME 默认为 ~/.dsh。
方法 A:一行命令(推荐,bundle 安装,发布后可用)
dsh plugin --profile web add github:jackxiao-hub/dsh-plugin-tree
装完重启 dsh web 生效(依赖 pnpm,npm install -g pnpm 即可)。
方法 B:插件市场
设置 → 插件市场 → 搜索 dsh-plugin-tree → 一键安装(收录于 awesome-dsh-plugin 后出现)。
方法 C:手动 link 安装(当前方式,无需发布)
- 克隆本仓库到本地任意目录,如
C:\dev\dsh-plugin-tree - 在 profile 的
package.json中:
{
"dependencies": {
"@dsh-external/dsh-client-ui-plugin-tree": "link:C:/dev/dsh-plugin-tree"
},
"dsh": {
"profile": { "bundles": ["@dsh-external/dsh-client-ui-plugin-tree"] }
}
}
pnpm install后重启dsh web。
插件市场功能已拆分为独立插件 @dsh-external/dsh-client-ui-plugin-market,本插件只负责插件明细。
验证
重启后进入 设置 → 插件,出现"插件明细"标签:默认只显示第三方插件(切换"来源 → 全部"查看完整树);点击任意插件展开详情;工具栏可切到"依赖树"、执行"检查更新"。
配置
无配置项。 本插件是纯 UI 投影 + 用户主动触发的操作,所有行为内建,不需要 cordis.patch.yml 配置块(bundle 安装时只插入一行挂载)。
权限与数据
- 只读:
ctx.loader.entries()与各包package.json(建树)、profile manifest(来源分类) - 写入:启停时改写 profile 的
cordis.patch.yml(仅替换目标{id, disabled}行,保留注释与其他内容) - 子进程:
pnpm outdated/pnpm add(会访问配置的 npm registry,尊重.npmrc镜像) - 不读取任何凭据;不注册提示词/工具/消息,从不参与模型请求路径(无 KV cache 影响)
卸载
- 从 profile
package.json移除@dsh-external/dsh-client-ui-plugin-tree依赖与dsh.profile.bundles行(方法 A/B 则用dsh plugin --profile web remove <spec>) - 重启
dsh web
兼容性
- 开发验证于 Windows + dsh web 当前 mainline(2026-08 快照);Node 22/24
- Host 侧改动需重启 dsh web 生效;Client 侧(界面)按 rev 逐请求刷新,无需重启
常见问题
- 插件明细报"暂时无法读取"? 多为 host/client 版本不匹配(RPC schema 或描述符过期)——重启 dsh web 并刷新页面。
- 改动界面不生效? 界面是 client 面,刷新即可;host 面(启停/更新/建树)改动需要重启。
- 更新后插件没变?
pnpm add只改磁盘,运行中的 loader 仍持有旧模块,重启 dsh web 后新版本才挂载。 - 同名插件一堆? 同一包可以有多个 Loader 行(如
include:预设),状态各自独立;树中按 entry id 判定,依赖图按包名合并为一个节点。
更新日志
- 2026-08:重名条目按唯一 entry id 判定——
deps/dependents携带entryId,同名 chips 各显其态、各跳其行;修复整层静态过滤后的深度压缩、RPC schema 同步 - 2026-08:视觉规范统一——边框=状态(绿/灰/红/虚线)、填充=来源(官方淡蓝/第三方淡黄)、图例、依赖图过滤静态文件
- 2026-08:依赖图交互完善——1:1 像素渲染、缩放、全屏灯箱、拖拽平移、悬停链路隔离、点击钉住、全屏节点详情浮层、悬停闪烁修复
- 2026-08:依赖树图上线——SVG 分层依赖图,节点状态边框 + 来源填充
- 2026-08:检查更新 / 更新安装(pnpm outdated / add)、行内更新按钮
- 2026-08:停用/启用(写 patch 层 + 即时
entry.update,热生效持久化) - 2026-08:M1 —— 依赖分层树、来源徽章、搜索与三轴筛选、详情与依赖跳转
License & security
MIT License(见 LICENSE)。发现安全问题请通过 GitHub issue 私密描述(不要贴凭据/日志中的敏感信息),或直接提 PR 修复。
English
Features
- 🌳 Dependency-layered tree: layers by longest dependency chain (L0 Foundation … L5 Domain services, deeper layers show as
L{n}), collapsible with per-layer counts; empty layers auto-hide - 🏷️ Provenance badges: official / third-party × bundle / npm / link / workspace / static
- 🔍 Search + three independent filter axes: module/description search; status, vendor (third-party by default), install source — intersected
- 📋 Node details: version, source, description, status, and dependency lists; third-party plugins can be disabled/enabled right from the details (live, persisted to
cordis.patch.yml, survives restarts) - 🔗 Dependency/dependent chips: border color = status (green=enabled, gray=not enabled, red=failed, dashed gray=static), background = provenance (official=light blue, third-party=light yellow); resolved by unique entry id — duplicate module names (one package, several Loader rows) each show their own status and jump to their own row
- ⬆️ Update check / install: npm third-party plugins only (
pnpm outdated, 60s cache); rows with a newer version get an inline Update button (pnpm add <pkg>@latest), then a restart applies it - 🕸️ Dependency graph: toolbar switch to a layered SVG graph — static packages filtered out; border = status (green/gray/red/dashed), fill = provenance (light blue/light yellow), legend included; arrows point to prerequisites
- 🔎 1:1 pixel rendering, zoom / fullscreen lightbox (in-page overlay, ESC to exit) / drag-to-pan on blank space / auto horizontal centering on entry
- 🎯 Hover chain isolation: hovering a node shows only its full up/down chain (up = prerequisite chain, down = dependent chain; the two branches never cross and cycles stop), everything else hides; click pins the chain, blank-space click releases
- 📌 Fullscreen node popover: in fullscreen, clicking a node opens details right next to it (prefers below, flips/clamps at screen edges), without triggering the covered in-page details panel
Installation
$DSH_HOME defaults to ~/.dsh.
Method A: one-line install (recommended, bundle; once published)
dsh plugin --profile web add github:jackxiao-hub/dsh-plugin-tree
Then restart dsh web (requires pnpm — npm install -g pnpm).
Method B: plugin market
Settings → Plugin Market → search dsh-plugin-tree → one-click install (once listed in awesome-dsh-plugin).
Method C: manual link install (current way, no publishing needed)
- Clone this repo to any local directory, e.g.
C:\dev\dsh-plugin-tree - In the profile's
package.json:
{
"dependencies": {
"@dsh-external/dsh-client-ui-plugin-tree": "link:C:/dev/dsh-plugin-tree"
},
"dsh": {
"profile": { "bundles": ["@dsh-external/dsh-client-ui-plugin-tree"] }
}
}
pnpm install, then restartdsh web.
The plugin-market feature lives in the separate plugin @dsh-external/dsh-client-ui-plugin-market; this plugin covers plugin details only.
Verification
After the restart, open Settings → Plugins and find the "Plugin details" tab: third-party plugins are shown by default (switch the vendor filter to "All" for the full tree); click any plugin to expand its details; the toolbar switches to the "Dependency graph" and runs "Check updates".
Configuration
None. This is a pure UI projection plus user-triggered actions — everything is built in, no cordis.patch.yml config block needed (the bundle install just inserts a mount row).
Permissions & data
- Read-only:
ctx.loader.entries()and per-packagepackage.json(tree building), profile manifest (provenance) - Writes: rewrites the profile's
cordis.patch.ymlon toggle (only the target{id, disabled}row; comments and other content preserved) - Subprocesses:
pnpm outdated/pnpm add(talks to the configured npm registry, respects.npmrcmirrors) - Never reads credentials; registers no prompts/tools/messages and never touches model request paths (no KV-cache impact)
Uninstall
- Remove
@dsh-external/dsh-client-ui-plugin-treefrom the profilepackage.json(dependency +dsh.profile.bundlesrow; for method A/B usedsh plugin --profile web remove <spec>) - Restart
dsh web
Compatibility
- Developed and verified on Windows with the dsh web current mainline (2026-08 snapshot); Node 22/24
- Host-side changes require restarting
dsh web; client-side (UI) changes apply on refresh (per-request rev), no restart
Troubleshooting
- "Plugin details temporarily unavailable"? Usually a host/client version skew (stale RPC schema or descriptor) — restart
dsh weband refresh. - UI changes not showing? The UI is the client side — refresh. Host-side changes (toggle/update/tree building) need a restart.
- Updated a plugin but nothing changed?
pnpm addonly touches disk; the running loader keeps the old modules untildsh webrestarts. - Duplicate-named plugins everywhere? One package can have several Loader rows (e.g.
include:presets) with independent states; the tree keys them by entry id, the graph merges them into one node per package.
Changelog
- 2026-08: Duplicate names resolved by unique entry id —
deps/dependentscarryentryId; same-named chips each show their own status and jump to their own row; depth compression after whole-layer static filtering; RPC schema sync - 2026-08: Unified visual spec — border = status (green/gray/red/dashed), fill = provenance (official light blue / third-party light yellow), legend, static filtering in the graph
- 2026-08: Graph interaction polish — 1:1 pixel rendering, zoom, fullscreen lightbox, drag-to-pan, hover chain isolation, click-to-pin, fullscreen node popover, hover flicker fix
- 2026-08: Dependency graph — layered SVG graph with status borders and provenance fills
- 2026-08: Update check / install (pnpm outdated / add) with inline update buttons
- 2026-08: Enable/disable (patch layer write + live
entry.update, hot and persistent) - 2026-08: M1 — dependency-layered tree, provenance badges, search & three-axis filters, details and dependency jumps
License & security
MIT License (see LICENSE). To report a security issue, describe it privately in a GitHub issue (no credentials or sensitive log excerpts), or open a fix PR directly.
License
MIT