Agent Pool + Cube 沙箱:架构方案

2026-10-30。dsh(大脑)从沙箱里挪出来,常驻在一个 Agent Pool 里;只有需要执行工具时,才给会话绑定一台 CubeSandbox(手)。本文先 review 现方案,再给目标架构、要验证的点,以及需要你在腾讯云上准备的 Cube 配置。
标 估算 的是推算;标 待验证 的是方案依赖、但还没实测的假设。

进展(2026-11-02):P0–P3 都已完成并上线 :8081。选了 AGS 托管(§10.1),工具 cs-tools-022,广州。dsh 是共享容器 cs-pool 里的 worker 进程(2 个预热),工具经 E2B 协议打到每会话一台的 AGS 沙箱;工作区快照在用过工具的一轮后和每次暂停前保存,沙箱丢失或归档后从快照重建;bash 换成跨调用、跨暂停都保留状态的持久 shell。make smoke-hands PAUSE_CHECK=1 TC_PY=… 全部通过。与本文方案的出入:会话目录和快照放在本机磁盘(单机够用,多机时换 CFS / COS);预热 worker 不复用,一个 worker 只服务一个会话。现行架构、一次完整对话的流程、耗时与开销以 docs/architecture.html 为准;本文保留为方案与决策记录,下文的估算已被那里的实测取代。

结论

① 方向可行,而且 dsh 本身就是为此设计的dsh 0.2.1 的工具不直接碰本机,而是通过几个“执行世界”接口:ctx.fs(文件)、ctx.subprocess(进程和终端)、ctx.shell(bash)。官方 README 写明“根据命令运行位置选择本地或远程执行”。我们写一个 Cube 版的实现插件,dsh 就能留在 Pool 里,把工具打到沙箱上执行。
② 官方的 E2B 实现不能直接用dsh 自带的远程实现是 dsh-e2b 系列,停在 0.1.5-rc.3,比 dsh 0.2.1 落后一个大版本。它在插件启动时就建沙箱、关闭时删沙箱,不支持重连、暂停、模板。我们要自己写一个懒绑定、可暂停、可重连的版本,可以参考它的代码(MIT 许可)。
③ 带来的好处模型 key 不再进沙箱;只聊天的会话不建沙箱;等审批时沙箱可以暂停;dsh 不用每次唤醒都冷启动 2 秒;大脑和手可以分别扩缩、分别升级。
④ 主要代价是每次工具调用都多一次网络往返方案阶段本机实验环境(嵌套虚拟化)测得读文件 p50 约 90 ms、跑命令约 240 ms。AGS 实测(§9.2):fork 适配器加缓存后每次工具调用 67–230 ms;与模型每步数秒相比占比很小,见 architecture.html §3。

1. 现方案 review

现状(方案 A):每个会话一个 Docker 容器,dsh 跑在容器里,网关通过 envd 持有 dsh 的 stdio。休眠时先 session/close,再杀 dsh,最后 docker stop;唤醒时 docker start,重启 dsh,再 session/resume。

问题原因依据Pool 方案下
模型 key 在沙箱里dsh 在容器里调模型,key 在 dsh 进程的环境变量中。模型执行的命令能否读到 /proc/<dsh>/environ 还没测handoff §10 #3解决:key 只在 Pool
等审批时永不休眠,一直占名额dsh 挂着审批请求,容器停了就丢handoff §10 #2解决:dsh 在 Pool 里等,沙箱可以暂停
休眠丢进程、丢 shell 状态docker stop 杀光所有进程cube-restore-report §4解决:Cube 暂停保留进程
每次唤醒冷启动 dsh 约 2 秒(占启动的 85%)dsh 跟着容器一起停architecture §4.2解决:Pool 里有预热好的 dsh
只聊天也占一台 2C4G 的容器沙箱和会话一一绑死—解决:第一次调工具才建沙箱
隔离弱:容器和宿主共享内核Docker—解决:MicroVM 有独立内核
单机,换机器会话就丢状态都在一台机器的磁盘上—部分:会话日志要放到共享存储(§4.3)
dsh 的 bash 每次调用都是新 shell,变量留不住默认加载 dsh-tool-bash2026-10-29 实测可选:换持久 bash,依赖远程终端(§9 S4)

