World State 把“模型当前应知道的事实”拆成有稳定 ID 的分区。每个分区独立定义紧凑 Snapshot 和差异渲染;整个 Snapshot 则用 JSON 对象持久化,并用 RFC 7386 Merge Patch 推进基线。模型读自然语言片段,Rollout 记结构化状态,两条输出不能混淆。
分区是类型擦除后的有序表
WorldState 内部按插入顺序保存 section。内建分区与 Extension 分区最终都实现同一擦除接口:生成可选 Snapshot、识别遗留片段、判断保留片段和相对旧值渲染差异。
class WorldStateSection(Protocol):
id: str
def snapshot(self) -> JsonValue: ...
def should_persist(self) -> bool: ...
def render_diff(self, previous: PreviousState) -> ContextFragment | None: ...
class WorldState:
sections: OrderedDict[str, WorldStateSection]
Snapshot 不能为 JSON null,因为 Merge Patch 用 null 表示删除对象字段。序列化前会移除对象内部的 null 字段;类型恢复失败时,分区得到 Unknown,应渲染足够完整的说明,而不是假装已知旧值。
三态比较比 Option 更精确
PreviousSectionState 有 Absent、Unknown、Known(value) 三种状态。Absent 表示旧状态明确没有该分区;Unknown 表示保留历史可能含有它,但无法恢复类型化快照;Known 才允许精确增量。
def diff_world_state(previous, current):
fragments = []
for section in current.sections_in_order():
old = previous.lookup(section.id) if previous else Absent()
if fragment := section.render_diff(old):
fragments.append(fragment)
patch = json_merge_patch(previous.json, current.snapshot_json())
return fragments, None if patch == {} else patch
新分区写入 {id: value},变化分区替换该字段,消失分区写入 {id: null}。对象值的分区还能按子键增删,例如 Deferred Tool namespace 用对象 Snapshot,使 Patch 不必每次复制整张目录。
持久化顺序与恢复
正常更新先记录模型可见 fragments,再持久化 Full/Patch WorldState item。恢复时先重放历史,再推进 baseline,避免 Rollout 出现“状态已经改变但模型从未收到变化”的前缀。无差异时既不生成片段,也不写空 Patch。
ContextManager.replace() 会清空 baseline,因为替代历史未必仍含旧分区文本。正确性优先于节省一次完整重注入。
源码与测试锚点
codex-rs/core/src/context/world_state/mod.rs:分区接口、三态和 Snapshot。codex-rs/core/src/session/world_state.rs:有序装配内建/扩展分区。codex-rs/core/src/context_manager/history.rs:baseline、full/patch 选择。codex-rs/core/src/context/world_state/world_state_tests.rs:Merge Patch 与恢复测试。
评论
登录后即可评论