opencode-acp 1.18.0-pr.392.149 → 1.18.0-pr.394.152

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,15 @@ The model decides <em>when</em> and <em>what</em> to compress — not a hard lim
10
10
 
11
11
  ---
12
12
 
13
+
14
+ ## 📄 Paper / Preprint
15
+
16
+ - **[Model-Driven Incremental Hierarchical Compression: Training-Free Multi-Generational Context Management for Long-Lived Coding Agents](./paper/model-driven-incremental-hierarchical-compression-training-free-multi-generational-context-management-for-long-lived-coding-agents.md)** (English, v0.2)
17
+
18
+ A production-scale longitudinal study: 4.5 months, three hosts, 174,327 model calls, 18.76B cumulative input tokens (~24.7B across all hosts), zero window violations on 204,800-token models, marathon sessions of 8,584–12,049 calls. The paper is open-sourced under the MIT License as part of the codebase — a living document anyone may edit.
19
+
20
+ ---
21
+
13
22
  <p align="center">
14
23
  <a href="https://www.npmjs.com/package/opencode-acp"><img src="https://img.shields.io/npm/v/opencode-acp.svg?style=flat-square" alt="npm"></a>
15
24
  <a href="https://github.com/ranxianglei/opencode-acp/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/opencode-acp.svg?style=flat-square" alt="license"></a>
package/README.zh-CN.md CHANGED
@@ -10,6 +10,15 @@
10
10
 
11
11
  ---
12
12
 
13
+
14
+ ## 📄 论文 / 预印本
15
+
16
+ - **[模型驱动的分层增量压缩:面向长寿命编码 Agent 的免训练多代上下文管理](./paper/模型驱动的分层增量压缩-免训练多代上下文管理.md)**(中文版,v0.2)
17
+
18
+ 生产规模纵向研究:四个半月、三宿主、174,327 次模型调用、187.6 亿累计输入 token(三宿主合计约 247 亿),204,800-token 窗口零违规,马拉松会话 8,584–12,049 次调用。本文与代码一同以 MIT 许可开源,是代码库的一部分 —— 任何人都可以编辑。
19
+
20
+ ---
21
+
13
22
  <p align="center">
14
23
  <a href="https://www.npmjs.com/package/opencode-acp"><img src="https://img.shields.io/npm/v/opencode-acp.svg?style=flat-square" alt="npm"></a>
15
24
  <a href="https://github.com/ranxianglei/opencode-acp/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/opencode-acp.svg?style=flat-square" alt="license"></a>
package/dist/index.js CHANGED
@@ -9150,7 +9150,7 @@ ${rules}`;
9150
9150
  const lines = [
9151
9151
  `[ACP Debug] Recommendation filter:`,
9152
9152
  ` Input: ${compressible.length} range(s), ${fmt(compressible.reduce((s, r) => s + r.tokens, 0))} tokens`,
9153
- ` Output: ${candidatePlan.candidates.length} candidate(s) (${candidatePlan.truncatedCount} truncated)`
9153
+ candidatesEnabled ? ` Output: ${candidatePlan.candidates.length} candidate(s) (${candidatePlan.truncatedCount} truncated)` : ` Output: ${recommendedRanges.length} range(s) (last segment marked dangerous)`
9154
9154
  ];
9155
9155
  logger.debug(lines.join("\n"));
9156
9156
  }
@@ -9162,7 +9162,7 @@ ${rules}`;
9162
9162
  const growth = currentTokens !== void 0 && (state.nudges.lastNudgeShownTokens ?? state.nudges.lastPerMessageNudgeTokens) !== void 0 ? currentTokens - (state.nudges.lastNudgeShownTokens ?? state.nudges.lastPerMessageNudgeTokens) : 0;
9163
9163
  const growthStr = growth > 0 ? ` (+${fmt(growth)} since last nudge)` : "";
9164
9164
  const plainTextTokens = composition.textTokens;
9165
- const efficiencyNote = effectiveTipsVariant !== "maxLimit" ? "\nThis is an efficiency nudge to compress early when content is no longer needed and keep context lean \u2014 not an overflow warning. A separate, stronger alert will appear if the context is actually full.\n\n" + COMPRESS_PHILOSOPHY : "";
9165
+ const efficiencyNote = effectiveTipsVariant !== "maxLimit" ? candidatesEnabled ? "\nThis is an efficiency nudge to compress early when content is no longer needed and keep context lean \u2014 not an overflow warning. A separate, stronger alert will appear if the context is actually full.\n\n" + COMPRESS_PHILOSOPHY : "\nThis is an efficiency nudge to compress early and keep context lean \u2014 not an overflow warning. A separate, stronger alert will appear if the context is actually full.\n\n" + COMPRESS_PHILOSOPHY : "";
9166
9166
  const sysPart = composition.systemTokens > 0 ? `${fmt(composition.systemTokens)} system (${pct2(composition.systemTokens)}%) | ` : "";