现方案做对了、要保留的:

这些在新方案里都不变。

2. 目标架构

手机 App 测试台 / Android REST+SSE 控制面(我们) Gateway 鉴权 · 会话 · 事件流 ACP 客户端 Sandbox Broker 会话 ↔ 沙箱绑定 建 / 暂停 / 恢复 / 归档 Agent Pool(dsh workers) dsh · 会话 1 cube 执行插件 已绑定沙箱 dsh · 会话 2 只聊天 未绑定 预热 worker dsh 已启动 等待分配 ACP(stdio) 首次调工具 时申请绑定 模型服务 key 只在 Pool CUBE / AGS(你配置) Cube 控制面 API create / pause / connect 沙箱(MicroVM) 每个会话一台,懒创建 envd · /workspace · 工具链 无 dsh、无模型 key 空闲 → 带内存暂停 很久不用 → 归档后删除 ctx.fs / ctx.subprocess → envd(每次工具调用) 持久存储(COS / CFS) 事件日志 · dsh 会话目录 · workspace 归档 任何 Pool 节点都能接手任何会话 轮末归档

实线是每轮都走的路径,虚线是按需或后台的路径。蓝线是新增的关键路径:每次工具调用都从 Pool 打到沙箱里的 envd。

组件职责状态在哪
Gateway不变:鉴权、会话、事件流、审批、App 的文件 API。新增:把会话分配给一个 dsh worker事件日志、会话元数据 → 持久存储
Agent Pool常驻一批 dsh 进程。一个活跃会话占一个 dsh 进程(原因见 §3.3)。保持若干个已启动、未分配的预热进程dsh 会话目录 → 共享存储,worker 本身无状态
cube 执行插件(我们写,运行在 dsh 进程里)实现 ctx.fs 和 ctx.subprocess,把操作转成 envd 调用。第一次被调用时向 Broker 申请沙箱无
Sandbox Broker(网关里的一个模块)会话和沙箱一一对应;负责懒创建、恢复、暂停、归档,以及恢复失败时的兜底;校验沙箱身份;对接 Cube 或 AGS 的 API绑定表 → 网关元数据
沙箱只做“手”:文件、命令、终端。镜像里是工具链加 envd,不装 dshworkspace 在沙箱盘上,轮末归档到 COS

3. 关键:dsh 的执行世界

3.1 dsh 0.2.1 的接口(README 原文,从运行镜像里读取)

接口本地实现(现在加载的)谁在用它
ctx.fs:读、写、列目录、监听、原子编辑dsh-fs-localdsh-tool-fs(read / write / edit)、dsh-workspace-changes
ctx.subprocess:起进程、真实终端(PTY)、收集输出、终止dsh-subprocess-localdsh-tool-fs-search(grep / glob)、dsh-terminal-bash(持久 shell)、dsh-workspace-changes(git)
ctx.shell:bash 工具的执行方式dsh-bash-sandbox(landlock)/ dsh-bash-localdsh-tool-bash

dsh-subprocess 的 README 原文:“每个组合配置一个 subprocess 实现,并根据命令运行位置选择本地或远程执行。”dsh-terminal-bash 也写明“同一个后端既可以与本地执行世界组合,也可以与远程执行世界组合”。所以只要替换这几个实现,工具层不用改。

另外,dsh-e2b 的 README 列出了留在宿主(也就是 Pool)里的东西:Cordis 服务、agent 和会话状态、会话日志、模型请求、skill。这正是我们要的切分。

3.2 为什么不能直接用 dsh-e2b

Cube 兼容 E2B 协议,按理把 dsh-e2b + dsh-fs-e2b + dsh-subprocess-e2b 指向 Cube 就行。但是:

所以我们写一个自己的执行插件 cloudsandbox-exec-cube(名字暂定):

如果 DeepSeek 后续发布了支持外部生命周期的 0.2.x e2b 系列,就换回官方实现。这件事值得去问 dsh 团队,handoff 里已经列为待确认项。

3.3 一个会话占一个 dsh 进程

dsh 的执行世界是进程级的:一个组合里只有一个 ctx.fs 和一个 ctx.subprocess,dsh-e2b 也写明“一个沙箱,一个句柄”。如果一个 dsh 进程同时服务多个会话,它们会共用同一个沙箱,这就违反了按设备隔离。所以:

4. 生命周期与状态

4.1 两条独立的生命周期

对象状态何时转换
dsh worker(大脑)预热 → 已分配 → 已释放会话第一次收到消息时分配;空闲 T1 后释放;之后来消息就从池里再分配一个,再 session/resume
沙箱(手)无 → 运行 → 已暂停 → 已归档 第一次调工具时创建;
没有工具在跑,并空闲 T2(比如 2 分钟)后暂停,等审批期间同样可以暂停;
下次调工具时恢复;
暂停超过 T3(比如 7 天)后把 workspace 归档到 COS,再删除沙箱;
归档后再调工具:新建沙箱,从 COS 还原 workspace

好处是两边各省各的:只聊天的会话只占大脑;用户离开了,大脑先释放,手稍后暂停,都不需要对方配合。

4.2 恢复失败的兜底

AGS 上实测恢复 100/100(cube-restore-report.html §9),本机实验环境则只有 8/18(§6)。生产形态没问题,但这只是 100 次样本,Broker 仍然要有退路:

  1. 重试:恢复失败后,等沙箱状态回到 paused 再重试,最多 N 次(实测有的在第 4 次才成功)。
  2. 冷重建:从最近一次轮末归档新建沙箱,还原 workspace,并在工具结果里告诉模型“远程电脑已重建,之前的进程和终端状态已丢失”。
  3. 身份校验:每次绑定或恢复后,先读出沙箱里的一个随机 nonce,与 Broker 记录的比对,不一致就拒绝使用(对应报告 §6.2 观察到的错误路由)。

dsh 在 Pool 里,所以沙箱出问题只会表现为某次工具调用失败,对话本身不会断。这正是 WorkBuddy 从 SANDBOX 迁到 LAMP 的理由(见 docs/research/mobile-cloud-computer.md §1.2)。

4.3 状态放在哪

状态放在哪备注
事件日志、会话元数据网关,现在是本地磁盘多节点时迁到 MySQL / COS,这是独立的一步
dsh 会话目录(对话上下文)Pool 节点的共享存储(CFS / NFS),或者轮末归档到 COS、分配时取回任何 worker 都能 session/resume。现在固定 DSH_HOME 的约束继续保留
workspace沙箱盘上;轮末增量归档到 COS(tar 或 git bundle)不建议直接用 Cube 的 S3 Volume(s3fs)当 /workspace:git 和 npm install 这类小文件密集操作在 s3fs 上会很慢 待验证
进程、shell、内存沙箱暂停快照只在 L1(暂停)期间有效,归档后丢失

App 的文件 API 改成通过 envd 访问沙箱,沙箱暂停时会触发恢复。沙箱已归档时直接读 COS 上的归档,不用为看个文件把沙箱拉起来。

5. 一轮对话怎么走

App  POST /prompt ─► Gateway
Gateway: 会话没有 worker → 从预热池取一个 → session/resume(约 60 ms)
Gateway ─ session/prompt ─► dsh(Pool)
dsh ─► 模型:思考、回复文字                  (不碰沙箱)
dsh: 要执行 bash / read / grep
  cube 插件 ─► Broker:申请沙箱
     Broker:无 → create   已暂停 → connect(恢复)   运行中 → 直接用
     Broker:nonce 校验 ─► 返回 envd 地址和访问令牌
  cube 插件 ─► envd:执行;结果返回给 dsh
