运行中的修改,到底什么时候生效

拆解 pi(DeepSeek 开源终端 Coding Agent)v0.83.0 的 setter 与 pending writes:调用 setModel() 返回后,「新模型生效」有四个不同的观察面,其中两个还是旧的。源码依据:pi-internals 21 章

setter 返回了,然后呢

Agent 运行中,你调用了 await harness.setModel(second),它返回了。直觉上「模型已经是 second 了」。

但如果你同时问四个地方,会得到四个答案:

  • harness.getModel()second------setter 已更新 Harness 的最新配置
  • 已经发出的 provider request:旧模型------请求用的是 active turn state,不重读字段
  • 下一次 createTurnState()second------下一份快照会读到新值
  • session.buildContext()(保存点 flush 前):还是旧的 branch 配置------busy 时 setter 只把变更放进 pending queue

一次修改,四个观察面,其中两个还停在旧值。这不是 bug,是设计:当前请求必须用稳定的输入(turn snapshot),修改只对下一轮生效

setter 的两个时钟

以 setModel() 为例。它先保存 previousModel。phase 为 idle 时,等 appendModelChange() 成功;phase 非 idle 时,只向 pending queue 放入一条 model_change。接着无论哪条路径,都把 this.model 指向新模型,并发出 model_update 事件。

setThinkingLevel() 和 setActiveTools() 结构相同。setTools() 还会先校验工具名唯一、active name 都存在,再决定追加还是排队。setResources() 与 setStreamOptions() 不写 Session entry------它们只改变当前实例,进程重建时需要宿主重新提供。

pending write 为什么不能立即插队

这是这一章最值得细看的地方。assistant message 可能带多个 tool call。低层 loop 要先把 assistant message 和对应的 tool results 形成相邻、完整的对话片段,再进入下一轮。

如果一个 subscriber 在 message_end(assistant) 里追加 custom message,并且立刻写入 Session------这条消息就会落在 assistant 与 tool result 之间。下一次从树构建上下文时,模型 API 所需的工具配对可能被切断:模型看到 tool call,却看不到对应的 result。

所以 Harness 让运行中的 appendMessage() 只排队,idle 时才直接追加。flushPendingSessionWrites() 始终读数组首项,按 entry type 调 Session 对应方法,成功后才 shift()。某项失败不会越过它写后面的内容------简单的 FIFO,没有重试计数、没有 durable queue id、没有跨进程恢复。

Hook 是顺序的,不是并发的

subscribe() 注册全事件观察者,存放在专门的 handler set 里。emit 时按注册顺序等待每个 listener;任意一个抛错,错误被规范成 Hook error,后续 listener 不再执行。它不是 fire-and-forget 的埋点。

on(type, handler) 注册带类型的 Hook,同样顺序等待,保存最后一个非 undefined 结果。所以 context、tool_call、tool_result 这些 Hook 的默认 reducer 是 last-result-wins,不是自动合并所有对象。provider options 和 payload 是例外:链式处理,前一个 handler 改出的结果交给下一个。

失败不会回滚

message_end 到来时,Harness 先 session.appendMessage(event.message),成功后才通知 subscriber。subscriber 抛错,已经追加的消息不会从树上删除。setter 也是先提交自己负责的状态,再发 update 事件;update listener 失败会让 public Promise reject,却没有补偿性回滚。

拆完这章,我的感受是:Agent 框架的「修改」语义,比普通系统复杂得多------因为同一份状态同时活在内存配置、turn 快照、pending queue 和 Session storage 四个地方。pi 的处理是给每个观察面明确的语义:修改立即可见于内存,只对下一轮生效于请求,只在保存点落盘于存储。做 Agent 平台的人,最怕的就是把四个观察面混成一个「当前状态」------那才是真正找不到 bug 的根源。

想看完整拆解(setter 四观察面状态表与 Hook 失败语义源码),这里有 pi-internals 小册子

源码依据:packages/agent/src/harness/agent-harness.ts L225-L317、L442-L484、L512-L536、L538-L554、L884-L955、L961-L1023,pi v0.83.0,commit 845d6ff1。

相关推荐
2501_9127840813 小时前
跨境建站避坑:为什么通用电商架构不适配反向代购业务
大数据·人工智能·架构·taoify
yychen_java13 小时前
二:Multi-Agent 协作架构与 MCP 协议实战:Java 企业级 AI 智能体进阶指南
java·人工智能·架构
tqs_1234513 小时前
AI后端服务高性能架构:GPU独立部署、算力解耦、弹性伸缩实战
人工智能·架构
谁在黄金彼岸14 小时前
Windows 远程桌面(RDP)是怎么建立的
架构
leeyi14 小时前
数据库迁移不翻车:golang-migrate 实战,143 个 DDL 有序执行(第97篇-E83)
go·aigc·agent
程序员贺加贝14 小时前
库存不是一个数字:从 On Hand 到 Available、Reserved 的销售订单库存预留设计
架构·saas
博、、14 小时前
本地AI智慧电商平台定制开发:技术架构与实战指南
人工智能·架构
老郑聊AI业财智造14 小时前
数据不搬家,也能做检索:Milvus的“湖原生”架构革命
人工智能·ai·架构·软件工程·软件构建·milvus
shiyi.十一15 小时前
第8章:计算机网络中的安全 — 知识要点与架构
计算机网络·安全·架构