9167
9167
  let breakdown = `${efficiencyNote}
9168
9168
  Breakdown: ${sysPart}${fmt(composition.toolTokens)} tool (${pct2(composition.toolTokens)}%) | ${fmt(composition.summaryTokens)} summaries (${pct2(composition.summaryTokens)}%) | ${fmt(composition.codeTokens)} code (${pct2(composition.codeTokens)}%) | ${fmt(plainTextTokens)} text (${pct2(plainTextTokens)}%) | ${fmt(composition.reasoningTokens)} reasoning (${pct2(composition.reasoningTokens)}%)${growthStr}`;
@@ -10154,22 +10154,39 @@ function renderOverview(visibleMessages, summaryTokens, systemTokens, blocks, fe
10154
10154
  }
10155
10155
  }
10156
10156
  if (!fetchFailed) {
10157
- const pruneMap = ctx.state.prune.messages.byMessageId;
10158
- const visibleRaw = rawMessages.filter((msg) => {
10159
- const msgId = msg.info?.id || "";
10160
- const entry = pruneMap.get(msgId);
10161
- return !entry || entry.activeBlockIds.length === 0;
10162
- });
10163
- const candidates = renderCompressionCandidates(rawMessages, ctx);
10164
- if (candidates.length > 0) {
10165
- lines.push("");
10166
- lines.push(...candidates);
10157
+ if (ctx.config?.compress?.candidates === true) {
10158
+ const candidates = renderCompressionCandidates(rawMessages, ctx);
10159
+ if (candidates.length > 0) {
10160
+ lines.push("");
10161
+ lines.push(...candidates);
10162
+ }
10163
+ } else {
10164
+ const pruneMap = ctx.state.prune.messages.byMessageId;
10165
+ const visibleRaw = rawMessages.filter((msg) => {
10166
+ const msgId = msg.info?.id || "";
10167
+ const entry = pruneMap.get(msgId);
10168
+ return !entry || entry.activeBlockIds.length === 0;
10169
+ });
10170
+ const protectedRefs = ctx.config?.compress ? computeProtectedRefs(visibleRaw, ctx.state, ctx.config.compress) : /* @__PURE__ */ new Set();
10171
+ const contextRanges = buildCompressibleRanges(
10172
+ visibleRaw,
10173
+ ctx.state,
10174
+ ctx.config?.compress?.protectedTools ?? [],
10175
+ ctx.config?.protectedFilePatterns ?? [],
10176
+ protectedRefs
10177
+ );
10178
+ if (contextRanges.compressible.length > 0 || contextRanges.protected.length > 0) {
10179
+ lines.push("");
10180
+ lines.push(
10181
+ formatCompressibleRanges(contextRanges.compressible, contextRanges.protected)
10182
+ );
10183
+ }
10167
10184
  }
10168
10185
  }
10169
10186
  lines.push("");
10170
10187
  const hintTool = topToolName || "bash";
10171
10188
  lines.push(
10172
- `Tip: acp_status({scope:"uncompressed", view:"ranges"}) for raw ranges, or acp_status({scope:"uncompressed", view:"messages", tool:"${hintTool}"}) for per-message listing`
10189
+ ctx.config?.compress?.candidates === true ? `Tip: acp_status({scope:"uncompressed", view:"ranges"}) for raw ranges, or acp_status({scope:"uncompressed", view:"messages", tool:"${hintTool}"}) for per-message listing` : `Tip: acp_status({scope:"uncompressed", view:"messages", tool:"${hintTool}"}) for per-message listing`
10173
10190
  );
10174
10191
  return lines;
10175
10192
  }
@@ -10536,7 +10553,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
10536
10553
  import { join as join4 } from "path";
10537
10554
  import { existsSync as existsSync4 } from "fs";
10538
10555
  import { homedir as homedir3 } from "os";
10539
- var LOG_VERSION = true ? "1.18.0-pr.392.149" : "dev";
10556
+ var LOG_VERSION = true ? "1.18.0-pr.394.152" : "dev";
10540
10557
  var LEVEL_RANK = {
10541
10558
  debug: 10,
10542
10559
  info: 20,
@@ -12749,7 +12766,7 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
12749
12766
  });
12750
12767
  }
12751
12768
  const prePruneTokens = getCurrentTokenUsage(state, output.messages);
12752
- const candidateMessages = output.messages.slice();
12769
+ const candidateMessages = config.compress.candidates === true ? output.messages.slice() : void 0;
12753
12770
  prune(state, logger, config, output.messages);
12754
12771
  hideConsumedCompressCalls(state, output.messages);
12755
12772
  assignMessageRefs(state, output.messages);
@@ -13219,7 +13236,7 @@ var server = (async (ctx) => {
13219
13236
  }
13220
13237
  const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
13221
13238
  logger.info("ACP plugin initialized", {
13222
- version: true ? "1.18.0-pr.392.149" : "dev",
13239
+ version: true ? "1.18.0-pr.394.152" : "dev",
13223
13240
  workspace: ctx.directory,
13224
13241
  logLevel: logger.level,
13225
13242
  debug: config.debug,