做一份不会重放出错的本地 Codex token 台账

一份本地用量台账可以同时把同一段 Codex 历史多算和少算。解决办法是把用量事件当成一条带重放与归档语义的流来处理,而不是一堆待求和的数字

第一个不对劲的迹象,是一次大到没法用价目漂移解释的对比。一份长期运行的 Codex rollout 比预期多贡献了好几亿 token。JSONL 是合法的,每个用量事件都能解析,没有任何明显损坏

错在一个假设上:以为一个合法的 last_token_usage 对象总是代表一个新的计费回合

同一个增量可能被上报不止一次

Codex 写的 token 计数事件带两种有用的用量视角。last_token_usage 描述最近一次增量,total_token_usage 是当前这次运行的累计计数器

在一次长会话里,运行时可能在累计计数器不前进的情况下重复上报最近那个增量。天真的扫描器看到又一个合法事件,就再加一次。在实测的一份 rollout 里,这些重复产生了大约 3.31 亿个幻影 token

那对累计值给了扫描器一把重放键:

此前累计: input=150, output=15
新的增量: input=50,  output=5
新的累计: input=150, output=15
判定:     重放,跳过这个增量

比较必须同时用累计输入和累计输出。如果这一对完全没变,那这个事件就是对已计入用量的一次重复上报

这条规则刻意比「单调递增」更窄。压缩会把累计计数器重置成更小的值,而一个更小的累计对仍然可能伴随一个新的、合法的增量,所以扫描器要计入它。更老的 Codex 版本可能根本没有 total_token_usage,那些事件也放行,因为没有可靠的重放信号

由此得到的不变式很简单:

累计对相同    -> 跳过
累计对前进    -> 计入
累计对变小    -> 按一次重置计入
没有累计对    -> 按旧数据计入

这条规则由一份专门的样本覆盖,含六个事件:两个原始回合、两次精确重放、一次压缩重置、一个旧式事件。必须活下来四个,合计 200 输入、20 输出 token

反方向的错误住在另一个目录里

去掉重放的增量修好了膨胀,但没有让台账变完整

Codex 会把更旧的 rollout 文件从 ~/.codex/sessions 移到 ~/.codex/archived_sessions。只走活跃目录树的扫描器,会在会话一被归档时就悄悄丢掉历史。在一份本地数据集上,有 25 亿个 7 月的 token 只存在于归档目录树里

读取器现在两个根都走:

~/.codex/sessions
~/.codex/archived_sessions

两边用同一套截止时间、文件过滤、解析器和缓存。这很要紧,因为支持归档不该造出第二条行为不同的记账路径。一份 rollout 就是一份 rollout,不管它此刻归哪个生命周期目录管

这两个 bug 把总数推向相反方向:重放让活跃文件虚高,忽略归档则把旧文件删掉。任何一个都可能部分掩盖另一个,让一次粗略比对看起来还算合理

流式处理比聪明的 JSON 更重要

rollout 文件不是整洁的记账导出。它们含有工具输出、截图和其它可能有好几 MB 的响应条目。记账相关的记录只是很小的一部分:turn-context 行确定当前模型,token-count 行携带用量

因此扫描器带着体积兜底逐行流式读取,并在 JSON 解析之前先做一次廉价的字节标记检查。不可能含有这些标记的超大记录,在被拼成内存里的大字符串之前就被跳过。已解析的文件按路径、修改时间和大小缓存,所以稳态刷新不会去重读没变过的会话

这个设计让台账留在本地,同时不至于每次刷新都变成一次完整的历史导入

归属到哪一天,是一个产品决定

处理完重放和归档之后,两个读同一批文件的工具之间可能还有一处差别:一个可能把所有 token 都归到会话的开始日期,另一个则用每个事件自己的时间戳

Agent Island 用事件时间,按用户本地时区。一个跨过午夜的会话会同时给两天贡献用量。把整个文件归到它的开始日更省事,但那会把后来的工作往前挪,对长期运行的会话来说,可能把周视图或月视图扭曲得很厉害

选哪个时间戳都不会改变累计总量,改变的是日线图讲出来的故事

这份台账仍然不能承诺什么

本地 token 事件支撑的是一个用量估算,它不提供账单

模型价目表会过时;服务商计费可能套用本地日志里没有体现的规则;缓存输入需要与非缓存输入不同的费率;早期事件可能出现在模型上下文之前,需要一条写明的兜底。界面应该把结果叫作 API 价值估算,而不是确切花费,也不是与服务商面板的对账结果

更大的教训关于事件语义。解析只是第一步。一份值得信任的本地台账还需要知道:一个事件什么时候算新的、旧文件被移到了哪里、哪个时间戳拥有这笔用量,以及源数据支撑不了哪些说法

Agent Island 1.7.1 在 macOS 与 Windows 上都包含重放保护与归档扫描。项目免费、MIT 许可,会话记账留在用户自己的机器上。想看这份台账怎么变成 Claude Code 与 Codex 的周工作报告,或者 下载当前版本