一份本地用量台账可以同时把同一段 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 的周工作报告,或者 下载当前版本
