Skip to content

feat: strip closed-turn thinking replay via kernel reasoningReplay (needs acp-kernel 0.0.60) - #338

Closed
ranxianglei wants to merge 4 commits into
masterfrom
2026-09-09_thinking-strip
Closed

feat: strip closed-turn thinking replay via kernel reasoningReplay (needs acp-kernel 0.0.60)#338
ranxianglei wants to merge 4 commits into
masterfrom
2026-09-09_thinking-strip

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Fixes #336
依赖 acp-kernel PR #225(需先发布 0.0.60 并在此 bump pin)。

变更

  1. 投影:assistant 消息的 thinking 块投影为 contentType: "reasoning" core,子 id base#r<n>(内核因此能看见并按策略剥离);带 thinking 的消息其 text/call core 一并转为子 id 形式(#t0/#callId),重建端按子 id 存活过滤。
  2. 重建:coreOutToAgentMessages 按存活的 base#r<n> 过滤原始 thinking 块(内核剥掉的不再透传回 pi);同时把内核改写过的 compress 调用文本(活范围过滤+summary 存根)同步回 toolCall arguments——此前内核瘦身对 pi 出口无效。
  3. 配置:AdapterConfig.reasoningReplay 默认 "open-round"(闭合轮次剥离),kill-switch "always"/"never",coreOverrides 优先。默认生效即修复 Protected-message exemption inflates the incompressible context floor: per-compression reasoning is never reclaimable (~83.5% of measured residual) #336 的不可压缩地板。

实测(真实风暴会话重放,sessionTokens ~168K)

指标 新(open-round)
出口视图(CJK-aware) ~155K 48.8K
thinking 回放 75.8K(70% 贴在 compress 锚点) 0.9K(仅开轮)
compress 调用 args 21.6K 16.5K(存根化)

测试:全套 628 pass + 新增 messages-reasoning 7 例(投影/剥离/重建过滤/配置默认)。

合并后待办

  • 等 acp-kernel 0.0.60 上 npm → 本仓库 bump package.json pin + lockfile + 发版(两版本字段提交)。

…needs acp-kernel 0.0.60)

Fixes #336 (requires acp-kernel PR #225)

- entriesToCoreMessages projects assistant thinking blocks as contentType
  'reasoning' cores with deterministic base#r<n> sub-ids; companion text/call
  cores shift to sub-id form when thinking exists so the rebuild can filter
  per sub-id survival.
- coreOutToAgentMessages filters original thinking blocks by surviving
  base#r<n> sub-ids, and syncs kernel-rewritten compress-call text (live-range
  filter + summary stubs) back into toolCall arguments.
- AdapterConfig.reasoningReplay defaults to 'open-round' (kill-switch
  'always'/'never', coreOverrides wins).

Measured on the storm session: outgoing view 155K→49K (thinking 75.8K→0.9K).
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 已接手。当前状态盘点:

阻塞点:acp-kernel 0.0.60 尚未上 npm

