阅读 Pi 的 createAgentSessionServices、runtime factory、session replacement 和 cwd-bound services 设计。
Runtime Services 是 Pi 把 CLI、SDK、print mode、interactive mode 和 RPC mode 统一起来的边界层。它为当前有效工作区创建一组 cwd-bound services,再基于这些 services 创建 session;当用户 new、resume、fork 或 import 时,runtime 替换整套 session 和 services。

为什么不能把 resource loader、settings、model registry 和 session 都做成进程级全局单例?
- services 是围绕当前工作区创建的一组依赖。
- runtime factory 把宿主参数转成 services 和 session。
- active runtime 保存当前 session、diagnostics 和替换能力。
- session replacement 不是换一个 id,而是重建一套 cwd-bound runtime。
源码推演(省略版)
Section titled “源码推演(省略版)”下面不是完整源码,而是把本课主线压缩成可以在文档里直接阅读的关键形状。读者即使不打开本地源码,也应该能看出运行时如何组织职责。
async function createRuntime(scope: RuntimeScope) { const services = await createServices(scope); const session = await createSessionFromServices(services);
return { session, diagnostics: services.diagnostics, async switchSession(nextScope) { const next = await createRuntime(nextScope); this.session = next.session; this.diagnostics = next.diagnostics; }, };}- 这段源码形状说明 runtime replacement 的关键:切换 session 时,相关 services 也要跟着重建。
- 如果只替换 session id,却复用旧 resource loader,就会出现 stale context。
- CLI、RPC、交互模式可以不同,但都应该共享这个 runtime 边界。
设计一个 runtime tracer 输出,记录创建、切换、diagnostics 变化和 active session 替换结果。
- 能说明 cwd-bound services 的意义。
- 能解释 session replacement 为什么要重建 runtime。
- 能判断哪些对象不应该做成全局单例。
- 实践题:基于本课的省略版源码,补出一个最小实现草图,要求写清输入、输出、副作用和错误处理。
- 思考题:本课机制如果只靠 prompt 约束,而不放进 harness 或 runtime,会出现什么工程风险?