雨天小六

读懂 Codex(4.15):ContextManager 的原始历史所有权

· 更新于 2026-08-02 · 专栏:读懂 Codex

#Codex#Agent Runtime#Prompt#上下文工程#软件架构

ContextManager 是 Session 内原始 History 的唯一结构化所有者。它按最旧到最新保存 ResponseItem,同时持有 token usage、History version、TurnContext 引用项和 World State baseline。调用方可以克隆快照用于请求,却不应绕过它直接改 Session History。

Arc 提供写时复制快照

History items 存在 Arc<Vec<ResponseItem>> 中。clone_history() 只克隆 Arc 和元数据,多个只读消费者共享同一向量;真正追加、删除或规范化时通过 Arc::make_mut 复制。这样一次采样可以拿稳定快照,而 Session 继续接收事件时不会修改已经交给请求构造器的向量。

Session 持有 ContextManager,采样通过写时复制获得历史快照
图 4.15-1:所有权仍在 Session 的串行状态内,快照只分享不可变 items。任一分支需要修改时才复制底层 Vec。
class ContextManager:
    def __init__(self):
        self._items: PersistentVector[ResponseItem] = PersistentVector()
        self.history_version = 0
        self.token_info = None
        self.reference_context_item = None
        self.world_state_baseline = None

    def snapshot(self) -> "ContextManager":
        return shallow_copy_sharing_items(self)

Python 复刻不必模拟 Rust Arc,可以在 Session 锁内复制不可变 tuple,或让 History actor 串行处理命令。关键契约是“请求快照一旦捕获就不被活动 Session 原地改变”。

原始历史与 Prompt 投影

raw_items() 返回持久化语义下的真实项目;for_prompt() 消费一个 ContextManager 快照,在副本上补配对、删孤儿、降级媒体,最终返回模型可接受项目。合成修复不写回原始 History。

原始 History 投影为一次请求专用 Prompt History
图 4.15-2:Rollout 事实与请求协议分离。一次中断可以在原始历史中留下半对调用,Prompt 投影会补成完整对,但不会伪造持久化工具结果。
def for_prompt(snapshot, modalities):
    items = list(snapshot.raw_items)
    ensure_call_outputs_present(items)
    remove_orphan_outputs(items)
    normalize_media(items, modalities)
    return items

附属状态为什么也归它所有

Token usage 必须与 History 边界一起更新,World State baseline 必须在 History 重写时清空,reference context item 又决定下一 Turn 能否发差异。若分散在多个互不协调对象里,压缩只替换 items 却忘记清基线,就会产生模型视图缺口。

源码与测试锚点

  • codex-rs/core/src/context_manager/history.rs::ContextManager
  • codex-rs/core/src/session/mod.rs::clone_history
  • codex-rs/core/src/context_manager/history_tests.rs:快照、baseline 与规范化。

评论


← 返回文章列表