Claude 与 Codex 的用量缓存要按服务商分别计时

桌面端的用量视图需要缓存,用来应付冷启动和临时的网络失败。危险的捷径是给整份快照配一个新鲜度时间戳。如果 Claude 刷新成功而 Codex 失败,用一个新时间戳重写文件,就会悄悄延长过期 Codex 数据的寿命

解法是把新鲜度建模在和失败同一条边界上:每家服务商一个时间戳,再加一条关于「什么才算可缓存数据」的保守规则

把数值和新鲜度存在一起

Agent Island v1.7.1 定义的快照包含 Claude 数据、Codex 数据、一个用于兼容的整体时间戳,以及各自独立的 claudeUpdatedAtcodexUpdatedAt 字段。更老的快照可以退回到旧时间戳,而新写入会保住每家服务商真实的年龄

snapshot = {
  claude,
  codex,
  updatedAt,
  claudeUpdatedAt,
  codexUpdatedAt
}

整体时间戳对解码旧记录和快速拒绝仍然有用,但它不授权两家服务商的数值一起恢复

不要把错误当成新鲜数据缓存

只有当相关窗口没有错误、并且至少存在一个真实信号(一个正的百分比,或者一个重置时间戳)时,某家服务商的结果才可缓存。一个套餐标签加两个 0% 的窗口是不够的。没有这道闸门,一次认证失败或空响应就会被存成一个看起来很干净的 0%

带错误的数值也要拒绝,哪怕它们保留着上一次成功抓取的百分比。这些百分比对当前这块屏幕可能有用,但把它们存到新的时间之下,等于把过期数据洗成一条新鲜的缓存记录

部分成功可以保留,但不能续期

假设 Claude 返回了新鲜结果而 Codex 超时。快照可以存下 Claude 的新值,同时把上一个有效的 Codex 值带过来。时间戳必须说实话:

claude 数值: 新的        claudeUpdatedAt: 现在
codex 数值: 沿用旧的     codexUpdatedAt: 旧时间戳

如果两家都没有产出新鲜的可缓存数据,就不写新快照。这防止反复失败的刷新把缓存无限延长。没有被抓取的服务商遵循同一条规则:它可以保住一个有效的既有数值,但绝不会仅仅因为同伴被抓取了,就拿到一个新鲜时间戳

让每家服务商各自过期

恢复检查会把每家服务商的时间戳与最大年龄比较。可能一家恢复了,另一家变空。这样在部分故障期间缓存仍然有用,同时不会让两个数值以同样的置信度呈现

这条策略也应付得了 schema 演进。Codex 在 2026 年 7 月的响应里可能只含一个有意义的用量窗口,同时把次要窗口标为不存在。只要那个真实窗口带有用量或重置数据,这种形状仍然可缓存。要求两个窗口都填满,会把一个合法的服务商响应变成永久的缓存未命中

能抓到「时间戳洗白」的策略测试

  1. 带错误的沿用用量既不能创建也不能续期快照
  2. 只有套餐、百分比全 0 的数据不能作为健康用量缓存或恢复
  3. 真实用量保住它的百分比和重置时间,同时剥掉缓存里的错误
  4. 一个新鲜的 Claude 结果保留更旧的 Codex 值,且不改动 Codex 的时间戳
  5. 没有被抓取的服务商永远拿不到新鲜时间戳
  6. 恢复时可以保住一家、让另一家过期
  7. 合法的单窗口服务商形状仍然可缓存

产品与测量的边界

这条缓存策略存在于打了 tag 的 macOS 与 Windows v1.7.1 源码里,并有对应测试。用户可见的 macOS 用量界面已验证。Windows 上存在这条策略,本身并不能证明每一处 Windows 用量界面的行为,那需要单独的界面验证

用量百分比和本地 API 价值估算同样不是订阅账单、不是省下的钱、不是收入、不是用户数、也不是安装量。缓存的正确性提升的是显示的诚实度,不是底层指标的含义

实现可以在公开的 Agent Island v1.7.1 源码里看到。可复用的规则很简单:把新鲜度限定在会失败的那个依赖上、永远不给你没抓取过的数据续期,以及在把空响应变成 0% 之前先要证据