Files

12 KiB
Raw Permalink Blame History

description, kind
description kind
共享远程沙箱内的 shell 命令与终端:agent 可以在那里运行什么、输出如何处理,以及可以期待什么——面向 E2B 家族的部署方与维护者。 package-reference

@deepseek-ai/dsh-subprocess-e2b

English | 中文

概述

dsh-subprocess-e2b 让 agent(智能体)的 shell 命令与终端在远程沙箱内运行:agent 可以执行 Bash、打开交互式终端并读取其输出,体验与本地执行完全一致,而宿主机器上什么都不会运行。现有的命令、终端与语言服务器功能无需任何改动即可继续工作——不需要 E2B 专用工具。密钥与宿主环境变量绝不会泄漏进沙箱:只有 agent 显式请求的环境条目才会传入。请与 dsh-e2bdsh-fs-e2b 一起使用,让命令、终端与文件共享同一个远程世界。主要代价是远程延迟——每条命令都要经过一段短暂异步初始化,而不是立即启动。

目录


使用本包

当 agent 的 shell 命令与终端应在远程沙箱内而非你的机器上运行时,使用本包。它是 E2B 家族的命令半边:命令、终端与文件共享同一个远程世界。

何时选择

当组合已经使用 E2B 沙箱且希望命令与终端在其中运行时,选择本包。宿主执行请选择本地子进程包。需要立即获得进程 ID 的工具——例如 ACPAgent Client Protocol)子进程后端——无法使用本包。

配置

唯一设置是包检查运行中命令状态的频率;默认值适合大多数部署,调大它可以减少远程请求,代价是退出检测略慢。

字段 默认值 含义
pollMs 20 包检查运行中命令状态的频率(毫秒)

生成的配置目录是每个受支持字段及其 JSDoc 的穷尽式真源。

运行命令

agent 可以在沙箱中按指定的工作目录与环境运行命令,选择输出的交付方式(实时流式、在大小上限内捕获,或路由到应用自身的输出),并在命令卡住时停止它——停止会先礼貌地请求命令退出,短暂宽限期后再强制终止,因此卡住的命令不会残留。非常大的输出可以保存到沙箱中的文件里,供 agent 稍后读取。命令的退出码会正常报告;如果命令运行期间沙箱消失,该命令会被视为已结束而不是报错。

使用终端

agent 可以在沙箱中打开交互式终端、发送输入、读取输出,并向其中运行的程序发送信号——提示符、交互式工具与全屏程序的行为与本地完全一致。scrollback 与就绪检测等终端功能由终端工具提供,无需改动即可工作。

保持环境干净

命令在干净、沙箱原生的环境中运行:宿主变量与形似凭据的值不会被隐式传入,只有 agent 显式请求的条目才会被设置。这使密钥不会进入沙箱。

如果沙箱消失

沙箱是短暂的:如果命令或终端运行期间沙箱被删除——无论是到期、关闭还是被别处移除——受影响的命令会被视为干净地结束。请不要依赖能在沙箱中存续的工作。

默认沙箱镜像自带命令工作所需的运行时与工具:nodebashsetsidpsawktrenvbase64chmodteeheadrmkillidgetent


理解实现

实现细节——点击展开

本节解释提供方背后的设计决策,并指出实现它们的代码位置;可观察行为已在使用本包中完整说明。

设计理念

  • 延后的远程身份。 同步 seam 从不阻塞在网络请求上:句柄异步发布真实进程组 ID,包装层的私有文件是 pid、退出码与 spill 有效性的权威来源。
  • 单一终止阶梯。 终止、回滚与资源释放共享同一条进程组信号路径——先 SIGTERM,再 SIGKILL 加 SDK kill 回退——并把已证明的完全停稳视为最终状态。
  • 环境必须显式。 宿主内容与形似凭据的内容都不会隐式进入沙箱;每个环境值都会被清理,每个 spec.env 条目都是显式选择。

源码地图

文件 职责
src/index.ts 插件入口:E2BSubprocessRuntimeConfig、spawn 与 spawnTerminal、资源释放
src/process.ts E2BSubprocessHandle:远程包装层、发布、终止、输出投影
src/terminal.ts E2BTerminalHandlePTY 分配、会话拆除
src/environment.ts 远程环境探测、清理、序列化
src/output.ts base64 解码器与有界输出读取器
src/remote.ts 共享控制 shell 辅助:选项构造、轮询 tick、进程组信号
src/invariant.ts 不变式伴生插件(无运行时不变式;存活远程句柄是私有的拆除所有权)

远程包装层

引导脚本会从沙箱 PATH 解析自身所需的工具,拒绝任何缺失或不可执行的路径,通过 env -isetsid --wait 执行 exec,把进程组 ID 与退出码发布到 ctx.e2b.runtimeRoot/processes 下的私有文件,并把 stdout 与 stderr 重定向到带保留完成帧的 base64 编码器;teehead -c 约束可选 spill 文件的大小。

进程身份与发布

同步 seam 会立即返回句柄,同时命令异步启动;pid 在包装层发布进程组 ID 且适配器验证通过之前保持 -1,stdin 与常规观察都等待该发布。启动信号会在分配前中止环境与私有状态准备;分配开始后,取消会等待可清理的临时 SDK 句柄。

