Sutera-Diffusus
dsh-sandbox-tester
DSH sandbox tester: process-isolated testing ground for DeepSeek Harness
- Stars
- 1
- Language
- JavaScript
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-sandbox-tester
DSH 沙盒测试器——为 DeepSeek Harness 打造的进程级隔离测试场。
开发者正在面对什么
在 DSH 上开发插件、打补丁、做测试时,你面对的是这样一个现实:所有插件都运行在同一个宿主进程里。改坏一行代码,死循环会卡死整个主进程,未捕获异常会崩掉整个应用;测试脚本一个手滑,误杀进程、误删数据,连聊天记录都可能一起陪葬。然后就是那个熟悉的循环:页面打不开 → 重启 Launcher → 切换间隙报连接失败和 400 → 再重启……改坏一次代码,一晚上就没了。
于是,有了沙盒测试器
把每一次开发/测试改动,先关进一个完全隔离的沙盒实例(独立进程 + 独立数据 + 独立端口)里跑:沙盒里随便崩、随便死循环、随便误操作,最坏的结果也只是沙盒进程自己倒下,本体 3080 全程无恙。改动想回到本体,还必须通过机器强制的合回门禁(目标白名单 + 逐文件语法校验 + bundle 校验 + 备份/回滚清单),带着坏状态偷渡?门都没有。
沙盒里随便作,本体永不翻车。
目录
特性
🧪 进程级隔离沙盒
sandbox_create从本体程序目录复制出独立沙盒(默认裁剪,fullCopy: true全量);- 沙盒 = 独立程序副本 + 全新
DSH_HOME+ 自动分配独立端口(3182 起,冲突自动 +1); - 沙盒由
node bin.js web --port <p>直接拉起,崩溃只死沙盒进程; - 实证:沙盒内注入坏补丁/强杀沙盒进程,本体 3080 全程 HTTP 200。
🛠️ 9 个原生工具
| 工具 | 用途 |
|---|---|
sandbox_list | 列出全部沙盒(状态/端口/年龄/最近报告) |
sandbox_create | 创建沙盒(裁剪或全量复制、指定端口) |
sandbox_inject | 把待测插件/补丁打进沙盒(自动备份 + 回滚清单,路径越界即拒绝) |
sandbox_run | 预检本体 → 拉起沙盒 → 轮询健康 → 可选一键 QA |
sandbox_health | 端口 + HTTP + 关键 bundle 检查,产出报告 |
sandbox_stop | 停止沙盒(进程树校验:永不会误伤 3080) |
sandbox_destroy | 销毁沙盒(需 confirm: true,目录与注册表全清) |
sandbox_merge | 门禁式合回(见下文) |
sandbox_prune | 清理孤儿/超龄沙盒(默认 48h 标记,dryRun 预览) |
🚧 合回门禁(机器强制,不可绕过)
目标白名单(11 个补丁面文件 + 显式新增)→ 逐文件 node --check → bundle 校验 → 备份计划 + 回滚清单 → 默认 dryRun 只校验出报告;真实写入需 DSH_SANDBOX_MERGE_ALLOW=1 且失败即自动回滚。
🌐 一键 QA(真实浏览器)
sandbox_run qa: true 接跑 CDP 9223 驱动的 headless Edge:首页 200、/plugins/dsh-sandbox/client.js 200、设置页真实渲染「测试沙盒」区段、控制台无未捕获异常,产出结构化报告。
⚙️ 设置页管理
DSH 设置 → 测试沙盒:沙盒卡片(状态徽标/报告徽标/端口/年龄/操作按钮)、新建表单、48h 超龄提示、一键清理、合回门禁摘要卡。
架构
设计原则:编排/执行平面分离
dsh-sandbox 遵循编排平面与执行平面分离(orchestration–execution separation)原则:编排平面驻留于本体进程(信任域 T0),只承担调度、校验与生命周期管理;一切不可信的插件与补丁都在执行平面——独立沙盒进程(不可信域 T1)——中运行。两个平面之间唯一的交互通道是受操作系统强制约束的进程边界,不存在任何共享内存或共享数据目录。
分层架构
┌─────────────────────────────── 编排平面(本体进程 · 信任域 T0)───────────────────────────────┐
│ L4 客户端层 client/client.js — 设置页「测试沙盒」区段(卡片管理 / 报告徽标 / 门禁摘要) │
│ │
│ L3 工具层 9 个原生工具:list · create · inject · run · health · stop · destroy · │
│ merge · prune │
│ · 统一参数 schema 校验;merge 为门禁式事务(见隔离不变量 I5) │
│ │
│ L2 服务层 registry — 沙盒注册表(原子写:tmp + rename) │
│ ports — 端口池(探测分配,冲突自动递增,3182 起) │
│ proctree — 进程树管理(终止前反查 3080 归属,含本体即拒绝) │
│ │
│ L1 配置层 settings 命名空间 sandbox(SANDBOX_ROOT / PORT_START / AGE_HOURS) │
├─────────────────────────────────────────────────────────────────────────────────────────────┤
│ ▲ 受控接口:spawn(强制注入独立 env)· taskkill(进程树校验)· HTTP 轮询 · report.json 回传 │
│ │ 信任边界 = 操作系统进程隔离(无共享内存,无共享数据目录) │
├─────────────────────────────────────────────────────────────────────────────────────────────┤
│ 执行平面(沙盒进程 · 不可信域 T1) │
│ 独立程序副本 ─ 独立 DSH_HOME ─ 独立端口(3182+)─ 待测插件 / 补丁 │
│ 故障域 F 完全独立:死循环 / 未捕获异常 / 资源耗尽 / 误操作均被限制在 F 内 │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
隔离不变量(架构正确性判据)
| # | 不变量 | 强制机制 |
|---|---|---|
| I1 | 进程隔离 | 沙盒由 spawn 独立拉起;沙盒崩溃/被强杀,本体进程不受任何影响 |
| I2 | 数据隔离 | 启动时强制注入独立 DSH_HOME;沙盒对本体数据目录零引用 |
| I3 | 端口隔离 | 端口池自动分配(3182 起),与本体 3080、固定副本 3181 永不冲突 |
| I4 | 终止安全 | sandbox_stop 在 taskkill 前反查 3080 监听 PID,目标进程树包含本体即拒绝执行 |
| I5 | 写入门禁 | merge 执行目标白名单 + 逐文件语法判定 + bundle 校验;默认 dryRun 只出报告,真实写入需显式开关且失败自动回滚 |
生命周期状态机
creating ──▶ stopped ⇄ running ──▶ destroyed
│ ▲
└──(48h 未运行或进程已死)──▶ prune 回收
完整的门禁决策树、一键 QA 交互时序与事故对照见 FLOW.md。
安装要求
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows 10 / 11 |
| Node.js | 18+(执行安装脚本需要) |
| DeepSeek Harness | 0.1.0-rc.6 或同系列版本 |
| 磁盘 | 每个沙盒默认裁剪复制约 270 MB(node_modules) |
安装脚本会修改 DSH 安装目录中两处文件(profile manifest、apiproxy 白名单,均先备份),建议安装前关闭 DSH 页面。
安装教程
第 1 步:获取插件
方式 A:下载 Release(推荐):打开 Releases,下载最新版 zip 并解压。
方式 B:克隆仓库
git clone https://github.com/Sutera-Diffusus/dsh-sandbox-tester.git
cd dsh-sandbox-tester
第 2 步:确认 DSH 安装目录
DSH 安装目录通常包含 DeepSeekHarness-Launcher.exe 和 node_modules。可通过启动器配置确认:
Get-Content "D:\Deepseek harness\DeepSeekHarness-Launcher.cfg"
其中 workDir 字段指向安装目录,下文以 <DSH_INSTALL_DIR> 代替(本文示例路径 D:\Deepseek harness 为作者环境,请按实际替换)。脚本会从目标目录的 DeepSeekHarness-Launcher.cfg 自动解析其 DSH_HOME。
第 3 步:执行安装脚本
node install.mjs --target "<DSH_INSTALL_DIR>"
幂等四步接线(重复执行安全):
- bundle 行合入 profile manifest(
dsh-sandbox+file:依赖); - node_modules junction(profile 链接 + 内置包扁平回退);
- apiproxy 设置白名单加
sandbox(先备份.dsh-sandbox-bak); - 客户端插件挂载校验(
/plugins/dsh-sandbox/client.js可达)。
第 4 步:重启 DSH 并验证
- 重启 DSH(服务与页面);
- 打开设置页 → 应出现「测试沙盒」区段;
- 新建会话,让 Agent 调用
sandbox_list→ 9 个工具已注册。
卸载
node install.mjs --target "<DSH_INSTALL_DIR>" --uninstall
使用说明
在会话中使用工具
直接对 Agent 说,例如:
- 「用测试沙盒验证这个补丁:先
sandbox_create,再sandbox_inject打进去,sandbox_run起来,健康检查过了再sandbox_merge」 - 「
sandbox_list看看现在有哪些沙盒,把超龄的清掉」
设置面板
路径:DSH 设置 → 测试沙盒。
| 分组 | 内容 |
|---|---|
| 沙盒卡片 | 名称 / 状态(运行中·已停止·已销毁)/ 最近报告(通过·失败 + 摘录)/ 端口 / 年龄 / 启动·停止·健康检查·销毁 |
| 新建沙盒 | 名称 + 可选端口 + 完整复制开关 |
| 维护 | 48h 超龄标记、一键清理孤儿沙盒、合回门禁摘要 |
合回门禁
sandbox_merge(name, targets, dryRun=true)
├─ ① 目标白名单(11 补丁面 + 显式新增,越界即拒)
├─ ② 逐文件 node --check
├─ ③ bundle 校验
├─ ④ 备份计划 + 回滚清单(不执行)
└─ ⑤ dryRun=true → 只出报告;dryRun=false 需 DSH_SANDBOX_MERGE_ALLOW=1,失败即回滚
合回成功后自动同步 D:\DeepseekHarness_Backup(DSH 启动守卫 bin-guard 的回滚源)。
数据与隐私
- 沙盒注册表写入
D:\ai-temp\dsh-sandbox-registry.json,沙盒实体在D:\DeepseekHarness_Sandboxes\(可在设置中改); - 不读取、不上传任何用户凭据或会话数据;
- 除复制本体程序目录(只读)外,插件不对本体做任何写入;
- 无遥测、无外部网络请求(一键 QA 仅连本机 127.0.0.1)。
项目结构
dsh-sandbox/
├─ lib/
│ ├─ index.js # 宿主插件主入口(服务组装 + 9 工具注册 + settings 命名空间)
│ ├─ registry.js # 沙盒注册表(原子写)与共享常量
│ ├─ ports.js # 端口池(探测 + 自动分配)
│ ├─ proctree.js # 进程树管理(3080 保护 + 拉起/停止/存活判定)
│ ├─ tools-lifecycle.js # list/create/inject/stop/destroy/prune
│ ├─ tools-runhealth.js # run/health
│ └─ merge-gate.js # 合回门禁
├─ client/
│ └─ client.js # 设置页「测试沙盒」区段
├─ test/
│ ├─ smoke.mjs # 单元冒烟(24 项)
│ ├─ e2e.mjs # 端到端对抗(创建→启动→杀进程→坏补丁→销毁,13 项)
│ └─ qa-cdp.mjs # 一键 QA(CDP 9223 真实浏览器,4 项)
├─ skills/dsh-sandbox/ # Agent 技能(SKILL.md)
├─ cordis.patch.yml # bundle 接入(loader entry: test-sandbox)
├─ install.mjs # 安装/卸载(幂等)
├─ DESIGN.md # 设计规格(含评审结论)
├─ FLOW.md # 工作流程图(Mermaid)
├─ LICENSE / README.md / CHANGELOG.md / SECURITY.md / CONTRIBUTING.md
开发与测试
# 单元冒烟(24 项,不启动任何进程)
node test/smoke.mjs
# 端到端对抗(真实复制 270MB 创建沙盒;需本体 3080 在运行以做无损对照)
node test/e2e.mjs
# 一键 QA(需 headless Edge CDP 9223 + 目标实例)
node test/qa-cdp.mjs <port>
开发建议:在独立 DSH 测试副本上开发验证,避免污染主安装;本仓库开发期间遵循的隔离政策见 CONTRIBUTING。
故障排查
| 现象 | 处理 |
|---|---|
副本/本体启动报 duplicate loader entry id: sandbox | 你的组合里混入了旧版 cordis.patch.yml;确认使用 test-sandbox entry(本仓库已修复) |
| 设置页没有「测试沙盒」区段 | 安装后需重启 DSH;确认 apiproxy 白名单含 sandbox(install.mjs 会打印) |
| 沙盒启动失败 | 看沙盒 stderr;首启需完成引导,QA 脚本已自动处理(预置 workspace) |
| 销毁沙盒报错 | confirm 必须为 true;运行中的沙盒先 sandbox_stop |