Skip to content

fix: stitched-stream usage double-count after compress re-request (adapter-anthropic >0 guard) #300

Description

@ranxianglei

Model: glm-5.3

压缩重请求后的拼接流导致下游 usage 双计(假 EMERGENCY)

证据(issue #292 日志)

13:26:21.161Z [366af3e19c251c72] [acp-usage] round 1 input=261206 cached=118663 (cache hit 45%)
13:26:21.250Z [366af3e19c251c72] nudge INJECT T1: usage=131% (261206/200000) ... reason="EMERGENCY T1"

261206 = 142543 + 118663 精确对上。机制:内层执行 compress 后向上游重请求,返回下游的流是两轮拼接:round 1 的 message_start(cache_read=118663)+ 合成 terminal(input_tokens=142543, cache_read=0)。下游解析只在 > 0 时更新(src/loop/adapter-anthropic.ts:297-299),terminal 的 0 无法覆盖 round 1 旧值 → 142543 + 118663 双计 → 131% 假超窗 → 误触发 EMERGENCY nudge + preflight 压缩。

该守卫本身有正当理由(src/loop/adapter-anthropic.ts:291-296 注释:部分 relay 会在 message_delta 回显 input_tokens: 0,采纳会低估上下文、压缩永不触发),不能简单去掉。

修复要求(两层任一或组合,建议都做)

  1. 生成侧(治本):acp-loop 多轮拼接流的合成 terminal 携带完整权威 usageinput_tokens + cache_read_input_tokens 都填终轮真实值),让下游能原子采纳
  2. 解析侧(防御)adapter-anthropic.tsmessage_delta/terminal 的 usage 对象同时含 input_tokens(>0)与 cache_read_input_tokens 字段时,按完整对象原子更新(0 值可覆盖旧值);仅当字段残缺时维持现行 >0 守卫

验收(单测)

构造拼接流:round1 message_start(input=50000, cache_read=118663)+ 合成 terminal(input=142543, cache_read=0)→ 断言记录的总输入为 142543(非 261206);再构造 relay 回显 input_tokens:0 场景 → 断言不覆盖 message_start 真值(现行行为保持)。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions