Skip to content
dsh.fish
Bundle

@dsh-external/dsh-client-ui-plugin-tree

Dependency-layered plugin skill tree tab for the dsh web GUI plugins settings

Source
jackxiao-hub
License
MIT
Updated
Updated 20 days ago

Readme

# dsh-plugin-tree 🌳

[![awesome · DSH plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)

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](#english)
<img width="827" height="817" alt="image" src="https://github.com/user-attachments/assets/ae27d3e8-42f0-4c58-b01a-ec8b6115276f" />
<img width="797" height="798" alt="image" src="https://github.com/user-attachments/assets/ecc00468-5ba0-46a3-8d00-86b7cbc73357" />
<img width="2403" height="1273" alt="image" src="https://github.com/user-attachments/assets/f922c540-426b-4a8e-9ff2-fc2506854c82" />
---

## 中文

### 功能

- 🌳 **依赖分层树**:按最长依赖链自动分层(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 安装,发布后可用)**

```bash
dsh plugin --profile web add github:jackxiao-hub/dsh-plugin-tree
```

> 建议固定 commit 安装:`github:jackxiao-hub/dsh-plugin-tree#<commit-sha>`——固定后每次安装内容可复现、便于审计;不固定则随仓库最新提交变化。

装完**重启 `dsh web`** 生效(依赖 pnpm,`npm install -g pnpm` 即可)。

**方法 B:插件市场**

设置 → 插件市场 → 搜索 `dsh-plugin-tree` → 一键安装(收录于 awesome-dsh-plugin 后出现)。

**方法 C:手动 link 安装(当前方式,无需发布)**

1. 克隆本仓库到本地任意目录,如 `C:\dev\dsh-plugin-tree`
2. 在 profile 的 `package.json` 中:

```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"] }
  }
}
```

3. `pnpm install` 后**重启 `dsh web`**。

> profile 的 `package.json`(依赖与 `dsh.profile.bundles` 层栈)属于 `dsh plugin` 命令维护;手改仅限发布前的本地开发捷径,发布后请用方法 A/B。

> 插件市场功能已拆分为独立插件 **@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 影响)

### 卸载

1. 从 profile `package.json` 移除 `@dsh-external/dsh-client-ui-plugin-tree` 依赖与 `dsh.profile.bundles` 行(方法 A/B 则用 `dsh plugin --profile web remove <spec>`)
2. 重启 `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**:**打包修复**——移除悬空的 `./remote` 导出(无对应产物),补齐 `lib/invariant.js` 伴生件产物(不随 bundle 自动挂载:等待 `invariants` 服务的 entry 会使 web 启动失败,需组合层显式挂载);Fiber 状态改按命名常量镜像映射(跨包 const enum 无法在 verbatimModuleSyntax 下引用,同官方处理);`pnpm` 命令超时改为调用方显式传入;安装说明补充 commit 固定建议
- **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](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)**

```bash
dsh plugin --profile web add github:jackxiao-hub/dsh-plugin-tree
```

> Pin the commit for reproducible installs: `github:jackxiao-hub/dsh-plugin-tree#<commit-sha>`. Unpinned installs follow whatever the repo's latest push contains.

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)**

1. Clone this repo to any local directory, e.g. `C:\dev\dsh-plugin-tree`
2. In the profile's `package.json`:

```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"] }
  }
}
```

3. `pnpm install`, then **restart `dsh web`**.

> The profile's `package.json` (dependency + `dsh.profile.bundles` stack) is maintained by the `dsh plugin` command; hand-editing is a pre-publish dev shortcut only — use Method A/B once published.

> 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-package `package.json` (tree building), profile manifest (provenance)
- Writes: rewrites the profile's `cordis.patch.yml` on toggle (only the target `{id, disabled}` row; comments and other content preserved)
- Subprocesses: `pnpm outdated` / `pnpm add` (talks to the configured npm registry, respects `.npmrc` mirrors)
- Never reads credentials; registers no prompts/tools/messages and never touches model request paths (no KV-cache impact)

### Uninstall

1. Remove `@dsh-external/dsh-client-ui-plugin-tree` from the profile `package.json` (dependency + `dsh.profile.bundles` row; for method A/B use `dsh plugin --profile web remove <spec>`)
2. 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 web` and 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 add` only touches disk; the running loader keeps the old modules until `dsh web` restarts.
- **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**: **Packaging fixes** — removed the dangling `./remote` export (no matching artifact), shipped the `lib/invariant.js` invariant companion (NOT auto-mounted from the bundle: an entry waiting for the `invariants` service aborts web boot — compositions mount it explicitly); Fiber states now map through a named-constant runtime mirror (cross-package const enums are unreachable under verbatimModuleSyntax, same stance as the official packages); pnpm command timeouts are passed explicitly by callers; install docs recommend pinning the commit
- **2026-08**: **Duplicate names resolved by unique entry id** — `deps/dependents` carry `entryId`; 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](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

Install

dsh plugin --profile web add github:jackxiao-hub/dsh-plugin-tree

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source