Skip to content

fix(token-usage): Pi 会话补充上下文用量与百分比(卡片页脚) - #898

Open
Barrierml wants to merge 2 commits into
deepcoldy:masterfrom
Barrierml:fix/pi-context-usage
Open

fix(token-usage): Pi 会话补充上下文用量与百分比(卡片页脚)#898
Barrierml wants to merge 2 commits into
deepcoldy:masterfrom
Barrierml:fix/pi-context-usage

Conversation

@Barrierml

Copy link
Copy Markdown
Contributor

背景

pi 会话在 botmux 回复卡片上不显示「上下文 N/M (P%)」页脚,codex/claude 均正常。根因:foldPiLine 只累计 input/output/cacheRead/cacheWrite 用于成本统计,从不生成 latestContextUsage,因此 getSessionUsageSnapshot().context 恒为 null。

改动

  • src/core/cost-calculator.ts
    • foldPiLine 按 claude 同口径(input + cacheRead + cacheWrite)计算最新一搏的上下文占用并写入 agg.latestContextUsage;空 usage 的合成记录不覆盖上次测量
    • 窗口信息(windowTokens / percentUsed)从 ~/.pi/agent/models.json 读取(mtime+size 缓存,避免逐行重读)。模型 id 兼容 provider/modelmodel:variant 形态;models.json 缺失/不可解析时降级为仅 usedTokens(无百分比),与 claude 行为一致
    • __resetSessionUsageCachesForTest 顺带重置 piModelsCache
  • test/cost-calculator.test.ts:新增 3 条 pi 上下文单测(无 models.json 降级 / 有 models.json 出百分比 / 变体模型 id 归一化)

验证

  • test/cost-calculator.test.ts 56 通过;test/cost-calculator-cache.test.ts + bounded-widen 49 通过
  • tsc --noEmit 通过

备注

pi 的 JSONL 只含每搏增量 usage,无窗口字段,百分比口径为「最近一搏 prompt 侧 tokens / 模型 contextWindow」,与卡片页脚「最新上下文」语义一致。

foldPiLine 此前只累计 input/output/cache 用于成本统计,从不生成
latestContextUsage,导致 pi 会话的回复卡片缺失「上下文 N/M (P%)」
页脚(codex/claude 均正常)。

- foldPiLine 按 claude 同口径(input+cacheRead+cacheWrite)计算最新
  一搏的上下文占用并写入 latestContextUsage
- 窗口信息从 ~/.pi/agent/models.json 读取(mtime+size 缓存),模型 id
  兼容 provider/model 与 model:variant 形态;找不到配置时降级为仅
  显示 usedTokens,与 claude 行为一致
- __resetSessionUsageCachesForTest 顺带重置 piModelsCache

配套单测:无 models.json 降级、有 models.json 出百分比、变体模型 id
归一化匹配。
@Barrierml
Barrierml requested a review from deepcoldy as a code owner August 16, 2026 16:08
@deepcoldy

deepcoldy commented Aug 17, 2026

Copy link
Copy Markdown
Owner

自动化初步复审发现两处建议修正后再合入的问题(最终以维护者审阅为准):

  1. foldPiLine 当前把 usedTokens 计算为 input + cacheRead + cacheWrite,少算了本次 assistant 的 output。Pi 0.84.0 自身的 calculateContextTokens() 口径是优先使用 usage.totalTokens,否则回退为 input + output + cacheRead + cacheWrite。本机真实 transcript 的末条 usage 为 input=11684, output=33, totalTokens=11717,当前实现返回 11684,而 Pi 原生上下文值是 11717input 确实不含缓存,继续加 cacheRead/cacheWrite 不会双算;问题仅在遗漏 output。建议优先采用有效的 totalTokens,缺失时再按四项求和,并把现有窗口测试的预期一并改为包含 output。

  2. models.json 的模型身份是 (provider, model id),真实 transcript 也分别记录 message.providermessage.model;当前却把所有 provider 的模型压到只按 model.id 索引的单个 Map。两个 provider 配置同名模型但窗口不同时,后遍历的配置会静默覆盖前者,随后可能显示错误百分比,而不是安全降级。建议优先按 message.provider + message.model 精确命中;若保留 bare-id 回退,应只在该 id 全局唯一时使用。

建议新增两类回归测试:

  • 带非零 output/totalTokens,直接锁定 Pi 原生上下文口径;当前新增测试都将 output 排除在 context 断言之外,因此没有捕获偏差。
  • 两个 provider 含相同 model id、不同 contextWindow,验证按 transcript provider 选择正确窗口。

补充核对结果:models.json 缺失或 JSON 畸形会被 try/catch 安全降级,不会抛出到卡片路径;Pi 属于非 Codex 的 append-only fold,latestContextUsageSource 只服务 Codex tracked replay,因此 Pi 不写该 source 不影响增量缓存。

- foldPiLine: prefer usage.totalTokens (Pi 0.84 native口径), fallback to
  input+output+cacheRead+cacheWrite (previous sum omitted output)
- models.json resolution keyed by provider+model; bare-id fallback only when
  the id is unambiguous across providers (different windows → degrade safely)
- tests: 3 existing Pi tests updated to include output; +3 new regression tests
  (totalTokens preference, provider-qualified window hit, ambiguous bare id)

Verified: tsc --noEmit clean; vitest 59/59; pnpm build clean.

Co-Authored-By: Claude <noreply@anthropic.com>
@Barrierml

Copy link
Copy Markdown
Contributor Author

两处复审意见已修正并推送(33b67128):

  1. totalTokens 口径foldPiLine 现在优先 usage.totalTokens,缺失时才回退 input+output+cacheRead+cacheWrite 四项和;3 条既有 Pi 测试的预期已改为含 output,并新增 1 条 totalTokens 优先的回归测试(模拟真实 0.84 transcript 尾部 input=11684, output=33, totalTokens=11717 → 断言 11717)。
  2. provider 维度:models.json 解析改为双索引(provider/model 精确键 + bare id);resolver 优先用 transcript 的 message.provider + message.model 精确命中;bare id 在不同 provider 窗口不一致时标记 ambiguous 并安全降级为 usedTokens-only(不再静默覆盖)。新增 2 条回归测试(provider 精确命中 / 冲突 id 降级)。

验证:tsc --noEmit 干净;vitest test/cost-calculator.test.ts 59/59 通过;pnpm build 干净。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants