Skip to content

第 6 章:终端运行时——Orca 的真正内核 ​

目标:理解从 node-pty 字节到 xterm 画面的完整链路,以及 snapshot、flow control、query authority 和 incarnation 如何让终端可恢复。

1. 为什么终端是全项目最复杂的子系统 ​

Orca 托管的 Agent 都运行在终端里。终端同时是:

  • 进程控制通道;
  • 字节流协议;
  • 全屏 TUI 图形界面;
  • 用户输入设备;
  • Agent 状态与标题的辅助信号;
  • 跨桌面、SSH、手机的共享资源。

renderer 可重载、窗口可隐藏、SSH 可断线、daemon 可重启,而 Agent 不能轻易丢失。因此终端不是一个组件,而是一个分布式状态机。

2. 分层模型 ​

前台数据可以走低延迟直通;恢复数据来自 provider/runtime 的权威模型。

3. IPtyProvider:可替换进程宿主 ​

pty-provider-contract.ts 定义统一能力:

生命周期 ​

  • spawn(opts):创建或请求 attach;
  • attach(id):订阅既有 PTY;
  • shutdown(id, opts):有 deadline 的关闭;
  • probePtyLiveness、listProcesses。

交互 ​

  • write、resize、sendSignal;
  • getCwd、getForegroundProcess;
  • onData、onReplay、onExit。

恢复与流控 ​

  • getBufferSnapshot;
  • serialize / revive;
  • pauseProducer / resumeProducer;
  • setPtyBackgrounded;
  • acknowledgeDataEvent。

Agent authority ​

  • claim protocol capability;
  • owner listing authority;
  • create-operation replay;
  • PTY incarnation。

实现包括 local、daemon adapter 和 SSH provider。

4. Spawn 的输入不只是 shell command ​

PtySpawnOptions 还携带:

  • cwd、env 与 envToDelete;
  • launch Agent 与 startup prompt delivery;
  • worktree、tab、pane identity;
  • Windows shell / WSL distro;
  • Codex home 与账户选择;
  • startup ingress authority;
  • Agent session claim / operation id;
  • AbortSignal 与 physical commit callback。

这是因为“启动 Codex”不是执行字符串 codex:还要在进程出生前完成身份、hook、账户、PATH、trust 和重试语义。

5. PtySpawnResult 是恢复协议 ​

除了 id 和 pid,结果可能带:

  • incarnationId:物理进程代次;
  • snapshot + cols/rows:daemon reattach 画面;
  • providerSequence:序列域继续还是重置;
  • replay:relay 增量回放;
  • coldRestore:磁盘 scrollback + cwd;
  • sessionExpired:请求 attach 但原 PTY 已过期;
  • exitedBeforeSpawnReply:响应前已退出;
  • agentSessionEnsure:claim/adopt 结果。

它描述的不是“创建成功”,而是调用者应该怎样把 view 与一个可能已存在、已退出或从磁盘重建的终端对齐。

6. PTY identity 与 incarnation ​

main 维护:

  • ptyOwnership:PTY 到 connection/provider;
  • ptyPaneKey / paneKeyPtyId:双向 pane 绑定;
  • ptyIncarnationById:当前物理代次;
  • size、visibility、last input、output counters;
  • spawn reservation 与 serializer generation。

退出事件只有在 incarnation 匹配时才生效。否则,一个旧进程迟到的 exit 可能杀死已经复用同 id 的新进程。

7. 输出链路与序列号 ​

正常输出:

main 先喂 headless model,再投递 renderer。这样 renderer 即使丢弃后台输出,host 仍保有可序列化的终端状态。

8. 前台低延迟与后台内存上限 ​

renderer scheduler 区分:

  • 前台交互小块:立即写;
  • 大量 redraw:滚动预算;
  • 不可见 pane:后台队列或直接 gate;
  • stale pane:丢弃 renderer backlog,等待 snapshot restore。

关键不是“绝不丢字节”,而是不让 renderer 无界保留字节,同时确保视觉状态可从 host model 重建。

主进程还可以暂停 producer,让子进程在 OS pipe 上自然 backpressure;不能暂停的旧 provider 仍依赖 pending cap 保持内存边界。

9. Hidden-output 恢复 ​

恢复步骤:

  1. 请求 main/provider snapshot;
  2. 暂存少量竞态 live chunk;
  3. 清空 xterm 并按 snapshot 尺寸 replay;
  4. 禁止 replay 中的 terminal query 回答 shell;
  5. 用 seq 丢掉已包含在 snapshot 的 live chunk;
  6. 写入剩余 chunk;
  7. 发送 post-reattach mode/cursor reset。

设计文档见 terminal-main-owned-state.md。

10. Query authority:谁可以回答终端查询 ​

TUI 会发 OSC/CSI 查询,例如颜色、光标、Kitty keyboard、设备属性。如果 snapshot replay 到 xterm 时,xterm 自动回答了历史查询,回答会被写回当前 shell,造成“时间穿越”。

Orca 因此区分:

  • startup ingress authority;
  • live view authority;
  • hidden/main model authority;
  • replay guard。

只有当前真实 view 的新查询可以回到 PTY。snapshot 里的旧查询只用于重建画面,绝不能产生副作用。

11. Stable pane 与 spawn reservation ​

renderer mount 可能并发触发同一 pane 两次连接。main 用 pane key reservation 和 serializer generation 保证:

  • 同一 pane 同时只有一个 fresh spawn;
  • 后到 attach 可复用已提交结果;
  • renderer 被销毁时清理未结算 serializer;
  • late promise 不能绑定到新一代 pane。

这类防线对于 React mount/unmount、window reload 和网络 retry 都必需。

12. Terminal title 与 side-effect facts ​

PTY bytes 中除了画面,还可能有:

  • OSC title;
  • bell;
  • shell command finished;
  • PR URL;
  • cwd(OSC 7);
  • color scheme query;
  • Agent 辅助状态。

如果远程链路为了后台性能做 keep-tail thinning,被丢弃的字节里仍可能有 bell 或 command-finished。provider 可以发 ordered PtyBackgroundStreamEvent,让“事实”与保留字节保持顺序。

13. 关闭与退休 ​

关闭 UI tab 不等于立即 kill;需要区分 user、cleanup、pty-exit。host 会检查:

  • 当前 publication epoch;
  • PTY 是否仍 live;
  • 是否有另一个 leaf/owner;
  • stop/hibernate transaction 是否正在保留 surface;
  • 请求是否只是客户端镜像 teardown。

真实 PTY exit 才是终端 authority。runtime 会移除 leaf、修复 split/layout、清理 binding,并同步持久化 revision 后再发布 absence。

14. 调试与性能观测 ​

源码内建:

  • PTY delivery breadcrumb ring;
  • renderer delivery health report;
  • terminal render desync evidence;
  • foreground latency/throughput budget;
  • hidden flood、WebGL atlas、scroll restore E2E;
  • daemon/SSH attach、early exit 与 incarnation 单测。

终端性能脚本集中在 tools/terminal-* 和大量 tests/e2e/terminal-*。

15. 源码导航 ​