dsh ─► session/update 事件 ─► Gateway ─► SSE ─► App   (与现在相同)
dsh: 需要审批 → Gateway 挂起请求;Broker 可以让沙箱先暂停
turn_end → Broker:增量归档 workspace;空闲 T2 后暂停沙箱

6. 安全

7. 时延与成本

7.1 每次工具调用的往返

AGS 实测(2026-10-30,从服务器 9.135.181.73 到广州 AGS,HTTPS 长连接,各 50 次):

操作p50p95
读文件 4 KB23.1 ms35.3 ms
写文件 4 KB21.1 ms26.0 ms
列目录(300 个文件)27.6 ms33.6 ms
跑一条命令(true)25.0 ms28.8 ms
rg 搜 300 个文件31.9 ms39.4 ms

达到验收线(p50 ≤ 30 ms、p95 ≤ 100 ms,命令 p50 25 ms)。一轮 30 次工具调用多出约 1 秒。Pool 直接放在现在的服务器上即可。

下面是更早的本机实验环境数据,仅作对照:

操作(经 CubeProxy,本机实验)p50p95
读文件 4 KB90 ms404 ms
写文件 4 KB44 ms83 ms
列目录52 ms118 ms
跑一条命令(true)238 ms696 ms
跑 grep -r158 ms408 ms

环境:Mac → Lima 虚拟机 → KVM 嵌套,CubeProxy 是 amd64 镜像,在 arm64 上用 qemu 模拟,每次调用都是 TLS。所以这些是悲观上限。绕过代理直连 envd 的对照组没测成,实验集群开始拒绝新建沙箱(408)。

估算 一轮 30 次工具调用,每次平均 150 ms,多出约 4.5 秒;模型首字本身要 8–21 秒(handoff §7),这个量级可以接受。如果同可用区 x86 上每次在 10–30 ms,就只多 1 秒左右。验收线建议:同可用区 envd 命令 p50 ≤ 30 ms、p95 ≤ 100 ms。

可以降低往返的手段:

7.2 资源与成本 估算

项现在Pool 方案
只聊天的会话一台 2C4G 容器一个 dsh 进程(约 100–200 MB)
活跃的编码会话一台容器一个 dsh 进程 + 一台沙箱
等审批容器一直运行、占名额dsh 进程等待,沙箱暂停(只付存储)
离开后容器停止,冷恢复 2.3 秒worker 释放;沙箱暂停,恢复后进程都在
新增固定成本—Pool 节点(几台常驻机器);Cube 控制面(AGS 托管免运维,或自建约 2.7 GB 内存加运维)

8. 对现有代码的影响 估算

模块改动
internal/sandbox/新增 cube.go:Cube / AGS 控制面客户端(create、pause、connect、kill、snapshot)。Docker 运行时保留,用于本地开发
internal/gateway/session.go拆成两个状态机:worker(大脑)和沙箱(手)。ensureReady 只负责分配 worker;沙箱交给 Broker
新增 internal/pool/预热 worker 的启停、分配、回收。第一版 dsh 进程可以直接跑在网关所在机器上(本地子进程),之后再拆成独立 Pool 服务
新增 internal/broker/绑定表、懒创建和恢复、重试与冷重建、nonce 校验、轮末归档。给插件提供一个只对内的 HTTP 接口
新增 dsh 插件(Node / TS)ctx.fs、ctx.subprocess、ctx.shell 的 Cube 实现,加组合配置(替换 fs-local、subprocess-local、bash-sandbox)
files.goApp 的文件 API 改为调 envd;已归档时读 COS
image/拆成两个镜像:Pool 镜像(dsh + 插件)和沙箱模板镜像(工具链 + envd,不装 dsh)
App 侧 API基本不变。sandbox 字段的含义改为“手”的状态(无 / 运行 / 暂停 / 归档),另加 worker 的状态

