KevinWen7415
dsh-virtual-workspace
Virtual Workspaces for DeepSeek Harness: a dynamic Cordis Plugin that groups multiple project directories under one name for cross-project read/search/write, with native sidebar integration and sandbox-consistent escalation.
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 14, 2026
- Updated
- Aug 14, 2026
Introduction
dsh-virtual-workspace
📖 English | 简体中文
Virtual Workspaces for DeepSeek Harness (DSH) — 一个动态 Cordis 插件,让 agent 可以跨多个项目目录同时读取、搜索和修改代码与文件。
English blurb: A dynamic Cordis Plugin that groups several project directories into named virtual workspaces the agent can read, search and modify together, with sidebar UI, built-in workspace-list mirroring, and sandbox-consistent write escalation.
✨ 特性
- 虚拟工作区:
名字 → 多个项目目录的映射组,一次定义、处处可用。 - agent 工具
vws(13 个动作):list / add / remove / add-dir / remove-dir / set-mirror / resolve / read / write / edit / ls / find / grep,支持名字:/相对路径语法,文件操作取首个命中、目录操作取并集。 - 内置侧边栏集成:接管侧边栏头部 + 添加工作区按钮,点击后向下弹出抽屉——既可用系统对话框创建普通工作区(原生行为),也可多选目录联立虚拟工作区,并在抽屉里管理既有工作区。
- 镜像到官方列表:成员目录自动注册为内置工作区条目(标题
工作区名 · 目录名),出现在侧边栏会话/工作区列表中;只清理自己创建的条目(所有权跟踪)。 - 沙箱一致:读取不受限;写入/编辑遵循调用会话的沙箱边界,越界被拒后可一次性审批升级(与内置 write 工具同款
sandbox_permissions + justification机制)。 - 全局感知:工具与提示段注册在根上下文,任何会话(包括在镜像目录下新建的会话)的 agent 都能调用
vws并看到工作区清单。 - 多语言:界面支持简体中文(zh)与英文(en);界面语言为 zh 时显示中文,其余语言一律回退英文;语言切换即时生效。
- 持久化:定义保存于
<部署工作区根>/.vws-workspaces.json,重启后自动恢复。
📷 截图
1. 点击 + 弹出的抽屉面板
2. 内置侧边栏中的镜像条目
3. 系统文件夹选择对话框
4. 对话中 agent 使用 vws 跨目录工作

