$ cat zh/blog/codex-token-replay-guard

构建不会重复计数的本地 Codex Token 台账

Codex 使用台账可能同时高估和低估同一段历史。要把使用事件当成带重放与归档语义的流,而不是一堆直接相加的数字。

本地 JSONL 很适合做个人工作台账,但“找到所有 token 数字再求和”会很快出错。流式客户端可能重复报告累计值,旧会话还可能从活跃目录移到归档目录。

同一个增量可能被报告多次

先区分累计快照与真正增量。若记录给出累计总数,应对同一会话按顺序求差,并在数值回退、进程重启或回放时建立新段。去重键至少包含会话、事件类型、顺序或时间以及原始数值。

漏算往往藏在另一个目录

只扫当前会话目录会低估历史使用。归档目录必须进入同一条读取管线,同时通过稳定会话标识去重,避免活跃文件与归档副本各算一次。

流式读取比聪明的 JSON 更重要

大型 JSONL 文件不应整体载入内存。逐行读取、容忍最后一行尚未写完,并把解析游标与文件身份保存到本地缓存。遇到截断或格式错误时跳过并记录,而不是把整个台账判废。

归属时间是一项产品决定

按文件修改时间归属某一天会被归档操作扭曲。优先使用 usage 事件自身的时间;缺失时才降级。跨时区展示要明确按本地日历还是 UTC,周报边界也必须一致。

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

本地 token 数量和按公开费率计算的 API value 都不等于订阅账单、节省金额或收入。缓存 token、供应商费率与记录缺失都会影响估计。关于数值口径,可继续阅读API value 到底代表什么

如何识别一次重放

不要只按时间戳去重,因为两个真实事件可能共享同一秒。更可靠的键来自会话标识、事件类别、流内顺序和累计值组合。若累计值完全重复且没有新回合证据,可以忽略;若数值回退,则开启新段并保留原因,避免产生负增量。

应当保留的审计字段

最终日报旁边应能找到使用事件时间、读取来源、原始输入/缓存/输出字段、去重决定和采用的时区。用户不一定每天查看这些信息,但一旦总数异常,这些字段决定了台账能否被解释和修正。