9. 开工前要验证的点(spike)

按风险排序。S1 到 S3 任何一条不成立,方案就要调整。

#验证什么怎么验不成立时
S1 通过dsh 0.2.1 能否加载我们的 ctx.fs / ctx.subprocess 实现,替换本地实现后工具都能工作(见 §9.1)先试把 dsh-*-e2b 0.1.5 装进 0.2.1,指向 Cube;不兼容就写最小实现,跑 read / write / edit / bash / grep / glob向 dsh 团队要 0.2.x 的远程实现,或者退回现方案
S2 通过同可用区每次 envd 调用的时延x86 Cube 上跑本文 §7.1 的脚本,加一组直连 envd 的对照超过验收线:评估把 grep / glob 合并成一次远程命令
S3 通过x86 上暂停 / 恢复的成功率(AGS 100/100,见 cube-restore-report §9)报告 §8 的 100 次测试不用 L1 暂停,只用冷重建(仍比现在好:大脑不停)
S4 通过持久 shell 能否跑在远程 PTY 上(spawnTerminal → envd PTY)。能;但沙箱暂停后 PTY 输出流会静默失效(不报错也不再有数据),fork 里按 lease 的 epoch 判断并按 pid 重连启用 dsh-tool-bash-persistent继续用一次性 bash
S5 已解决dsh-tool-fs-search 在远程世界里起的是什么进程;沙箱镜像需要装什么读插件代码,抓它的 spawn 参数在模板镜像里装对应的二进制
S6子 Agent 和 stdio MCP 也走 ctx.subprocess,会被起在沙箱里,这是否符合预期各跑一次子 Agent 先禁用(与旧方案 B 的结论相同)
S7ctx.fs 的监听(watch)在远程怎么实现看哪些插件依赖 watch远程实现返回“不支持”,或者用轮询

9.1 S1 结果(2026-10-30,AGS,经 E2B 协议)

做法:dsh 0.2.1 + 官方 dsh-fs-e2b / dsh-subprocess-e2b 0.1.5-rc.3 + 我们写的 cube-runtime(替换 dsh-e2b 管生命周期)。用一个按脚本发工具调用的假模型驱动(当天模型 relay 故障,而且脚本更可重复),在服务器上跑。细节和复现:poc/dsh-e2b-s1/README.md。

项结果
功能12 / 12:bash(在沙箱里,x86_64,宿主的 key 类变量一个都没带进去)、write / read / edit(含版本防护)、grep / glob、后台任务、相对路径、stderr 与退出码
每次工具调用耗时0.4–1.5 秒;同样脚本用本地工具约 35 ms。单次 envd 往返只要 ~25 ms(§7.1),所以问题在调用次数
调用次数12 步共 844 次 SDK 调用、600+ 次 envd 请求,每步 30–78 次

为什么慢(用 SDK 层追踪定位):

  1. dsh-fs-e2b 每解析一次路径就在沙箱里起一个进程跑 realpath … | base64,再 getInfo 一次,没有缓存。光 /workspace 就解析了 55 次。
  2. 每次请求模型前,系统提示词相关插件都要探测 /workspace/.git、/.git、AGENTS.md 等,每步约 17 次。其中 $DSH_HOME/AGENTS.md、~/.agents/AGENTS.md 本该读宿主上的配置,现在也被送去了沙箱:ctx.fs 是全局的,换成远程后所有读文件的插件都跟着变远程。
  3. 命令结束靠读沙箱里的 exit-code 文件轮询(pollMs 默认 20 ms)。

结论:dsh 的执行世界接口确实能把工具整体搬进 AGS,方向成立;但官方 e2b 适配器只是 POC 质量,不能直接上线。下一步写我们自己的 ctx.fs / ctx.subprocess:

目标是每次工具调用 1–3 次往返,也就是 50–100 ms。