环境边界

一次受信任的控制 shell 探测会从 passwd 条目解析沙箱用户的登录主目录,以 base64 ASCII 传输沙箱环境,再进行一次严格 UTF-8 解码;随后包装层移除环境中的 DSH_* 与形似凭据的名称(*KEY**SECRET**TOKEN*),并把每个有效的 spec.env 条目恢复为调用方显式选择。空名称、= 与违反 NUL 分帧规则的条目会在启动前被拒绝;在用户 profile 脚本运行前,此后的命令与 PTY 登录 shell 会获得位于根目录下、全新随机生成的 HOME,并为每个被清理的环境变量名设置空值覆盖。私有环境文件在使用后会被删除。

输出处理

远程包装层先把原始字节分流到可选的有界 spill 文件,再把每个实时分片编码为换行分隔的 base64 ASCII 帧;宿主会跨任意 SDK 回调边界增量恢复字节。pipe 模式把字节写入宿主 Node 流,inherit 模式写入 harness 进程流,collect 模式保留有界的宿主尾部并支持偏移读取。对于 collect 或 inherit 输出,超过 graceMs 后适配器会断开未完成的 SDK 流并扣留其不完整的 spill;原始 pipe 自然完成时则会等待无损传输并保留背压。批量与流式 stdin 都使用 SDK 句柄。

终止阶梯

终止与回滚共享同一条容错信号路径(signalRemoteGroups),在宽限期满时从 SIGTERM 升级到 SIGKILL,以 SDK kill 作为回退,并在报告成功前用有界进程表探测证明完全停稳;仅含僵尸进程的进程组视为空,SandboxNotFoundError 视为完全停稳。


进一步探索

当包级约定不够用时阅读以下页面。它们从家族组合逐步进入子进程 seam 表面,以及渲染它的消费方。


模型体验

通过消费方 seam 间接影响模型,例如 bash 执行器家族;它们渲染远程输出、退出事实、后台增量与 spill 路径。

KV Cache 影响

不会直接失效:请求前缀变更由消费方 seam 负责;本后端的传输永远不会进入请求。

已知限制与延期工作

这些限制说明本提供方何时不合适,或何时需要特别的运维注意。它们是当前包约束,不是任务积压。

  • SDK 仍会在宿主内存中保留完整命令输出:即使本适配器公开的是有界原始字节尾部,E2B CommandHandle.stdout.stderr 仍会累积 base64 传输内容,因此无法达到子进程 seam 通常提供的宿主内存边界,而且传输保留量大于源数据流。
  • 不支持需要同步 PID 的消费方:远程启动期间 pid 保持 -1;包括 ACP 子进程后端在内,要求立即获得正 PID 的消费方无法原样使用本提供方。
  • 私有状态随沙箱生命周期存在:进程目录与有效的 spill 文件会留在 .dsh-e2b 下,直到所有者删除沙箱;本 POC 不提供沙箱内清理。
  • 控制状态与沙箱用户同 UID:E2B 以同一默认用户运行每条命令,因此 0700/0600 权限无法把 .dsh-e2b 控制文件与并发运行的沙箱进程隔离开;真正的隔离需要 E2B 提供按命令用户或带外控制通道。
  • 数值进程身份没有复用围栏E2B 公开基于数值 PID/PGID 的输入、信号发送与清理操作,却没有与身份原子绑定的替代方案;在 E2B 新增身份原语,或实际故障证明需要更窄的协议之前,替代方案继续延后。
  • 初始环境探测会继承沙箱默认值:E2B 会把命令覆盖与默认环境条目合并,因此探测无法在枚举未知且形似凭据的名称之前将它们置空;因此,该 POC 不支持把 secret 放入沙箱默认环境变量。
  • E2B 不公开信号事实:适配器请求的 SIGTERMSIGKILL 只有在包装层发布的直接退出码没有胜出时才报告为信号;其他未请求的 SDK 退出始终保留为退出码,包括等于 128 + signal 的值。
  • 无法精确检查终端 stdin 等待状态:E2B 会公开前台进程组,但不提供证明其正在等待 fd 0 所需的 syscall 证据,因此通用 PTY 后端会回退到受控提示符标记与有界静默机制。
  • 依赖 Linux 工具与 E2B 传输语义:没有 Windows、逃逸会话恢复或网络分区的保真层。

开发备注

维护者的工作上下文——点击展开

本开发备注是维护者的工作上下文:开放问题与尚未决定的探索方向。它明确不具权威性——已交付的行为、限制与既定理由以上文和包代码为准。

开放:数值进程身份

E2B 公开基于数值 PID/PGID 的输入、信号发送与清理操作,却没有与身份原子绑定的替代方案。适配器会尽量减少宿主往返,并在 E2B 新增身份原语或实际故障证明需要更窄的协议之前,继续延后替代方案(TODO(e2b-pgid-identity))。

开放:替换环境与状态观察

由于 E2B 会合并命令覆盖,初始环境探测会继承沙箱默认值;又因为 E2B 无法独立于后代持有的输出观察直接命令的退出,collect/inherit 命令状态需要控制面轮询。两者都只能靠 E2B 的新原语来弥合(TODO(e2b-replace-environment)、TODO(e2b-status-watch))。