DeepSeek Harness Hub
← 返回列表

远程沙箱执行weijiafu14/dsh-remote-sandbox

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

把文件与命令执行迁到 E2B 沙箱,崩溃后自动恢复并同步工作区

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/14 · 已提供中文文档

DeepSeek Harness 的崩溃恢复型远程执行环境:在 E2B 沙箱上通过 ctx.fs/ctx.subprocess 实现,具备心跳保活、透明恢复和工作区同步。

综合分
26.6
GitHub 分
26.6
用户评分
★ Stars
0
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add weijiafu14/dsh-remote-sandbox
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-remote-sandbox

面向 DeepSeek Harness(dsh)的生产级远程执行世界:将 ctx.fs 和 ctx.subprocess 迁移到 E2B 沙箱中,使其能在崩溃后存活、在高负载下保持运行,并让你的工作区保持同步——这些正是官方 @deepseek-ai/dsh-e2b 概念验证明确遗漏的部分。

第三方插件套件。与 DeepSeek 无关联。MIT 许可。

为什么

dsh 的能力接缝让一次 provider 替换就能把整个执行世界迁移到远程沙箱——Bash、PTY 和 LSP 会跟随 ctx.fs/ctx.subprocess,无需分叉。官方 dsh-e2b 包证明了该接缝可行,但按其自身 README 所述,它只是一个 POC:沙箱“被刻意设计为临时性的”,五分钟后即销毁,将进程的完整输出保留在宿主机内存中,并且“既不上传也不同步宿主机工作区”。本套件让该执行世界可用于真实工作。

| | 官方 dsh-e2b(POC) | dsh-remote-sandbox |
|---|---|---|
| 沙箱生命周期 | 固定 5 分钟,然后删除 | 心跳保活,与任务同生命周期 |
| 连接断开 / 暂停 | 无——沙箱死亡即任务死亡 | 透明恢复:恢复已暂停的沙箱(磁盘保留) |
| 硬崩溃 | 无 | 重新创建 + 从上次同步的快照恢复工作区 |
| 宿主机工作区 | 不上传也不同步(仅路径拼写镜像) | 打开时 tar IN,请求/拆除时 tar OUT,独立于 .gitignore 的排除规则 |
| 进程输出内存 | 完整流保留在宿主机内存中(POC 承认这破坏了接缝的边界) | 有界的内存尾部 + 可选的宿主机溢出文件——宿主机内存有上限 |
| 每次 fs 操作的往返次数 | 每次变更需 3–8 次 SDK 命令(realpath、stage、rename、xattr……) | 一次——sidecar 在沙箱内以原子方式完成读-改-发布 |
| glob/grep(tool-fs-search) | 在远程世界中损坏(见下文) | 可用——ripgrep 随 sidecar 一起提供 |
| 自定义同步后端 | 不适用 | syncIn/syncOut 可通过 cordis.yml(!!js)覆盖 |

架构

宿主机(dsh 进程)                          沙箱(E2B)
┌───────────────────────────┐               ┌──────────────────────────┐
│ agent 循环、LLM 密钥、     │               │ sidecar(单个纯 JS        │
│ 会话、工具                 │               │ 打包,无原生依赖)         │
│                           │  一个 WSS     │  ├─ fs 原语                │
│ dsh-fs-remote  ───────────┼──────────────►│  ├─ 进程树                 │
│ dsh-subprocess-remote ────┤  结构化       │  └─ ripgrep                │
│ dsh-sandbox-keeper        │  协议         │                            │
│  ├─ E2B 生命周期          │               │ 工作区 ◄─ tar IN/OUT       │
│  ├─ 心跳 / 恢复           │               └──────────────────────────┘
│  └─ tar 同步              │
└───────────────────────────┘
- sidecar 是一个约 160 KB 的纯 JavaScript 文件(内联了 WebSocket 服务器,没有原生绑定)。keeper 将其上传,并用沙箱自带的 Node 运行它。它在本地执行原语,因此一次文件系统变更只需一次往返,而不是一连串 SDK shell 命令。
- keeper 拥有沙箱:它部署 sidecar,向前推进暂停截止时间以保持沙箱存活,并在连接断开时恢复已暂停的沙箱(磁盘,以及通过 E2B 的内存快照保留的 sidecar 本身),或者——仅当沙箱确实已消失时——重新创建它并恢复工作区。LLM 和 git 凭据永远不会进入沙箱。
- providers 是轻量适配器:每次 ctx.fs/ctx.subprocess 调用都通过 keeper 推导出当前的 sidecar 客户端,因此恢复操作会在 provider 毫无察觉的情况下在底层替换连接。

安装

dsh plugin --profile  add dsh-remote-sandbox
export E2B_API_KEY=e2b_...     # get one at https://e2b.dev/dashboard

dsh-remote-sandbox 包叠加在 dsh-base 之上:它禁用本地的 subprocess 和 fs-sandbox provider,并插入 keeper 以及远程 provider。Bash、terminal 和 LSP 在它们之上保持不变地组合。

若要改为手动接线,请在 cordis.yml 中禁用 dsh-subprocess-local 和 dsh-fs-sandbox,并插入:

