13 · 在线阅读
本章小节

第十三章 跨进程状态与远程执行

13.1 一个应用,为什么分成多个进程

进程是操作系统中正在运行的程序实例。一个代理应用可能同时拥有本地模型协调程序、浏览器界面以及远程机器上的命令执行器。它们不共享普通变量:本地把计数改成三,浏览器里的计数不会自然跟着改变;远程机器上的文件,也不能直接用本地路径读取。

Pi 仓库提供了两种需要区分的基础设施。Chord 处理有类型契约的对象、引用和状态通信;pi-env 为 Durable 提供远程执行环境,让文件操作和命令发生在另一台机器。两者都跨越进程边界,但解决的问题不同。了解这种分工,才能决定自己是在同步一个界面状态,还是在远程运行一个工具。

Chord 的对象可以理解为“某个地址上的状态与行为”。调用方拿到的是引用,即访问对象的句柄,而不是直接操作对象本体。对象按需创建,只要还有引用就继续存在。引用可以在同进程中使用,也可以跨进程使用;它隐藏了部分通信细节,但并没有消除网络断开等实际问题。

13.2 用契约表达允许怎样调用

契约是双方共同认可的接口说明。例如,一个计数器需要一个名字,公开一个数字状态,提供“增加指定数量”的方法。Chord 用 TypeBox 描述这些输入和状态;TypeBox 是能把 TypeScript 类型与运行时数据结构描述连接起来的工具。这样,接口不是只存在于注释里的一段文字。

宿主,也就是承载对象的运行环境,通过 createHost 创建,并安装对象的实现。调用方按契约取得引用,再调用方法。对象还知道调用方的身份,文档称为 principal。例如,所有者与访客可以得到不同对象、不同方法;身份与权限需要由应用组织,不能把任何拿到引用的人都当成管理员。

可以把一次调用想成下面这条线。远程过程调用通常缩写为 RPC,意思是把请求传给另一个进程,由它运行方法,再把结果送回来。

界面持有计数器引用 → 按契约请求增加二
宿主执行方法 → 修改计数 → 状态更新送回界面

Chord 在宿主之间交换 JSON 帧。帧是通信中一条有边界的消息,链接是负责传送这些消息的通道。工程提供内存链接、Node 进程通信链接和 WebSocket 链接。应用可以根据部署位置选通道,而不是为每种通道重新定义计数器的业务接口。

13.3 状态增量和热重载有什么用

可观察状态意味着,订阅方可以在数据变化时收到通知。Chord 的远程观察者先获得完整快照,再接收增量。快照是某一时刻的完整状态;增量只描述相对上一次发生了什么。例如,一万字输出后面新增加两行,传追加操作通常比每次重发全文更合适。

独立的 chord/delta 模块提供 JSON 修改追踪与增量应用。Durable 使用相关能力发布文档、会话视图和任务图。一次成功变更发布一个原子版本;回调抛错则保留原状态。调用方应遵守不可变数据约定,不能拿到已发布对象后直接修改,否则会绕过变更记录,破坏权威状态。

热重载是运行中替换代码。Chord 的设计保留状态和引用,让已开始的工作按旧实现完成,后续工作采用新实现;不兼容变化需要在安全位置迁移。它解决的是开发和插件更新时“代码变了,现有对象怎么办”的问题,并不等于任何代码都能无条件替换。

这里要保持证据边界:Chord 具备这些通用能力,不代表默认 Pi CLI 的每一个状态、插件或远程操作都由 Chord 承担。特别是默认 CLI 的资源重载与 Durable 的扩展替换,应分别阅读自己的实现。不能只因仓库里有热重载框架,就把所有产品行为归因于它。

13.4 远程工具怎样留住本地控制

pi-env 面向另一类需求:工作文件在远程服务器,模型协调、存储和凭据仍留在本地 Durable 工作进程。例如,本地代理决定读取 src/main.ts,远端执行环境读服务器工作目录里的文件,再把结果传回来;随后模型请求仍由本地这一侧安排。工具在哪里执行,与模型服务在哪里访问,是两项独立选择。

远程机器运行一个小型 Rust 程序,源码在 packages/env/daemon。Rust 是编译型语言,此处用于实现处理文件和进程操作的守护程序。RemoteExecutionEnv 实现 Durable 的执行环境接口,通过 Connection 发请求;远端程序在标准输入和标准输出上传输带长度边界的协议帧,诊断文字走标准错误。

常用连接方式是 SSH,即提供加密远程连接的协议。connectSsh 检测远端平台,在需要时部署对应程序并校验内容哈希,再启动连接;也可以使用延迟连接,在首次操作时才准备。应用需要让机器所有者核对主机密钥指纹,确认连接的是预期服务器。不能把“扫描到了一个密钥”当成“已经验证服务器身份”。

这条路线通常无需把本地模型 API 密钥复制给远端守护程序。不过,文件内容和工具输出会返回代理,之后可能进入模型请求;远端命令本身也具有远端账号的权限。因此,本地保存模型凭据并不自动提供文件隔离或命令沙箱。

掉线时还要考虑任务结果是否确定。当前协议会让客户端把丢失连接的请求标记为连接丢失,并在后续请求时建立新守护程序;旧文件句柄不能转交给新进程继续使用。守护程序在输入结束或长期收不到字节后会结束其启动的命令组。因此不能把 SSH 连接视为一个永久保活的远程任务系统,更不能假定重连后旧命令仍在后台运行。

13.5 小结与练习

本章小结:Chord 提供跨进程对象与状态通信的通用结构,pi-env 提供 Durable 工具的远端执行接口。一个关注“大家怎样看到相同状态”,一个关注“操作到底在哪台机器发生”。先画清本地、远端和模型服务的位置,再选组件,比先堆叠所有能力更容易理解。

练习一:浏览器要持续显示增长中的工具输出,首先涉及哪种机制?参考答案:快照加增量的状态发布机制。远端执行环境负责取得输出,不负责自动替你完成整个浏览器状态层。

练习二:本地连接服务器读文件,是否必须把模型凭据写到服务器?参考答案:pi-env 的典型架构不需要,模型协调与凭据留在本地。但返回的数据仍可能发给所选模型服务。

练习三:Chord 有热重载,是否能断言 Pi 所有扩展都使用 Chord?参考答案:不能。库的能力与具体产品接线是两种证据,要检查调用方依赖与实现。

本章源码依据