本 PR(#338,分支 2026-09-09_thinking-strip)现状

我现在做的:用 npm 上的 0.0.59-pr.225.76 dist 本地预验证(Agents.md §5 流程:overlay 到 node_modules → typecheck + test + build),确认代码对 0.0.60 就绪。

0.0.60 上 npm 后的动作(我会跟进):rebase master → bump pin 0.0.56→0.0.60 + lockfile → 全套检查 → push;之后人工合并本 PR,再走 v0.1.61 release 分支(两版本字段提交)。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 预验证完成(本地,使用 acp-kernel PR #225 的 CI 构建产物):

阻塞状态:acp-kernel 0.0.60 尚未上 npm(最新 stable 0.0.59)。acp-kernel PR #225 全绿(pr-validation / test 22 / test 24 / build-artifact 均 success)、mergeable clean、非 draft——只差合并与发布(合并 PR 是 human-only,我这边不能代劳)。

本地预验证(按 AGENTS.md 流程,将 acp-kernel@0.0.59-pr.225.76 的 dist 整体 overlay 到 node_modules/acp-kernel):

  • typecheck:✅ clean
  • test:✅ 628 pass / 0 fail / 3 skipped(与 issue 声明一致)
  • build:✅ tsup 成功,dist/index.js 735KB,kernel 内联

其他核查:

0.0.60 发布后的执行计划(默认按 AGENTS.md 惯例,有异议请指出):

  1. PR feat: strip closed-turn thinking replay via kernel reasoningReplay (needs acp-kernel 0.0.60) #338 rebase 到 master 并 push(仅代码,不动 package.json)。
  2. 人工合并 PR feat: strip closed-turn thinking replay via kernel reasoningReplay (needs acp-kernel 0.0.60) #338
  3. 切 release 分支 YYYY-MM-DD_release-v0.1.61:两版本字段提交(pi 0.1.60→0.1.61 + acp-kernel 0.0.56→0.0.60)+ lockfile,跑 typecheck/test/build,开 release PR。

若你希望先在 feature PR 上 bump pin(让 PR CI 在合并前转绿,release 提交只动 pi 版本),告诉我一声,我按那个流程走。

…ed reasoning, untestable)

Explicit reasoningReplay in acp.json (or coreOverrides) always wins; qwen/glm
verified open-round safe by live API matrix (delete/truncate/empty × closed
and open tool rounds all 200).
@ranxianglei

Copy link
Copy Markdown
Owner Author

开关语义(本次补充,commit a5025ff)

配置 行为
未配置 + qwen/glm/其他 open-round(闭合轮 thinking 剥离,默认开)
未配置 + GPT 系(provider/model 匹配 gpt-/o1,o3,o4/codex/openai) always(完全关闭,旧行为)
acp.json "reasoningReplay": "always" 强制关闭(kill-switch)
acp.json "reasoningReplay": "never" 连开轮也剥(激进档)
coreOverrides.reasoningReplay 最高优先

GPT 默认保守的依据:OpenAI Responses API 的 reasoning 是加密块、必须原样回传,且本地无 API 可验证(用户实测要求)。qwen3.8-27b(sglang 8199)与 glm-5.3(z.ai 代理 18081)已跑完整 API 矩阵:删除/截断/空串 × 闭合轮/工具未闭合轮,全部 200。

实现保证:从不截断 thinking 文本(存根化只作用于 compress 调用 args)、开轮永不碰(Anthropic 签名校验安全超集)。等 acp-kernel #225 合并发 0.0.60 后 bump pin 即可合并本 PR。

OpenAI reasoning items are opaque and must round-trip unmodified;
untestable from here, so default GPT-family to legacy keep-everything.
Explicit reasoningReplay config overrides the family default.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 已 review 新提交(a5025ff + 2407041)并重新预验证:

代码 review:defaultReasoningReplay(provider, modelId) 实现与语义表一致——优先级链 coreOverrides > 显式配置 > 供应商默认 保持;GPT 系正则 /(^|[^a-z0-9])(gpt-|o[134](-|\d|\/|$)|codex|openai)/i 边界处理正确(不会误伤 mygpt-x 这类子串,openai-compatible 前缀命中属于保守方向的合理假阳性)。方向安全:假阳性只会退回旧行为(不剥离),不会误剥。

重新预验证(新 tip 2407041,kernel overlay 不变):

  • typecheck:✅ clean
  • test:✅ 630 pass / 0 fail / 3 skipped(633 例,较上轮 +2)
  • build:✅ 735KB

"7 例"对上了:tests/messages-reasoning.test.ts 现在恰好 7 个顶层 test(原 5 + 新增 2 个 GPT 默认/显式覆盖),我上轮说的 6 例出入已消除。

一个小问题:分支里提交了 8 个 tmp/*.mjs 草稿脚本(ctx-breakdown/ctx2-6/inspect/repro-final/repro-loop,共 ~330 行)。建议 rebase 时顺手删掉(或你自行处理)——我执行 rebase 步骤时会默认移除,要保留请说一声。

阻塞未变:npm 上 acp-kernel 最新仍是 0.0.59(pr-225 dist-tag 还是 prerelease 0.0.59-pr.225.76),0.0.60 未发布。按你确认的流程:等 #225 合并 → 0.0.60 上 npm → 本 PR bump pin 0.0.56→0.0.60 + lockfile + rebase master + 移除 tmp/ → 跑全套检查 → push,然后即可合并。

CompressSettings now carries reasoningReplay, resolved through the
existing global → providers.<name> → models.<id> deepest-wins merge,
so the GPT-family escape hatch is a plain per-provider setting:

  { "compress": { "providers": { "openai": { "reasoningReplay": "always" } } } }

Precedence: compress (any level) > coreOverrides.reasoningReplay >
family default.
@ranxianglei

Copy link
Copy Markdown
Owner Author

Superseded: owner wants exact alignment with opencode-acp #377 (owner-locked design: compress-calls selector + char threshold + nested field-wise three-level config, adapter-level pass). Clean reimplementation coming on a fresh branch; kernel stays untouched.

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.

Protected-message exemption inflates the incompressible context floor: per-compression reasoning is never reclaimable (~83.5% of measured residual)

1 participant