9.2 优化后(2026-10-30)

按上面三条原因,把两个官方适配器 fork 成我们自己的 cloudsandbox-dsh-fs-cube、cloudsandbox-dsh-subprocess-cube(MIT,改动集中、可 diff),cube-runtime 负责记录沙箱里命令的启停。同一组 12 步脚本,在服务器上:

工具本地工具官方 e2b 适配器优化后优化后,模型每步思考 3 s
read35 ms0.8–1.1 s67 ms65 ms
write / edit35 ms1.0–1.4 s117–196 ms123–197 ms
bash35 ms0.7–1.4 s199–230 ms234–347 ms
grep / glob35 ms0.7–1.4 s~183 ms196–230 ms
12 步总 SDK 调用—844231274

“模型每步思考 3 s”用假模型的响应延迟模拟。它验证缓存不依赖时间窗口:真实模型的两次工具调用之间隔着好几秒,靠 TTL 的缓存会全部过期。

做了什么:

正确性:

还能再快的地方:bash 一步还有约 6 次往返(写状态文件、启动、读状态、清理、ps 查进程组),可以把清理和进程组检查放到后台。离 50–100 ms 的目标还差一点,但已经不影响体验:一轮 30 次工具调用多出约 5 秒,模型本身要几十秒。

9.3 真模型端到端(2026-10-30)

模型换成 DeepSeek 官方 API(deepseek-flash,OpenAI 兼容),任务是:在 /workspace/calc 下写一个 Python 小包(add / mul / safe_div),用 pytest 写测试并跑通,最后用 grep 确认 safe_div 里有 ValueError。工具全部在 AGS 沙箱里执行。

指标结果
结果6 个 pytest 用例全部通过(10 passed / 6 passed 取决于生成的用例数),grep 命中 raise ValueError
整轮墙钟25 秒(含建沙箱、装插件、6 次模型请求)
模型请求6 次,合计 9.3 秒
工具执行5 步合计 1.5 秒,p50 373 ms,最长 1.3 秒(一次 ls 加一次 pytest)
SDK 调用155 次,其中读文件 10 次(修掉 20 ms 轮询前是 6905 次,读 6006 次)
工具调用3 次 bash、2 次 write、1 次 grep

途中发现的问题:第一版跑同一个任务要 157–394 秒,瓶颈是沙箱从公网 PyPI 装 pytest 只有 15–20 KB/s(1.3 MB 要两分多钟),而且 Debian 的 Python 是 externally-managed,直接 pip install 会被拒。镜像里加上腾讯云 pip / npm 镜像、预装 pytest、允许系统级 pip 安装后,同一任务降到 25 秒。这说明沙箱镜像该预装常用工具,而不是让模型现场装。

途中发现并解决的问题(都已写进代码或镜像):

问题处理
dsh-e2b 建沙箱不带模板(E2B 默认 base 在 AGS 上不存在),启动即建、退出即删cube-runtime 替换它
AGS 对所有沙箱都报告 envdVersion = 0.2.10,与镜像里实际的 envd 无关。E2B SDK 按这个数字禁用 stdin、closeStdin、文件元数据cube-runtime 按配置的真实版本重建 SDK 句柄。这是 AGS 的 bug,应反馈
AGS 官方 envd 只有 v0.5.14;dsh-fs-e2b 的版本防护要文件元数据(envd ≥ 0.6.2)镜像换成上游 E2B envd 0.10.2(Apache-2.0,自己编译)。实测能在 AGS 上启动、鉴权、读写元数据
E2B SDK 默认以 user 用户执行镜像里建 user(uid 1000)
dsh-tool-fs-search 按宿主上 rg 的绝对路径起进程,不可配置镜像里在同一路径放一个指向系统 rg 的软链接(要求 Pool 的 dsh 安装路径固定)
permission 预设插件拒绝不做隔离的 bash 执行器远程世界禁用它(隔离边界是 MicroVM)
cordis 用 Proxy 包装服务,JS 私有字段(#x)不可用插件里用普通字段

10. 腾讯云 Cube 配置清单(请你准备)

10.1 先定形态

AGS(托管 Cube)自建 Cube
机器不用管x86 云主机,OpenCloudOS 9 + PVM 内核,或者物理机。建议至少 16 核 / 32 GB,数据盘 XFS
暂停、恢复云 API:PauseSandboxInstance(Memory=true) / ResumeSandboxInstanceCube API:/sandboxes/{id}/pause、/connect
已知限制暂停实例每账号默认约 10 个(需要提额);暂停按声明内存规格收存储费运维 16 个服务;要跨机恢复需开 S3 后端

已定:AGS 配置全部经云 API 完成,资源清单见 poc/ags-lab/README.md。Broker 的接口两种都能接,选哪个你定。我倾向 AGS:免运维,能更快拿到 x86 上的真实数据。

10.2 需要配置的项

项建议值说明
地域 / 可用区 / VPC与 Pool 机器同一可用区决定 §7.1 的时延。Pool 要能访问沙箱的 envd 入口(CubeProxy 或 AGS 数据面域名)
沙箱模板(镜像)我来写 Dockerfile:Ubuntu + git、node、python、ripgrep、build-essential + envd不装 dsh、不放 key。AGS 要求镜像用 @sha256 固定、系统盘 20Gi(见 docs/research/ags-custom-image.md)
规格2C4G 起和现在一致
存储后端自建:先用 xfs,要跨机再开 s3 + COS 桶s3 后端必须在建模板时指定,之后不能改
生命周期空闲超时由我们控制:创建时显式传 timeout;on_timeout=pause;auto_resume=false恢复由 Broker 显式调用,这样可以做重试和 nonce 校验。自建时把 paused_resource_release_ratio 调高
入口鉴权开启每沙箱访问令牌见 §6
网络模式PUBLICAGS 没有按域名的白名单;要收紧只能用 VPC + 安全组 + 出站代理,第二期再做
配额并发运行 ≥ 20、暂停 ≥ 100(测试期)AGS 暂停配额要提前申请
归档桶一个 COS 桶,用于 workspace 归档和 dsh 会话目录Pool 和网关可写;沙箱不可访问

10.3 配好后请给我

11. 分期 估算

阶段内容验收
P0 spike(不依赖腾讯云) 完成§9 的 S1、S5–S7;dsh 插件最小实现跑通 read / write / bash / grep测试台上一轮编码任务的工具都打到 Cube 沙箱里执行
P1 接入云上 Cube 完成 11-02S2、S3 实测;Broker(懒创建、暂停、恢复、重试、nonce);沙箱模板时延和恢复成功率达到验收线;make smoke 全过。实际:internal/hands + image/dsh-plugins,make smoke-hands PAUSE_CHECK=1 全过,只聊天的会话不建沙箱
P2 Pool 完成 11-02预热 worker、分配与回收、会话目录放到共享存储、轮末归档、冷重建杀掉任意 worker 或沙箱,对话可以继续;只聊天不建沙箱。实际:internal/gateway/pool.go、snapshot.go;smoke 里杀掉全部 worker 后模型仍记得暗号,云 API 停掉沙箱后文件从快照回来
P3 收尾 完成 11-02出网策略、App 文件 API 切到 envd / COS、持久 bash(S4)、文档与 Android 端字段适配handoff §10 的 #2、#3 关闭。实际:持久 bash(S4,PTY 断流后按 lease epoch 重连);出网实测并定为 PUBLIC(元数据服务、我们的内网都不可达);已归档会话的文件 API 直接读快照;测试台与 Android 展示 sandbox.hands 与 hands 事件;构建期锁死“Pool 里没有本地执行的 provider”

P1 没有改动 :8080:工具沙箱模式是第二个网关实例 :8081(同一个二进制和镜像,GATEWAY_HANDS_TOOL 打开)。