Skip to content
dsh.fish
Bundle

dsh-plugin-visual-composer

Visual Cordis plugin-tree composer for the DeepSeek Harness Web UI.

Source
VanillaCreamer
stars
3 stars
License
MIT
Updated
Updated 14 hours ago

Readme

# DSH Visual Composer

<p align="center">
  <strong>DeepSeek Harness 的可视化 Cordis 插件树编排器</strong>
</p>

<p align="center">
  <img alt="DeepSeek Harness" src="https://img.shields.io/badge/DeepSeek%20Harness-0.1.0--rc.6-4F7CFF">
  <img alt="Node.js" src="https://img.shields.io/badge/Node.js-%5E22.19%20%7C%7C%20%3E%3D24-339933">
  <img alt="License" src="https://img.shields.io/badge/License-MIT-blue.svg">
  <img alt="Status" src="https://img.shields.io/badge/Status-Prototype-orange">
</p>

DSH Visual Composer 是一个运行在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Web 界面中的社区插件。它把当前 Profile 的 Cordis 插件树转换成可视化画布,让你查看插件、添加插件或 Group、拖拽 Composer 管理的节点、编辑配置覆盖,并在保存前审阅脱敏后的 YAML Diff。

> [!IMPORTANT]
> 本项目是独立社区原型,不是 DeepSeek AI 官方插件。DeepSeek Harness 目前仍处于 Developer Preview,插件接口可能在后续 RC 版本中变化。

![Visual Composer 运行在 DSH Web 中](./demo.png)

## 目录

- [为什么需要它](#为什么需要它)
- [核心能力](#核心能力)
- [兼容性与前置条件](#兼容性与前置条件)
- [安装](#安装)
- [快速开始](#快速开始)
- [界面与操作](#界面与操作)
- [Cordis 编辑语义](#cordis-编辑语义)
- [保存、热更新与回滚](#保存热更新与回滚)
- [安全模型](#安全模型)
- [架构](#架构)
- [开发与测试](#开发与测试)
- [常见问题](#常见问题)
- [已知限制](#已知限制)
- [路线图](#路线图)
- [参与贡献](#参与贡献)
- [许可证](#许可证)

## 为什么需要它

DeepSeek Harness 采用“万物皆插件”的 Cordis 架构,但 Profile 的最终结构通常由 Bundle、`cordis.patch.yml`、Group 嵌套和运行时状态共同决定。只阅读 YAML 很难快速回答以下问题:

- 当前实际加载了哪些插件?
- 插件位于哪个 Group 中?
- 哪些节点处于 active、failed、disabled 等状态?
- 某个插件注入或依赖了哪些 Service?
- 一次配置覆盖最终会生成怎样的 Patch?
- 修改失败后能否安全恢复?

Visual Composer 将这些信息集中到 DSH Web 的插件设置页中,同时严格遵循 Cordis Patch 的真实语义,不把插件树伪装成任意连线的工作流引擎。

## 核心能力

- 读取当前 DSH Web Profile 的真实 Loader 树。
- 展示嵌套 Group、插件状态、模块名、Entry ID、注入信息与配置。
- 从左侧 Palette 添加插件或 Group 草稿。
- 将 Composer 管理的绿色节点拖入 Root 或任意 Group。
- 为现有 Entry 创建 `disabled` 和完整 `config` 覆盖。
- 按 ID、模块名或 Label 过滤插件树。
- 保存前展示脱敏后的 Composer 管理块 Diff。
- 使用预览签名保证“审阅的草稿”和“实际写入的草稿”一致。
- 仅维护 `cordis.patch.yml` 中有明确标记的区域,保留其他文本与注释。
- 通过乐观 Revision、防并发覆盖和原子替换写入配置。
- HMR 可用时等待根 Include 事务真正提交,再报告成功。
- HMR 拒绝或超时时自动恢复修改前文件。
- 自动创建轮换备份,并支持在 Web UI 中一键回滚最近备份。
- 对凭据、认证字段、`!!js` 表达式及敏感配置进行脱敏和编辑保护。

## 兼容性与前置条件

| 项目 | 当前验证版本 |
| --- | --- |
| DeepSeek Harness | `0.1.0-rc.6` |
| Node.js | `^22.19.0` 或 `>=24.0.0` |
| UI | DSH Web Profile |
| 操作系统 | 已在 macOS 验证;实现使用跨平台 Node.js API |

使用前请确保:

1. `dsh` 命令可以正常执行;
2. 已存在或允许初始化 `web` Profile;
3. DSH Web 通过本机回环地址访问,例如 `http://127.0.0.1:4632`;
4. 需要加入画布的第三方插件已经安装到同一个 Profile。

## 安装

### 方式一:安装 Release 中的预构建 tarball(推荐)

从本仓库的 **Releases** 页面下载:

```text
dsh-plugin-visual-composer-0.1.0.tgz
```

然后安装到 Web Profile:

```bash
dsh plugin --profile web add ./dsh-plugin-visual-composer-0.1.0.tgz
```

启动 DSH Web:

```bash
dsh --profile web
```

预构建 tarball 已包含 Host 和 Client 产物,安装时不需要在本机执行本项目的构建脚本。

### 方式二:从源码构建

```bash
git clone https://github.com/VanillaCreamer/dsh-plugin-visual-composer.git
cd dsh-plugin-visual-composer
npm ci
npm run pack
```

构建成功后,当前目录会生成:

```text
dsh-plugin-visual-composer-0.1.0.tgz
```

安装并启动:

```bash
dsh plugin --profile web add ./dsh-plugin-visual-composer-0.1.0.tgz
dsh --profile web
```

### 从 DeepSeek Harness 源码仓库运行

如果使用的是 DeepSeek Harness 源码 checkout,请在相应工作目录中将 `dsh` 替换为 `pnpm dsh`:

```bash
pnpm dsh plugin --profile web add /绝对路径/dsh-plugin-visual-composer-0.1.0.tgz
pnpm dsh --profile web
```

### 卸载

```bash
dsh plugin --profile web remove dsh-plugin-visual-composer
```

卸载插件不会主动删除其历史备份,也不会移除已经写入 `cordis.patch.yml` 的 Composer 管理块。建议卸载前先在界面中清除不再需要的草稿和覆盖。

## 快速开始

1. 启动 DSH Web;
2. 使用浏览器打开终端中显示的本机地址;
3. 进入 **设置 → 插件 → Visual Composer**;
4. 在左侧输入已经安装的模块名,或添加一个 Group;
5. 将绿色草稿节点拖到 Root 或目标 Group;
6. 点击节点,在右侧 Inspector 中调整禁用状态或 JSON 配置;
7. 点击右上角 **预览变更**;
8. 阅读 YAML Diff 与警告;
9. 点击 **确认并保存**;
10. HMR 可用时等待界面报告事务提交成功。

建议第一次使用时先添加一个空 Group,以熟悉预览、保存和回滚流程。

## 界面与操作

### Plugin Palette

左侧区域用于创建草稿节点:

- **模块名**:npm 包名或 Profile 内可解析的相对模块,例如 `@scope/plugin`、`./local-plugin.mjs`;
- **Entry ID**:可选;留空时自动生成唯一 ID;
- **添加插件**:创建普通插件草稿;
- **添加 Group**:创建 `cordis:group` 草稿;
- **过滤插件树**:按 ID、模块名或 Label 查找节点。

> Visual Composer 不负责下载或安装第三方代码。模块必须先安装到当前 Profile,否则预览会被服务端拒绝。

安装插件包示例:

```bash
dsh plugin --profile web add <包名或本地路径>
```

安装完成后重新打开或刷新 Visual Composer,再添加对应模块 Entry。

### Effective Cordis Tree

中间画布显示当前运行时插件树:

- 绿色节点:由 Visual Composer 管理的草稿节点,可拖拽;
- 普通节点:来自 Bundle 或现有 Profile 配置,只能创建覆盖;
- Group:可接收 Composer 管理的拖拽节点;
- CORE:关键基础节点,受到默认保护;
- 状态标记:显示 `pending`、`loading`、`active`、`failed`、`unloading` 或 `inactive`。

拖拽行为:

- 拖到画布 Root:移动到根级别;
- 拖到 Group:成为该 Group 的子节点;
- 不允许把 Group 拖入自身或其后代;
- 删除草稿 Group 时,会递归删除其 Composer 管理的后代。

### Inspector

选中节点后,右侧 Inspector 可以:

- 启用或禁用节点;
- 编辑完整 JSON `config`;
- 应用或清除现有节点覆盖;
- 删除 Composer 草稿节点。

如果配置包含密钥、Token、认证字段、`!!js` 表达式或其他被判定为敏感的值,该配置不会发送到浏览器,也不能在 Inspector 中替换。

### YAML Change Preview

点击 **预览变更** 后,右侧会显示:

- Override 数量;
- Insert 数量;
- Disabled 数量;
- 校验警告;
- 脱敏后的 Composer 管理块 Diff。

预览不会返回完整 `cordis.patch.yml`,也不会向浏览器暴露管理块之外的用户配置。

## Cordis 编辑语义

### 现有节点为什么不能拖动?

Cordis Patch 可以按 ID 覆盖、禁用或插入 Entry,但不能任意移动 Bundle 已经定义的 Entry。Visual Composer 因此只允许拖动自身管理的 Insert 节点,不会制造无法落盘的“伪排序”。

### `config` 是完整替换,不是深度合并

例如运行时配置为:

```json
{
  "timeout": 30000,
  "retry": 3
}
```

如果在 Inspector 中保存:

```json
{
  "timeout": 10000
}
```

最终覆盖不会自动保留 `retry`。请在提交前确认完整配置。

### Group 与 Insert

Visual Composer 将新节点转换为 Patch `insert`:

```yaml
- id: tools
  insert:
    - id: my-tool
      name: my-tool-package
      config: {}
```

根级节点则生成没有父 ID 的 `insert` Patch。

### Composer 管理块

插件只管理以下标记之间的内容:

```yaml
# >>> dsh-visual-composer managed block
- id: some-plugin
  name: package-name
  disabled: true
# <<< dsh-visual-composer managed block
```

标记之外的用户文本、注释、未知字段和 `!!js` 表达式保持原样。标记只会在 YAML 顶层整行出现时被识别;多行字符串中的同名文本不会被误判为管理块。

## 保存、热更新与回滚

### 保存流程

一次正式保存会经历:

1. 校验浏览器 Revision;
2. 恢复仅保留在 Host 内的敏感配置;
3. 验证 Entry ID、父子关系和 Group 拓扑;
4. 验证插件模块能在当前 Profile 内安全解析;
5. 生成脱敏 Diff 与预览签名;
6. 要求 Apply 请求携带同一草稿的预览签名;
7. 再次比较磁盘原文,防止检查与写入之间发生并发覆盖;
8. 创建修改前备份;
9. 使用同目录临时文件原子替换 `cordis.patch.yml`;
10. 等待根 Include 的提交后生命周期事件;
11. 检查实际 Loader 树是否与草稿一致;
12. 失败或超时时恢复原文件。

### HMR 行为

- **HMR 开启**:保存成功只会在 Include 事务提交并且运行树匹配后返回;
- **HMR 拒绝**:返回错误,并自动恢复修改前文件;
- **HMR 超时**:视为失败并恢复;
- **HMR 关闭**:Patch 会持久化,但需要重启 DSH 才能生效,界面会明确提示。

### 备份目录

备份默认保存在当前 Profile 下:

```text
$DSH_HOME/profiles/<profile>/.dsh-visual-composer/backups/
```

插件保留最近的轮换备份。点击 **回滚最近备份** 时:

1. 当前 Patch 会先再次备份;
2. 恢复最近一份有效备份;
3. HMR 可用时等待事务确认;
4. 回滚本身失败时恢复当前文件。

## 安全模型

Visual Composer 可以修改运行中的插件树,因此它被设计为一个**仅限本机的高权限配置界面**。

### 网络边界

API 同时要求:

- TCP 对端必须是 loopback;
- Host 必须是 `localhost`、`127.0.0.0/8` 或 `[::1]`;
- Origin 必须与当前本机 Authority 一致;
- 拒绝跨站 Fetch Metadata;
- POST 必须携带进程内 CSRF Token;
- 请求体具有严格大小上限。

即使 DSH Web 配置了 LAN `trustedHosts`,远程设备也不能访问 Visual Composer API。

### 文件边界

- Patch 路径固定为当前 Profile 的 `cordis.patch.yml`;
- 拒绝 Patch 文件符号链接和非普通文件;
- 备份目录经过 `realpath` containment 检查;
- 备份文件名受严格白名单限制;
- 模块 URL、绝对路径和逃逸 Profile 的相对路径会被拒绝;
- 写入采用同目录临时文件和原子替换。

### 敏感数据保护

以下内容不会直接下发到浏览器:

- API Key、Token、Secret、Password;
- Authorization、Cookie、Credential;
- Private/Signing/Encryption Key;
- DSN、认证 URL 和常见密钥形态;
- `!!js` 表达式;
- HMR 底层原始异常文本。

敏感值检测属于纵深防御,不应替代正确的密钥管理。仍建议通过环境变量或 DSH 支持的安全机制注入凭据,不要把明文秘密写入普通配置。

### 默认保护节点

以下 Entry 默认不能通过 Visual Composer 禁用:

- `visual-composer`;
- `webserver`、`web-runtime`、`modules`、`connection`;
- `client-runtime`、`client-hmr`;
- `ui-layout`、`ui-sidebar`、`ui-settings`;
- `api-gateway`、`api-remotes`、`timer`、`hmr`、`include`。

这是为了避免用户从界面中卸载 Web Shell、配置 Loader 或 Visual Composer 自身。

Host 插件配置还支持额外的 `protectedIds`:

```yaml
- id: visual-composer
  name: dsh-plugin-visual-composer
  config:
    protectedIds:
      - my-critical-plugin
```

## 架构

```text
DSH Web Browser
  └─ lib/client.js
       ├─ settings.plugins.tab
       ├─ Cordis Tree / Palette / Inspector
       └─ Preview / Apply / Rollback
              │ local-only HTTP API
              ▼
DSH Host
  └─ lib/index.js
       ├─ Loader tree projection
       ├─ Draft validation
       ├─ Secret redaction
       ├─ Patch composition
       ├─ Atomic persistence
       ├─ Backup rotation
       └─ HMR transaction confirmation
              │
              ▼
$DSH_HOME/profiles/<profile>/cordis.patch.yml
```

包中包含两个构建入口:

- `lib/index.js`:Host API、Loader 投影、校验、持久化、备份与 HMR 确认;
- `lib/client.js`:注册到 `settings.plugins.tab` 的 React Client 插件。

项目结构:

```text
.
├── src/
│   ├── index.ts              # Host 插件与本机 API
│   ├── patch.ts              # 管理块、校验、序列化与 Diff
│   ├── types.ts              # Host/Client 共享类型
│   └── client/
│       └── index.tsx         # Web UI
├── test/
│   └── patch.test.ts         # Patch 与安全边界测试
├── cordis.patch.yml          # 安装时注入 Visual Composer
├── esbuild.mjs               # Host/Client 双入口构建
├── package.json
└── README.md
```

## 开发与测试

安装依赖:

```bash
npm ci
```

常用命令:

```bash
npm run check       # TypeScript 严格类型检查
npm test            # Vitest 单元测试
npm run build       # 构建 Host、Client 和类型声明
npm run pack:check  # 完整检查并执行 npm pack --dry-run
npm run pack        # 完整检查并生成 tarball
```

本地完整验证:

```bash
npm run check
npm test
npm run build
npm run pack:check
```

安装刚构建的版本:

```bash
dsh plugin --profile web remove dsh-plugin-visual-composer
dsh plugin --profile web add ./dsh-plugin-visual-composer-0.1.0.tgz
dsh --profile web
```

建议使用专门的测试 Profile,不要直接对重要工作 Profile 进行开发调试。

## 常见问题

### 设置页中没有 Visual Composer

依次检查:

```bash
dsh plugin --profile web why dsh-plugin-visual-composer
dsh --profile web --dump-config
```

确认:

- 插件安装在启动时使用的同一个 Profile;
- `dsh.profile.bundles` 中包含本插件;
- DSH Web 已重启;
- 浏览器没有缓存旧的 Client Module。

### 添加插件时提示模块未安装

Visual Composer 只编排已存在的代码。先安装目标插件:

```bash
dsh plugin --profile web add <目标插件包>
```

然后刷新 Composer。

### 保存后没有立即生效

查看页面顶部是否提示 HMR 不可用。如果 HMR 被禁用,需要重启:

```bash
dsh --profile web
```

### 提示 Revision Conflict

磁盘上的 `cordis.patch.yml` 在页面加载后发生了变化。请刷新 Composer,重新检查草稿和 Diff,再保存。

### 配置编辑器是只读的

该节点的配置包含被脱敏的字段或表达式。Visual Composer 会将真实值保留在 Host 内,但不会允许浏览器替换整段配置。请直接使用本地编辑器修改对应配置。

### 无法拖动已有节点

这是 Cordis Patch 的语义限制,不是前端缺陷。已有 Bundle Entry 只能覆盖或禁用,不能通过 Patch 任意移动。只有 Composer 管理的绿色 Insert 节点可以拖动。

### 回滚按钮提示没有备份

只有成功进入正式保存流程后才会产生备份。尚未保存过时没有可回滚内容。

## 已知限制

- 当前仅验证 DeepSeek Harness `0.1.0-rc.6`;后续 RC 可能需要适配。
- 仅允许本机浏览器访问,不支持远程管理和多人协作。
- 不提供插件市场、下载或版本管理能力。
- 不支持移动 Bundle 定义的现有 Entry。
- `config` 使用完整替换语义,不提供深度合并。
- 目前配置编辑器使用 JSON,不会根据插件 Schema 自动生成表单。
- 被脱敏的配置只能在本地文件中编辑。
- 当前 Diff 聚焦 Composer 管理块,不展示整个用户 Patch。
- 跨平台实现尚未在 Windows 和 Linux 上完成完整端到端验收。

## 路线图

可能的后续方向:

- 基于插件 Schema 生成类型安全配置表单;
- 只读展示 Service provide/inject 依赖图;
- 增加备份历史选择和命名快照;
- 增加 Patch 导入、导出和更完整的冲突可视化;
- 为 Linux、Windows 建立端到端测试矩阵;
- 适配 DeepSeek Harness 后续公开版本;
- 增加英文文档和演示视频。

依赖图应由运行时 Service 信息自动推导,而不是允许用户随意连线;插件依赖与工作流边不是同一个概念。

## 参与贡献

欢迎通过 GitHub Issues 提交:

- 可复现的错误报告;
- 不同系统和 DSH 版本的兼容性结果;
- Cordis Patch 边界案例;
- UI/UX 建议;
- 安全问题之外的功能提案。

提交代码前请运行:

```bash
npm run check
npm test
npm run build
npm run pack:check
```

报告问题时建议附上:

- 操作系统与 Node.js 版本;
- DeepSeek Harness 版本;
- 插件版本;
- 使用的 Profile 名称;
- 脱敏后的错误信息和复现步骤。

请勿在公开 Issue 中提交 API Key、Token、Cookie、完整私有配置或未经脱敏的 `cordis.patch.yml`。

## 许可证

本项目基于 [MIT License](./LICENSE) 发布。

DeepSeek、DeepSeek Harness 及相关标识属于其各自权利人。本项目与 DeepSeek AI 没有官方隶属、授权或背书关系。

Install

dsh plugin --profile web add github:VanillaCreamer/dsh-plugin-visual-composer

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