Wayfinder 已到达 · BERTH-2154

Berth Bot 云电脑(Computer)整体方案

bot 在 Cloudflare 上拥有一台属于你的 Linux 电脑:跑脚本、读写文件、导出图表。它算出的交易永远交回对话、由你审批,电脑本身碰不到任何钥匙。依据 docs/bot/computer.md 与 ADR-0254 ~ 0260。

🔒 只用 Cloudflare 栈 永不签名、不动资金 不持委托 key / KEK / 会话 token 对外副作用走同一写管线

1 · 分期

五个阶段都已设计,第一版只交付 ①;/to-tickets 拆的就是这一段。

① 首刀
终端 / 文件
只给聊天 Run;线程内联卡只读;产物外置;可上传
②
Routine 用终端
每条 Routine 单独开关,默认关
③
持久浏览器
容器 headful Chromium + 查看器 + 用户接管
④
Routine 用浏览器
只读;要登录即报错
⑤
computer use
GUI 桌面,另开设计票

2 · 拓扑

两个 DO 分工:BotOwner 管人、Run 与额度;BotComputer 管机器。容器出网全部被拦截过滤。

flowchart TB
    C["客户端 web / desktop / mobile"]
    O["BotOwner DO
所有者 · Run · 线程 · 平台额度"] M["BotComputer DO(每所有者一个)
机器状态 · snapshot id · 并发计数 · alarm"] K["容器 standard-1
/workspace · 无任何 key"] E["出网 Worker
白名单 · 令牌桶 · 拒绝 HL /exchange 与 Berth API"] R[("R2
工作区备份 · 产物 · 上传")] S[("镜像仓库
rootfs snapshot 只留最新")] C -- 线程流 --> O C -. 查看器实时流(③起) .-> M O -- "RPC: exec / 文件 / 结算 / reset" --> M M -- this.ctx.container --> K K -- 全部出网 --> E M --> R M --> S

3 · 生命周期

一个所有者至多一台,名下 bot 共用工作区。只有三态,「没有电脑」不是状态。

stateDiagram-v2
    [*] --> 启动中: 首个 computer__* 调用
    启动中 --> 运行中: 就绪
    运行中 --> 待机: 空闲 5 min,存 snapshot + R2
    待机 --> 启动中: 只有 computer__* 调用能唤醒
    运行中 --> 待机: 平台意外停机
    

关键数字(Spike 实测)

snapshot 恢复< 1 s
冷启动(镜像已缓存 / 需拉取)0.1–0.6 s / 7–35 s
启动上限60 s → computer_unavailable
snapshot 有效期30 天,镜像换版即失效
工作区上限5 GB
并发(总 / Routine)4 / 2,超出 computer_busy

打开线程、下载产物、上传文件都不唤醒机器。重置云电脑会删 snapshot 与备份,产物保留。

4 · 一次调用的完整链路

额度、并发、污染、回传都在这一条链上。

  1. 模型调 computer__exec("python analyze.py")
  2. BotOwner平台额度 > 0?否 → computer_allowance_exhausted
  3. BotComputer并发 < 4?待机则唤醒(启动不计入命令超时)满 → computer_busy
  4. 容器bash -lc 跑命令(缺省 120 s,上限 600 s)脚本出网经出网 Worker:HL /info 放行,/exchange 与 Berth API 硬拦
  5. 客户端实时输出只推给终端卡,不进模型
  6. BotComputer结束:输出截断到 16k 字符(头 25% + 尾 75%),完整日志留工作区;结算运行秒扣平台额度(幂等)
  7. BotOwner结果包 nonce 信封,本 Run 标记污染
  8. 模型据此调 hl__place_orders([...]) → WriteIntent,因已污染 → 恒需审批审批卡加一行「本次对话用过云电脑,请逐项核对」
  9. 用户批准 → 写管线签名执行;云电脑全程拿不到 key

5 · 工具面(ADR-0257)

5 个工具全部直出;新效果档 computer_local 只改工作区、不审批。

工具做什么效果档
computer__exec单次非交互进程,状态不跨调用,无后台进程computer_local
computer__read_file带行号读文本,缺省前 2,000 行read
computer__write_file整文件写入computer_local
computer__edit_fileoldText → newText 精确替换computer_local
computer__export_artifact复制到 R2,挂消息上供下载 / 预览(≤ 25 MB,每 Run ≤ 10)computer_local

上传不是工具:composer 附件 → /workspace/uploads/。③ 起再加 computer__browser_*,对外动作用 computer_effect 走人审。

6 · 安全、计费、留痕、Routine

安全边界 · ADR-0256

  • 放行:包仓库、venue 只读、公开行情(按 host + path + method)
  • 硬拦:Berth API、链 RPC、venue 写端点(拒绝清单优先)
  • 容器启动参数只有 BERTH_NETWORK、BERTH_ACCOUNT_ADDRESSES,单测断言
  • 按所有者令牌桶 · 全局熔断 · 按所有者封禁

计费 · ADR-0255

  • 「模型额度」更名平台额度,云电脑也扣(BYOK 只扣云电脑)
  • 按实例运行秒 × standard-1 最坏单价 ≈ $0.074 / h
  • 用尽回 computer_allowance_exhausted,可透支一条命令
  • 日预算熔断 computerCircuit,托管聊天不受影响

留痕 · ADR-0258

  • 线程里的 tool part 就是留痕,不另建事件表
  • 运营只看元数据,读不到命令与输出
  • 新增审计 computer_reset / computer_banned
  • 浏览器截图存 R2 留 30 天;接管期间不录屏

Routine · ADR-0259

  • 每条 Routine 单独开「允许使用云电脑」,默认关
  • 可与自动下单同开:用了云电脑的那次转审批
  • 检查永远不碰云电脑
  • 花费按结算区间归类,混用算聊天

7 · 三端 UI 结构

① 唯一 UI 面

线程内联卡

  • 终端卡:命令 + 实时尾部 + 状态 + Stop
  • 文件 diff 卡 · 产物卡
  • 状态行:待机灰字 / 冷启动 >2 s 才提示
③ 起

查看器

  • Terminal / Browser / Files + 时间轴回放
  • 宽屏停靠右侧,窄屏全屏 sheet
  • 审批卡恒在线程里
③ 起

接管

  • Watching → Take control → 交回
  • web iframe · desktop WebContentsView · mobile WebView
  • 手机切 430×932;原生输入框发中文

8 · 首刀切片草案

规格 §12;/to-tickets 会细化并连阻塞边。

flowchart LR
    S1["1 exec 曳光弹
DO + 容器 + 终端卡"] --> S2["2 出网 Worker"] S1 --> S3["3 待机与恢复"] S1 --> S4["4 文件工具 + 日志"] S1 --> S5["5 计费 / 熔断"] S1 --> S6["6 产物与上传"] S3 --> S7["7 生命周期边缘
busy · Stop · 重置 · 硬删 · 封禁"] S5 --> S7 S1 --> S8["8 意图回传
hl__place_orders"] S4 --> S9["9 mobile 壳"] S6 --> S9

开工前须知

  • 设计稿归大佬:终端卡三态、文件 diff 卡、产物卡、状态行、上传入口、设置区、额度用尽卡、审批卡来源行与批量表格。实现票钉住 canvas artboard 后照稿,前面的切片可先用简陋渲染。
  • 切片 3 前要先测:DirectoryBackup → R2 往返耗时;snapshot 是否计入 50 GB 上限(规模化前找 CF 支持确认)。
  • hl__place_orders 动签名活路径:上生产前 web 与 mobile 各自 testnet QA。
  • 下一步:新会话里手动跑 /to-spec(补用户故事、确认测试接缝)→ 同会话 /to-tickets。