You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
不受影响:wire 上的工具名字节一个都不改(只改内部比较,不动保真);message-id/ref 编号、渲染 tag 格式、token 快照、nudge 节奏全不变;prefix-cache 稳态字节不变(只改「哪些工具结果够格进最近区排除」这个决策,不改任何渲染输出)。
结论:单调增宽,无回归面,唯一边界情形方向保守,可以安全落地。
二、read 工具是否应默认保护
先厘清「默认」。当前设计里 read 在 NEVER_PRESERVE_RECENT_TOOLS(内核常量注释写明理由:file/image contents — the largest common source of context bloat),即 read 结果默认被排除出受保护最近区 = 立即可压缩。这是刻意设计,不是 bug。
Activity
ranxianglei commentedon Sep 30, 2026
[bot] 🏷
已按源码逐行核实——这个「失效」是真实 bug,根因在 acp-kernel 的一个比较函数上。先给结论,再给统一方案。
一、根因(已在源码层确认)
acp-kernel 里所有工具名匹配都走同一个比较器
matchToolPattern(dist/index.js):两个分支都大小写敏感。它同时支撑全部工具名旋钮:
protectedTools/protectedLatestTools/neverPreserveRecentTools(最近区排除)/preserveRecentTools(正向豁免),以及 absorb、ccr 的excludeTools(同样调这个函数)。内置默认排除表是小写
["decompress","search_context","read","bash"](kernelNEVER_PRESERVE_RECENT_TOOLS)。bili 侧对工具名零归一化(我全局查过,所有toLowerCase都在处理 host/header/env,没有一个碰工具名),wire 上的名字原样进 kernel。于是:read)Read)read"Read" !== "read")→ Read 结果默认就受保护preserveRecentTools:["read"]read从表里划掉 → 行为改变这就是你截图那张对照表的机制,我在源码层验证成立。你机器上「参数没效果」不是参数坏了,而是大小写对不上让那条规则在你这成了死条款。
二、统一方案(建议,均不新增用户配置面)
问题分两层:① 纯大小写差异(本次报的;主流客户端 opencode / Claude / ZCode 基本都属于这类);② 完全不同的名字(你说的「名字可能还不一样」,主要出现在 codex 系这种工具词汇表不同的 harness)。
Phase 1 —— 根因修复:把
matchToolPattern改成大小写不敏感(两侧统一 casefold 后比较)。read/bash)。Phase 2 ——(可选,待数据)完全异名的规范化别名表:把已知跨客户端同义名归一到 canonical token 后再匹配(如
shell/exec/run_command → bash)。三、需要你拍板的两点
(查重:open/closed issue 与 devlog 均无同类记录,是新问题。)
一句话:bug 属实,根子在 acp-kernel 那个大小写敏感的
matchToolPattern;最干净的统一解是先把它改成大小写不敏感(一处修好全部旋钮+默认表),完全异名的别名表等你给清单再说。ranxianglei commentedon Sep 30, 2026
直接提交pr修复吧 需要讨论如果改成大小写敏感会带来问题吗
另外read工具是不是应该默认保护
ranxianglei commentedon Sep 30, 2026
[bot] 🏷
好,开工。先把两个讨论点讲清楚,再说 PR 怎么落。
一、改成大小写不敏感会带来问题吗
核心安全性质是单调性:大小写不敏感只会「多匹配」,绝不「少匹配」——若旧逻辑
a === b成立,则a.toLowerCase() === b.toLowerCase()必成立。所以原来被保护的仍被保护、原来被排除的仍被排除,唯一差异是一些「只差大小写、过去匹配不上」的组合现在开始命中。所有旋钮共用同一个
matchToolPattern,一处改全部生效:neverPreserveRecentTools(最近区排除,本 bug)Read现在命中read→ 立即可压缩protectedToolsMyTool模式也命中mytoolpreserveRecentTools(正向豁免)["READ"]也能划掉内置read条目excludeTools唯一理论风险:某客户端真注册了两个只差大小写的不同工具(如同时有
Read与read)——一个模式会把它俩都命中。实际客户端几乎不会这么做;即便发生,过匹配方向也是「更保护 / crush 更少」,非破坏性。可接受。不受影响:wire 上的工具名字节一个都不改(只改内部比较,不动保真);message-id/ref 编号、渲染 tag 格式、token 快照、nudge 节奏全不变;prefix-cache 稳态字节不变(只改「哪些工具结果够格进最近区排除」这个决策,不改任何渲染输出)。
结论:单调增宽,无回归面,唯一边界情形方向保守,可以安全落地。
二、read 工具是否应默认保护
先厘清「默认」。当前设计里
read在NEVER_PRESERVE_RECENT_TOOLS(内核常量注释写明理由:file/image contents — the largest common source of context bloat),即 read 结果默认被排除出受保护最近区 = 立即可压缩。这是刻意设计,不是 bug。我的建议:维持现状(read 默认可压缩,不默认保护),理由是不对称成本:
search_context/ 命令输出,read 的可再生性最高,所以默认排它最划算。若你确实想让 read 默认受保护,那是产品级默认值变更(AGENTS.md 规定默认值变更必须人拍板),我可以把
read从内置表移除来实现;但我不建议全局这么干——真有需要的客户端用preserveRecentTools:["read"]按客户端开即可,而这个逃生口本次修复后也能跨客户端正常工作了。所以 #3 我倾向不改,除非你有具体场景坚持要默认保护,告诉我我再单列。
三、PR 怎么落(跨仓)
根因函数
matchToolPattern在 acp-kernel;bili 侧只是透传配置 + 在src/decompress-shared.ts:442调它一次。因此:matchToolPattern为两侧toLowerCase()后比较 + 补回归测试(Read命中read;computeProtectedRefs不再把新鲜Read结果算进保护区)。按内核规矩,这属 §7.3 契约(protected-tool / recent-zone 语义)+ 跨仓,需 ≥2 agent review + 人工合并,且内核要先发版。Fixes #1725)。我现在就去改 acp-kernel 并开 PR,稍后把链接贴回这里。#3 若要改默认,说一声我一并处理。
ranxianglei commentedon Sep 30, 2026
[bot] 🏷
PR 已提交(内核侧,根因所在):
ranxianglei/acp-kernel#484 —
fix(protected): match tool names case-insensitively across clients改法就是之前说的 Phase 1:把
matchToolPattern两侧toLowerCase()后比较。一处改动让全部六个旋钮(protectedTools/protectedLatestTools/ 最近区排除 /preserveRecentTools/ absorb、crush 的excludeTools)跨客户端统一生效。已验证(不是「应该能跑」):
tests/protect-recent.test.ts)——我把源码临时还原成旧版跑了一遍,这 5 条全部失败,再套上修复后全过,证明它们真能抓住这个 bug;src/protected.ts+ 测试),无版本改动、无无关改动。关于 #3(read 是否默认保护):我没动默认值。 本次只修比较器,
read仍按原设计被排除出最近区(默认可压缩)。若你要改成默认保护 read,那是产品级默认值变更,告诉我我单开一个改动。接下来的跨仓流程(需要你推进的部分):
Fixes #1725)——这步等内核发版才能绿,所以现在先停在这里。一句话:根因修复已进 acp-kernel#484 并验证通过(单调增宽、无回归面),read 默认行为未动;等你 review/合并并发版后我就把 billion-context 的 pin 提上来收尾。
ranxianglei commentedon Sep 30, 2026
[bot] 🏷
补一条最新状态(刚重新核过):
latest仍是0.0.98;PR release v0.1.75 #484 仍 open、未合并(mergeable_state: clean)。npm 上只有 CI 的 PR 预览包(0.0.98-pr.484.340)——billion-context 的精确 pin 不能指向-pr.预发布版,所以 billion-context 提 pin 这步仍被卡住,现在做只会指向未发布版本、开出红 PR,不提前。小结:
read的默认保护行为未动。下一步(需要你推进):#484 过 ≥2 agent review + 人工合并 → CI 发版上 npm → 我再 bump pin + 补 bili 侧回归测试 + 开
Fixes #1725的 PR 收尾。Merge pull request #1906 from ranxianglei/2026-10-02_kernel-pin-0.0.100
chore: pin acp-kernel 0.0.100 — case-insensitive tool protection (ran…
fix(rebase): keep master's acp-kernel 0.0.100 pin alongside the PR's …
fix(rebase): keep master's acp-kernel 0.0.100 pin alongside the PR's …
fix(rebase): keep master's acp-kernel 0.0.100 pin alongside the PR's …