- id: sandbox-keeper
name: dsh-sandbox-keeper
config:
cwd: /home/user/workspace          # workspace path inside the sandbox
hostWorkspace: !!js process.cwd()  # local project synced in/out
- id: subprocess-remote
name: dsh-subprocess-remote
- id: fs-remote
name: dsh-fs-remote

配置(dsh-sandbox-keeper)

| 键 | 默认值 | 含义 |
|---|---|---|
| apiKey | $E2B_API_KEY | E2B API 密钥;绝不会转发到沙箱中 |
| template | E2B 基础镜像 | E2B 模板 id(基础镜像自带 Node) |
| cwd | /home/user/workspace | 沙箱内的工作区路径 |
| hostWorkspace | process.cwd() | 主机项目,在打开时同步进去,在请求/拆除时同步出来 |
| timeoutMs | 300000 | 暂停截止时间;心跳会将其向前推进 |
| heartbeatMs | 30000 | 保活与存活检测间隔 |
| excludes | node_modules、.pnpm-store、.dsh-remote-sidecar | 永不同步的路径段(.git 会被同步) |
| pauseOnDispose | true | 拆除时暂停(保留磁盘)而非杀死 |
| syncIn / syncOut | 通过 sidecar 的 tar | 用你自己的函数(!!js)覆盖,用于 git、对象存储、PVC 等 |

此方案绕过的两个上游 bug

在针对 deepseek-harness@0.1.0-rc.6 构建时发现:
1. tool-fs-search 硬编码了宿主机的 ripgrep 路径。 runRipgrep 将 resolveRgPath() —— 宿主机 @vscode/ripgrep 二进制的绝对路径 —— 作为 argv[0] 启动,而没有经过 resolveExecutable。该插件位于随附的 dsh-base 包中,但任何远程执行环境都缺少该宿主机路径,因此 glob/grep 在每次调用时都会失败。官方的 e2b 示例通过不挂载该插件来规避此问题。本套件将 ripgrep 与 sidecar 一起发布,因此该工具可以正常工作。
2. 沙箱权限模式没有远程语义。 dsh-fs-sandbox 扩展了 LocalFileSystem,并且 writableRoots() 混入了宿主机的 /tmp/os.tmpdir(),因此 read-only 和 workspace-write 在远程环境中会静默地不生效 —— e2b 示例被迫硬编码为 danger-full-access。sidecar 会针对沙箱自身的路径自行强制执行该模式。

已知限制与推迟的工作

- 终端(spawnTerminal)是实验性的,尚未被测试覆盖。 远程沙箱面向非交互式 agent 工作 —— 读/写/编辑、构建、测试、grep —— 这些从不需要 pty;该路径已得到充分测试。交互式终端是罕见情况,因此 spawnTerminal 以尽力而为的方式发布:它运行在 E2B 原生 pty 之上(输出、输入、调整大小和终止都是真实的),但该 API 不暴露前台进程组或输入等待的事实,因此 inspectForeground 报告会话 pid 和 inputWaiting: false,并且尚无测试覆盖它。计划中的重构: 通过预构建的 node-pty 将 pty 移入 sidecar,使其拥有真正的前台进程组(tcgetpgrp)和输入等待检测 —— 与本地终端完全对等,并且它将 pty 带到与其他所有内容相同的 sidecar 通道上。如果你的部署不打开交互式终端,这不会影响你。
- 恢复在断连前后的时刻是至少一次的。 在崩溃前几秒内发出的文件写入或命令在恢复后可能尚未生效;keeper 会注入一条模型可见的通知(通过 notify / consumeRecoveryNotice()),以便 agent 重新检查目录树。
- OUT 同步按设计是低频的。 恢复首先依赖暂停沙箱保留的磁盘;tar 快照是针对真正被删除的沙箱的兜底方案,因此没有每次写入的同步开销。如果你的部署需要,可以通过自定义 syncOut 启用周期性 OUT。
- 上游为预发布版本。 dsh 处于开发者预览阶段,不承诺兼容性;peer 版本被宽松地固定,随着 harness 的演进可能需要升级。

开发

pnpm install
pnpm -r run build          # tsc + esbuild the sidecar bundle
pnpm test                  # 37 unit + provider tests (no sandbox needed)
E2B_API_KEY=... pnpm test:e2e   # 6 real-E2B killer scenarios
单元测试套件会将真实的 sidecar 包作为本地进程启动,并驱动线协议、通过真实的 dsh FileSystem/SubprocessRuntime 基类驱动各 provider,以及针对假后端驱动 keeper 的生命周期/恢复/同步。E2E 套件会针对真实的 E2B 沙箱运行六个场景——保活、恢复、重建、有界 grep、tar 往返、自定义同步。

包

| 包 | 角色 |
|---|---|
| dsh-remote-protocol | sidecar 与宿主共享的线协议 + 编解码器 |
| dsh-remote-sidecar | 沙箱内执行器(单个打包文件) |
| dsh-sandbox-keeper | ctx.remoteSandbox:E2B 生命周期、心跳、恢复、同步 |
| dsh-fs-remote | ctx.fs provider |
| dsh-subprocess-remote | ctx.subprocess provider |
| dsh-remote-sandbox | 在 dsh-base 上串联以上三者的单行 bundle |

许可证

MIT

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

同作者(weijiafu14)的其他插件

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群