opencode-acp 1.14.8-dev.1 → 1.14.8-dev.2

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
@@ -492,6 +492,16 @@ For the complete list with root cause analysis, see the [bug tracker](https://gi
492
492
 
493
493
  ## Changelog
494
494
 
495
+ ### v1.14.8-dev.2 — Dev Prerelease (2 PRs since v1.14.8-dev.1)
496
+
497
+ Dev prerelease covering PRs #244–#245. Published to `dev` npm tag for early testing.
498
+
499
+ **PRs included**:
500
+ - **#245** — Fix: re-add HOW_TO_COMPRESS_RULES to nudge injection for high-attention summary guidance. v1.14.7 over-removed the rules from all 4 nudge locations (breakdown + 3 templates), leaving them only in system prompt. In long sessions, system prompt rules degrade due to "lost in the middle" effect — model needs rules at high attention (end of context) when nudge fires.
501
+ - **#244** — Fix: acp_status hides consumed compress calls from PROTECTED list.
502
+
503
+ **Install**: `opencode plugin opencode-acp@dev --global`
504
+
495
505
  ### v1.14.8-dev.1 — Dev Prerelease (7 PRs since v1.14.7)
496
506
 
497
507
  Dev prerelease covering PRs #238–#242. Published to `dev` npm tag for early testing.
package/README.zh-CN.md CHANGED
@@ -446,6 +446,16 @@ ACP 是 DCP 的直接替代品。迁移步骤:
446
446
 
447
447
  ## 更新日志
448
448
 
449
+ ### v1.14.8-dev.2 — Dev 预发布(v1.14.8-dev.1 以来 2 个 PR)
450
+
451
+ Dev 预发布,涵盖 PR #244–#245。发布到 `dev` npm tag 供早期测试。
452
+
453
+ **包含的 PR**:
454
+ - **#245** — 修复:重新将 HOW_TO_COMPRESS_RULES 加入 nudge 注入。v1.14.7 过度删除了所有 4 处 nudge 位置的规则(breakdown + 3 个模板),只保留在 system prompt。在长 session 中,system prompt 的规则因"lost in the middle"效应衰减——模型在 nudge 触发时需要规则在高注意力区(上下文末尾)。
455
+ - **#244** — 修复:acp_status 隐藏 PROTECTED 列表中已消耗的 compress 调用。
456
+
457
+ **安装**:`opencode plugin opencode-acp@dev --global`
458
+
449
459
  ### v1.14.8-dev.1 — Dev 预发布(v1.14.7 以来 7 个 PR)
450
460
 
451
461
  Dev 预发布,涵盖 PR #238–#242。发布到 `dev` npm tag 供早期测试。
package/dist/index.js CHANGED
@@ -7609,6 +7609,8 @@ Breakdown: ${sysPart}${fmt(composition.toolTokens)} tool (${pct2(composition.too
7609
7609
  if (recommendedRanges.length > 0) {
7610
7610
  breakdown += `
7611
7611
 
7612
+ ${HOW_TO_COMPRESS_RULES}
7613
+
7612
7614
  ${formatCompressibleRanges(recommendedRanges, contextRanges.protected)}`;
7613
7615
  breakdown += `
7614
7616
  \u{1F4A1} Compress all ranges in one call (pass multiple content entries: \`content: [{...}, {...}]\`).`;
@@ -7618,7 +7620,7 @@ Use \`acp_status({scope:"uncompressed"})\` to re-fetch compressible ranges after
7618
7620
  appendToLastTextPart(suffixMessage, breakdown);
7619
7621
  }
7620
7622
  if (effectiveTipsVariant === "maxLimit") {
7621
- tipsText = '\n\n\u26A0\uFE0F Context limit reached \u2014 compress now. Prioritize consumed tool outputs.\n\n{ "topic": "...", "content": [{ "startId": "<ID>", "endId": "<ID>", "summary": "..." }] }\n\nOnly use IDs from visible messages above. Compress older work first.';
7623
+ tipsText = "\n\n\u26A0\uFE0F Context limit reached \u2014 compress now. Prioritize consumed tool outputs.\n\n" + HOW_TO_COMPRESS_RULES + '\n\n{ "topic": "...", "content": [{ "startId": "<ID>", "endId": "<ID>", "summary": "..." }] }\n\nOnly use IDs from visible messages above. Compress older work first.';
7622
7624
  }
7623
7625
  state.nudges.lastNudgeShownTokens = currentTokens;
7624
7626
  {
@@ -8258,6 +8260,64 @@ function createDecompressTool(factoryCtx) {
8258
8260
 
8259
8261
  // lib/compress/status.ts
8260
8262
  import { tool as tool4 } from "@opencode-ai/plugin";
8263
+
8264
+ // lib/compress/parts.ts
8265
+ var STRUCTURAL_PART_TYPES = /* @__PURE__ */ new Set(["step-start", "step-finish", "reasoning"]);
8266
+ function hasMeaningfulContent(parts) {
8267
+ return parts.some((p) => !STRUCTURAL_PART_TYPES.has(p.type));
8268
+ }
8269
+
8270
+ // lib/compress/hide-consumed.ts
8271
+ var KEEP_LAST_ORPHANED = 2;
8272
+ function hideConsumedCompressCalls(state, messages) {
8273
+ const activeCallIds = /* @__PURE__ */ new Set();
8274
+ const allBlockCallIds = /* @__PURE__ */ new Set();
8275
+ for (const block of state.prune.messages.blocksById.values()) {
8276
+ if (block.compressCallId) {
8277
+ allBlockCallIds.add(block.compressCallId);
8278
+ if (block.active && !block.deactivatedByUser && !block.deactivatedByUserDeep) {
8279
+ activeCallIds.add(block.compressCallId);
8280
+ }
8281
+ }
8282
+ }
8283
+ const lastOrphanedCallIds = [];
8284
+ for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {
8285
+ const parts = Array.isArray(messages[i]?.parts) ? messages[i].parts : [];
8286
+ for (let j = parts.length - 1; j >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; j--) {
8287
+ const p = parts[j];
8288
+ if (p.type === "tool" && p.tool === "compress" && p.callID && !allBlockCallIds.has(p.callID)) {
8289
+ lastOrphanedCallIds.push(p.callID);
8290
+ }
8291
+ }
8292
+ }
8293
+ const keepCallIds = /* @__PURE__ */ new Set([...activeCallIds, ...lastOrphanedCallIds]);
8294
+ let hidden = 0;
8295
+ for (let i = 0; i < messages.length; i++) {
8296
+ const msg = messages[i];
8297
+ const parts = Array.isArray(msg.parts) ? msg.parts : [];
8298
+ let changed = false;
8299
+ const remaining = parts.filter((p) => {
8300
+ if (p.type === "tool" && p.tool === "compress") {
8301
+ if (p.callID && keepCallIds.has(p.callID)) return true;
8302
+ hidden++;
8303
+ changed = true;
8304
+ return false;
8305
+ }
8306
+ return true;
8307
+ });
8308
+ if (changed) {
8309
+ if (hasMeaningfulContent(remaining)) {
8310
+ messages[i] = { ...msg, parts: remaining };
8311
+ } else {
8312
+ messages.splice(i, 1);
8313
+ i--;
8314
+ }
8315
+ }
8316
+ }
8317
+ return hidden;
8318
+ }
8319
+
8320
+ // lib/compress/status.ts
8261
8321
  var ACP_STATUS_TOOL_DESCRIPTION = `Show context status \u2014 overview includes compressible ranges by default.
8262
8322
 
8263
8323
  No args: Overview with totals, compressed blocks, and compressible ranges.
@@ -8648,6 +8708,7 @@ function createAcpStatusTool(factoryCtx) {
8648
8708
  if (scope === "uncompressed") return "(unable to fetch messages)";
8649
8709
  rawMessages = [];
8650
8710
  }
8711
+ hideConsumedCompressCalls(ctx.state, rawMessages);
8651
8712
  return buildStatusReport(
8652
8713
  { state: ctx.state, config: ctx.config },
8653
8714
  rawMessages,
@@ -8714,55 +8775,6 @@ Call with blockId to get the full summary: acp_context_recap({ blockId: N })`);
8714
8775
  });
8715
8776
  }
8716
8777
 
8717
- // lib/compress/parts.ts
8718
- var STRUCTURAL_PART_TYPES = /* @__PURE__ */ new Set(["step-start", "step-finish", "reasoning"]);
8719
- function hasMeaningfulContent(parts) {
8720
- return parts.some((p) => !STRUCTURAL_PART_TYPES.has(p.type));
8721
- }
8722
-
8723
- // lib/compress/hide-consumed.ts
8724
- function hideConsumedCompressCalls(state, messages) {
8725
- if (state.prune.messages.blocksById.size === 0) {
8726
- return 0;
8727
- }
8728
- const consumedMessageIds = /* @__PURE__ */ new Set();
8729
- for (const block of state.prune.messages.blocksById.values()) {
8730
- if (block.active) continue;
8731
- if (block.deactivatedByUser) continue;
8732
- if (block.deactivatedByUserDeep) continue;
8733
- if (block.deactivatedByBlockId === void 0) continue;
8734
- if (!block.compressMessageId) continue;
8735
- consumedMessageIds.add(block.compressMessageId);
8736
- }
8737
- if (consumedMessageIds.size === 0) {
8738
- return 0;
8739
- }
8740
- let hidden = 0;
8741
- for (let i = 0; i < messages.length; i++) {
8742
- const msg = messages[i];
8743
- if (!consumedMessageIds.has(msg.info.id)) continue;
8744
- const parts = Array.isArray(msg.parts) ? msg.parts : [];
8745
- let changed = false;
8746
- const remaining = parts.filter((p) => {
8747
- if (p.type === "tool" && p.tool === "compress") {
8748
- hidden++;
8749
- changed = true;
8750
- return false;
8751
- }
8752
- return true;
8753
- });
8754
- if (changed) {
8755
- if (hasMeaningfulContent(remaining)) {
8756
- messages[i] = { ...msg, parts: remaining };
8757
- } else {
8758
- messages.splice(i, 1);
8759
- i--;
8760
- }
8761
- }
8762
- }
8763
- return hidden;
8764
- }
8765
-
8766
8778
  // lib/compress/hide-failed.ts
8767
8779
  function hideFailedCompressCalls(messages) {
8768
8780
  let mostRecentFailedId;
@@ -8809,7 +8821,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
8809
8821
  import { join as join3 } from "path";
8810
8822
  import { existsSync as existsSync3 } from "fs";
8811
8823
  import { homedir as homedir3 } from "os";
8812
- var LOG_VERSION = true ? "1.14.8-dev.1" : "dev";
8824
+ var LOG_VERSION = true ? "1.14.8-dev.2" : "dev";
8813
8825
  var Logger = class {
8814
8826
  logDir;
8815
8827
  enabled;