Skip to content

fix: drop hostUsageCredit — report provider-measured usage only (#660) - #691

Merged
ranxianglei merged 3 commits into
masterfrom
2026-09-10_host-usage-postfold-default
Sep 11, 2026
Merged

fix: drop hostUsageCredit — report provider-measured usage only (#660)#691
ranxianglei merged 3 commits into
masterfrom
2026-09-10_host-usage-postfold-default

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Sep 10, 2026

Copy link
Copy Markdown
Owner

What

Implements issue #660: the post-fold provider measurement is now the only usage reported to any host — the hostUsageCredit option (and the entire baseline-backfill machinery behind it) is deleted.

Two commits:

Why delete instead of flip the default

The backfill number is a virtual cumulative estimate the model never receives:

  1. It drifts turn-to-turn (kernel re-stacks blocks; est(original)−est(processed) varies with range placement → meter can decrease on no-compress turns).
  2. It can exceed the context window (repro: 1315 > 950K = 138%).
  3. Every host that already had correct values (pi/omp via plugin, codex via UA) needed a gate — a growing per-client allowlist, and ZCode (ZCode 宿主 usage 回填未压缩基线:压缩后上下文显示成累加值,非实际转发量(v0.1.88 起;#645 的 ZCode 面) #648) slipped through.
  4. It contradicts bili's own [acp-usage] ledger line (input = the provider-measured post-fold value).

Provider-side counting after the fold is exact by construction (sglang / OpenAI / anthropic all count the folded bytes that actually went out), which is why #589/#644/#649 all converge on "forward the provider number as-is".

The internal stats ledger (session.stats / [acp-usage]) is untouched — that path was always verbatim.

Docs & tests

README, AGENTS.md, exit-matrix doc, CHANGELOG note rewritten. tests/host-usage-backfill.test.ts renamed → tests/host-usage-postfold.test.ts, re-pointed at the verbatim-forwarding contract (unit: strip/pipe passthrough + split semantics retained; e2e: pi/omp/zcode/codex clusters flipped from "suppressed" to "the rule"; openai-chat prepareOpenai assertion flipped). Issue#589 test suite updated to raw-frame forwarding.

Pre-flight

  • npm run typecheck
  • npm test: 985 pass / 0 fail (incl. all 5 e2e clusters)
  • npm run build
  • Zero references to removed symbols repo-wide (git grep) ✓

⚠️ Bug 历史教训:hostUsageCredit 为什么被整体删除(写给未来)

#408 的 baseline backfill 不是「默认值选错」,而是设计之初就错——backfill 的本意就是展示一个模型永远收不到的数字。每次 prepare 请求时计算 credit = max(0, est(originalMessages) − est(processedMessages))(原始历史 token 估计 − 折叠后转发视图),写入 session.hostCreditTokens,下轮请求开头清零,宿主可见 usage = total + credit。后续所有修复都只是在这一个 arm 调用前多加一条 early-return 豁免,没有一次质疑过机制本身:

Commit 修法(实际 diff) 定性
06e7fb1+80a9f89#408 实现) 三处 prepare 内联无条件写入 credit、计入宿主 usage —— 对所有宿主,含模型根本收不到该数字的插件模式 起源:设计意图本身是错的
12d62b6#590 把三处内联 credit 收敛进 armHostUsageCredit(),函数首行加 if (pluginAgent === "pi") return;(症状:pi 页脚 302.7%;pi 插件模式压缩由宿主本地执行,baseline 不驱动任何东西) 第一次豁免(按 agent 类型)
b71f6e8#623 条件扩成 "pi" || "omp" return(症状:omp 205%,同类 MCP/plugin 会话) 第二次豁免
6bc8eaa+941d0b2#645 bili 启动的 codex 携带 pluginAgent:"mcp"(与 claude 撞车,agent 类型门会误伤 claude)→ 改按 UA 检测:if (isCodexClient(headers)) return;,并把 req.headers 穿线到全部调用点;941d0b2"codex" 宽松子串兜底防新变体漏检 第三次豁免(判据从"是谁"滑向"UA 长什么样")
2858db0+6fba944#648 ZCode 这类纯代理客户端无 header/UA 信号可写规则 → 引入全局开关 hostUsageCredit: "auto"|"off"(env BILI_HOST_USAGE_CREDIT),函数首行 if (hostUsageCredit === "off") return;,想拿真值的用户自己 opt-out bug 被固化成配置项
8c9367c(本 PR v1) resolveHostUsagePolicy map 替换 if 链,默认翻转为 postfold,opencode 入表 仍保留 bug 选项
a49270d 删除整个机制(-379 行):arm 函数、credit 字段与计数器、四道豁免门、开关/env/web UI;后折叠 provider 实测计量成为唯一模式 本次交付

旁证(可复现):ZCode 用户症状链 —— 上下文条 4%→37% 虚高、纯追加轮 11→14 跳涨且非单调、模型侧实际只有 ~4K —— 逐条对应 est(original)−est(processed) 语义 + 内核块重组导致的漂移;bili 自己的 [acp-usage] input= 行一直记录真实转发值,两个数字必然有一个是谎话。

识别「虚拟数字」的三个判据(全中就该删,而不是做成可选项):

  1. 模型永远收不到它(模型侧 ~4K vs 宿主演示 36K);
  2. 随轮次漂移(内核重组块 → est(original)−est(processed) 变化;纯追加轮甚至能递减);
  3. 能超过物理上限(复现 1315 > 950K 窗口)。

教训:当一个数字错了,先问「这个数字的来源是否在我们系统的真值集合里」,而不是先问「哪些客户端会看到它」。provider 侧计量天然在真值集合内(它数的是折叠后真正发出的字节)。豁免名单只会单调增长(pi → omp → codex → ZCode 写不出 → 开关兜底),每新增一个宿主变体都可能漏一格;开关出现的那一刻就是豁免法失败的证明——默认值仍在对未知的未来客户端撒谎。一个配置选项的保留成本由未来所有 bug 持续支付,删除成本是一次性的。

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown

📦 Built Package Artifact

Branch: 2026-09-10_host-usage-postfold-default (ef8967f)

Option A — Install from npm PR tag (recommended)

npm install -g billion-context@pr-691

Each push to this PR publishes a new version under the pr-691 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr691.tgz
npm install -g package

This comment is automatically updated on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Reviewing now.

Confirmed shape: a single clean commit (8c9367c) directly on top of current master (1d09d5b, v0.1.101), touching exactly four files — src/config.ts, src/server.ts, CONFIGURATION.md, tests/host-usage-backfill.test.ts. No stray/generated files, no unrelated churn.

I'm independently re-running the pre-flight (typecheck / test / build) and tracing the wire behavior in both compression modes (plugin vs proxy) per AGENTS.md §6, plus checking for leftover references to the old "auto"/"off" values. Will post concrete findings + a mergeability verdict next.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Review complete — mergeable, with one narrow backward-compat edge worth your sign-off.

Independent pre-flight (re-ran on review-691 at 8c9367c):

  • npm run typecheck — clean
  • npm test — 1319 pass / 0 fail / 2 skipped (e2e-gated) ✓ matches your numbers
  • npm run build — success

Diff cleanliness (first gate): single commit straight on top of current master (1d09d5b), 4 files, every hunk on-purpose. No generated files, no unrelated churn, no whitespace noise. Passes.

Correctness checks I ran beyond reading the diff:

  • The raw string is interpreted in exactly one place (parseHostUsageCredit); every other site uses the typed HostUsagePolicy. Grep confirms no leftover "auto"/"off" comparisons anywhere in src/, and all three armHostUsageCredit call sites dropped the headers argument consistently.
  • Display-only invariant holds. hostCreditTokens flows only into host-facing reporting: hostContextTokens = realTotal + creditplugin.ts:452/472 (status). Nudge and preflight read the real post-fold counts, never the credit — so your acceptance criterion ("internal ledger / nudge / preflight always post-fold regardless of display policy") is intact.
  • Wire tests pin both sides on both wires (anthropic/ZCode + responses/codex): default→folded, baseline→uncompressed, plus a canonical+legacy parse unit test. Good coverage.

Findings (none blocking):

  1. Legacy autobaseline silently drops the pi/omp/codex exemptions. Old auto meant "smart default with per-host exemptions"; the new alias maps it to unconditional baseline. So a user who explicitly set hostUsageCredit: "auto" and runs bili-launched pi/omp/codex regresses to the >100% drift that pi plugin 模式宿主 usage 回填未压缩基线:footer 显示 302.7%/1M 与实际请求(折叠后 ~57K)不符 #590/omp 插件会话原生压缩被扩展全部取消后仍收 #408 usage 回填: omp footer 只增不减 (205%/1M) #623/[Question] Previously, Codex displayed the context window size after compression, but it now appears to show an unexpected/incorrect value. #645 fixed. Users who set nothing are safe (they get the new postfold default). Blast radius is small — it requires having hand-written the old default value — but your "explicit user choices are preserved" line is slightly overstated for this combo. My call: acceptable to ship; guarding it fights the whole point of killing the whack-a-mole. If you want zero regression, the minimal fix is HOST_USAGE_POLICY = { pi: "postfold", omp: "postfold" } (codex stays unkeyable — see fix: address all code review findings (condense, routing, session-id, dead code) #2).

  2. HOST_USAGE_POLICY cannot target codex. It keys on session.metadata.pluginAgent, but bili-launched codex announces pluginAgent:"mcp", shared with claude (confirmed at src/mcp.ts:188). So the documented "add a host = one map entry" escape hatch can't single out codex — a {mcp:…} entry would hit claude too. The old code used UA (isCodexClient), which this PR removes. Shipped default is unaffected (codex folds by default), so this is latent — but the extensibility story has a hole for the one host that needed UA-level disambiguation. Worth a one-line code comment so the next person doesn't assume the map covers codex.

  3. No CHANGELOG entry for the Redesign #408 host-usage backfill: post-fold by default, baseline opt-in (opencode gap + whack-a-mole exemptions) #660 flip. The existing [Question] Previously, Codex displayed the context window size after compression, but it now appears to show an unexpected/incorrect value. #645/ZCode 宿主 usage 回填未压缩基线:压缩后上下文显示成累加值,非实际转发量(v0.1.88 起;#645 的 ZCode 面) #648 entries describe the old default/exemption model. If you add changelog lines per landed feature, a short note keeps the record coherent. (Skip if changelog is curated at release time.)

I did not push anything — no changes to the branch. Happy to land the #2 clarifying comment (and optionally the #1 map seed) directly on the branch if you want them in before merge.


中文摘要:PR #691 已独立复验(typecheck 干净、测试 1319 通过、构建成功,diff 干净无杂项),核心改动正确且「信用仅用于展示、内部账本恒为折叠后值」这一不变量成立,可以合并;唯一需你拍板的是遗留 autobaseline 会让「显式写了旧默认值且跑 bili pi/omp/codex」的用户回退到 >100% 漂移(影响面很小,我倾向接受),另提示 HOST_USAGE_POLICY 因 codex 与 claude 共用 pluginAgent:"mcp" 而无法单独覆盖 codex(潜在限制,建议补一行注释)。

@ranxianglei ranxianglei changed the title feat: report post-fold host usage by default; make baseline opt-in (#660) fix: drop hostUsageCredit — report provider-measured usage only (#660) Sep 11, 2026
ework-agent and others added 3 commits September 11, 2026 22:37
)

Flip the #408 host-usage backfill default from baseline to post-fold: the usage reported to every host is now the actually-forwarded (folded) request — the tokens the model really receives — which is sane for any display and fixes the >100% drift that hit pi/omp/codex/ZCode when shown the uncompressed baseline.

config: hostUsageCredit values are now postfold|baseline (default postfold); legacy auto->baseline and off->postfold still parse so existing configs keep their chosen behavior.

server: armHostUsageCredit resolves via resolveHostUsagePolicy (a per-host map keyed on the announced agent type, falling back to the global switch) instead of a hard-coded pi/omp/codex exemption chain. Adding a host = one map entry, not a new if. opencode (a plain proxy client that never registers) now gets post-fold by default, closing the gap noted in #660.

tests: wire-level regression for the default-postfold path (plain client) plus baseline opt-in controls; parser unit test. docs: CONFIGURATION.md BILI_HOST_USAGE_CREDIT row updated.

Fixes #660
The opt-in baseline backfill remained a bug after every gate existed:
a virtual number the model never receives (model sees ~4K, host sees
36K), drifting turn-to-turn as the kernel re-stacks blocks, able to
exceed the context window (repro 1315 > 950K), and contradicting our
own [acp-usage] ledger line. Post-fold provider measurement is already
correct on every backend (sglang / OpenAI / anthropic) because the
provider counts the exact folded body — so the entire baseline
machinery is deleted: config switch + env var + web UI field,
backfillHostUsage + estimateTokensOfMessagesFromWire +
buildUncompressedContextEstimate, the credit field and both session
counters, and all four suppression gates (#590/#623 pluginAgent,
ledger ([acp-usage]) is untouched. Net -379 lines; docs rewritten
(README/AGENTS/exit-matrix/CHANGELOG note); tests renamed to
host-usage-postfold and re-pointed at the verbatim-forwarding contract
(pi/omp/zcode/codex e2e flipped from "suppressed" to "the rule").

Pre-flight: npm run typecheck ✓; full suite 985 pass / 0 fail
(incl. 5 e2e clusters); npm run build ✓.
The option no longer exists after a49270d deleted the mechanism; CONFIGURATION.md still described it (stale since 8c9367c) and CONFIGURATION.zh-CN.md never got a counterpart row (#648 documented the option in English only). Both tables now carry the removal note. Legacy values in env/file config are ignored (config parser only reads known keys).
@ranxianglei
ranxianglei force-pushed the 2026-09-10_host-usage-postfold-default branch 3 times, most recently from c9ead44 to ef8967f Compare September 11, 2026 15:00
@ranxianglei
ranxianglei merged commit 09a5247 into master Sep 11, 2026
12 checks passed
@ranxianglei ranxianglei mentioned this pull request Sep 11, 2026
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.

1 participant