📦 官方安装(bundle,永久内置)
本仓库同时是官方 bundle 格式的插件包(package.json 声明 dsh.bundle → cordis.patch.yml + index.js),可从 GitHub 直接安装并随 profile 永久启动:
dsh plugin --profile <name> add github:KevinWen7415/dsh-virtual-workspace
dsh --profile <name>
- 本包为纯 JavaScript、无构建步骤,因此不需要官方文档中 TypeScript 包所需的 pnpm
allowBuilds审批; - 卸载:
dsh plugin --profile <name> remove dsh-virtual-workspace; - bundle 同时携带 Host 与 Client:
vws工具、系统提示段、镜像注册、状态持久化、沙箱升级,以及侧边栏 + 抽屉面板 UI(v1.2.0 起,经dsh.client+ 同源/api/vws路由通信)——与动态版功能对齐; - 与动态安装对比:bundle 安装进程重启后自动加载,不依赖任何会话。
🚀 安装教程(动态插件方式)
本插件是动态 Cordis 插件:运行在 DSH 进程内,通过内置的 cordis_* 工具定义与激活,无需构建。
0. 前置条件
- 已部署并运行 DeepSeek Harness(DSH),能打开 Web 界面(如
http://127.0.0.1:3080); - 至少有一个可用会话;
- 能访问 GitHub(推荐);否则先在本地 clone:
git clone https://github.com/KevinWen7415/dsh-virtual-workspace。
1. 准备代码
源码位于:https://github.com/KevinWen7415/dsh-virtual-workspace(公开仓库,无需 clone 即可由 agent 直接读取)。
src/host.js 与 src/client.js 各是一个 export default function () { … };其中 return { … } 的函数体就是要交给 cordis_define 的 code.host / code.client。
2. 安装(推荐:把 GitHub 地址直接给 agent)
打开 DSH 会话,发送一句话:
请从这个仓库自动安装插件:https://github.com/KevinWen7415/dsh-virtual-workspace
(读取 src/host.js 与 src/client.js,用 cordis_define 定义后 cordis_run 激活)
agent 会自行读取两个源文件并完成 cordis_define → cordis_run,然后:
- 页面若出现审批提示(awaiting-approval),点击允许(首次含浏览器 UI 的包需要审批);
- 收到激活成功通知后刷新页面。
若 DSH 所在机器无法访问 GitHub:先在本地
git clone https://github.com/KevinWen7415/dsh-virtual-workspace,再发送「请安装 <本地克隆路径> 这个插件」,后续步骤相同。 安全提示:只安装你信任的仓库。
2′. 安装(手动调用工具)
- 调用
cordis_define:plugin:{ "kind": "new", "idPrefix": "vws" }name/purpose:随意填写,例如Virtual Workspacescode.host:粘贴src/host.js里export default function () {与文件末尾}之间的return { … }整段code.client:同理取src/client.js的函数体
- 记录返回的
pluginId/packageId; - 调用
cordis_run:{ "pluginId": "…", "packageId": "…", "mode": "run" }; - 审批通过、收到成功通知后刷新页面。
3. 验证安装
- 点击侧边栏头部 + → 向下弹出 Virtual Workspaces 抽屉;
- 在抽屉中添加一个工作区(名称 + 每行一个目录)→ 内置侧边栏出现
名字 · 目录镜像条目; - 在对话里说"用
vws list列出虚拟工作区",agent 应返回状态 JSON。
4. 日常使用
- 界面:抽屉里添加/移除工作区、
Sidebar: on/off镜像开关、目录 ×;面板可按住标题栏拖动; - agent:直接说"读
EDB:/src/xxx"、"在 EDB 里搜索 xxx"、"把 EDB 的 xxx 改成 yyy";写入超出会话边界时 agent 会请求升级,你点批准即完成一次性写入。
5. 更新 / 停用 / 卸载
| 操作 | 方式 |
|---|---|
| 更新版本 | 对同一 pluginId 用 cordis_define(kind:"existing")追加新包 → cordis_run mode:"update" |
| 回滚 | cordis_run mode:"run" 指定 currentPackageId |
| 停用(保留定义) | cordis_stop |
| 卸载 | ① 先在抽屉里移除工作区或关闭镜像(清理内置列表中的镜像条目)② cordis_stop ③ cordis_undefine |
6. 常见问题
- 激活报
Failed to fetch:瞬时网络问题,直接重试cordis_run(或刷新页面后重试),无需改代码; - DSH 进程重启后:插件需重新激活(定义仍在,对原
pluginId再cordis_run即可;工作区定义持久化,不丢失); - 卸载后内置列表还有镜像条目:注册记录是持久化的;若卸载前未清理,可在官方侧边栏手动删除这些条目;
- 审批被拒:不会自动重试;需要时再次手动发起
cordis_run; - GitHub 地址安装的条件:仓库
github.com/KevinWen7415/dsh-virtual-workspace为公开仓库;DSH 需能访问 GitHub(否则用本地 clone 路径);首次激活仍需页面审批。
代码约束(平台要求):纯 JavaScript,无
import/require/JSX/TypeScript;Client 一律React.createElement;文件操作必须经ctx.fs服务。详见docs/03-development.md。
提示:动态插件随 DSH 进程存续。如需永久内置、脱离会话生命周期,可将其固化进 host composition(见
docs/02-design.md演进路线)。
📂 仓库结构
dsh-virtual-workspace/
├── README.md # 简体中文说明(本文件)
├── README.en.md # English README
├── LICENSE # MIT
├── package.json # dsh.bundle 清单 + 元信息
├── cordis.patch.yml # bundle 补丁层(官方安装入口)
├── index.js # 静态 Host 插件(bundle 入口,免构建)
├── src/
│ ├── host.js # 动态 Host 半(code.host)
│ └── client.js # 动态 Client 半:内置 + 抽屉面板 UI(code.client)
└── docs/
├── 01-requirements.md # 需求文档(用户反馈、功能/非功能需求、验收)
├── 02-design.md # 设计文档(插槽选型、镜像注册、抽屉设计、跨会话作用域)
├── 03-development.md # 开发文档(代码结构、发布流程、调试、规范)
├── 04-api-reference.md # 接口文档(工具/RPC/状态文件/错误码)
├── 05-testing.md # 测试文档(用例、回归清单、已知限制)
└── images/ # 截图目录(按上表放置)
🧭 核心概念
| 概念 | 说明 |
|---|---|
| 虚拟路径 | 名字:/相对路径:在所有成员目录中解析;文件取首个命中,目录操作取并集 |
| 镜像 | 成员目录注册进内置 workspaceRegistry,标题 名字 · 目录名;插件只删除自己创建的条目 |
| 沙箱 | 读取不受限;写入按会话边界;越界可用 sandbox_permissions 一次性升级(用户审批) |
| 作用域 | 工具与提示段为全局注册——所有会话的 agent 可用 vws |
❓ FAQ
- 为什么虚拟工作区不在内置列表里? 内置列表由
workspaceRegistry驱动且只接受真实存在的目录("虚假目录"被拒绝)。本插件通过镜像注册解决:成员目录以名字 · 目录名出现在官方列表。 - 别的会话能跨工作区改动吗? 能:
vws全局可用、读取不限;写入遵循各会话边界,跨目录写入走一次性审批升级。 - 状态存在哪里?
<部署工作区根>/.vws-workspaces.json(本机示例:C:\Users\<用户>\.vws-workspaces.json)。
📚 版本演进
| 包 | 说明 |
|---|---|
| pkg-1 | 初版:工具/服务/RPC + 设置页 |
| pkg-2 | 写入始终盖上调用会话的沙箱策略(与内置 fs 工具一致) |
| pkg-3 | 移除设置页;侧边栏悬浮按钮 + 管理面板 |
| pkg-4 | 镜像注册进内置侧边栏(开关/所有权跟踪/安全清理) |
| pkg-5 | 撤销悬浮按钮,接管内置 + 流程(单目录原生 + 多目录创建/管理) |
| pkg-6 | 抽屉形态:面板 fixed 定位向下弹出(动画 + 独立滚动),解决槽位高度不足 |
| pkg-7 | 多语言:注册 en/zh 字典;zh 显示简体中文、其余语言回退英文,语言切换即时生效 |
| pkg-8 | 修复:关闭系统目录弹窗后抽屉卡死(picking 不再禁用整个抽屉,Cancel 恒可点,重开重置) |
| pkg-9(动态当前版) | 抽屉可拖动:按住标题栏拖动(元素级指针捕获,无全局监听),grab/grabbing 光标反馈 |
| bundle v1.2.0 | 官方 bundle 格式(Host + Client):dsh plugin add github:KevinWen7415/dsh-virtual-workspace 永久安装,含抽屉 UI |



