opencode-acp 1.12.4 → 1.12.6
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 +16 -0
- package/README.zh-CN.md +16 -0
- package/dist/index.js +36 -30
- package/dist/index.js.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/messages/inject/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -422,6 +422,22 @@ For the complete list with root cause analysis, see the [bug tracker](https://gi
|
|
|
422
422
|
|
|
423
423
|
## Changelog
|
|
424
424
|
|
|
425
|
+
### v1.12.6 — Stale contextLimitAnchors Fix (PR #143)
|
|
426
|
+
|
|
427
|
+
**Problem**: `contextLimitAnchors` were populated when `overMaxLimit=true` but only cleared on a compress tool call in the current turn (`currentTurnHasCompress`). If context dropped below `maxLimit` via another mechanism (OpenCode compaction, external message deletion), the anchors stayed stale → `applyAnchoredNudges` kept injecting the "⚠️ Context limit reached" template at low context levels (as low as 10% usage).
|
|
428
|
+
|
|
429
|
+
**Fix**: Added `else` branch in `lib/messages/inject/inject.ts` that clears `contextLimitAnchors` whenever `!overMaxLimit`, establishing symmetry with the existing turn/iteration anchor cleanup at `!overMinLimit`. 3 regression tests (state-level clear, integration with prompt markers, sub-minLimit clear path). Dual-agent reviewed (Oracle + independent reviewer, both APPROVE).
|
|
430
|
+
|
|
431
|
+
Files: `lib/messages/inject/inject.ts`. Tests: `tests/inject.test.ts`. 691 tests pass.
|
|
432
|
+
|
|
433
|
+
### v1.12.5 — Bug 20 Suppression Fix + Growth Floor Gate Correction (PRs #139, #140)
|
|
434
|
+
|
|
435
|
+
**Problem**: Two bugs in the nudge suppression logic introduced after v1.12.4. (1) `isContextOverLimits` Bug 20 suppression checked `(part as any).type === "tool-invocation" && (part as any).toolInvocation?.toolName === "compress"` — a message-part format that does not exist in the SDK (all 18+ other tool-type checks in the codebase use `part.type === "tool" && part.tool === "compress"`). The suppression never matched, so `overMaxLimit` was never set to `false` after a compress call → the max-limit alert fired every turn → over-compression feedback loop. (2) The growth floor gate (PR #134) made `growthFloor` the sole gate for `nudgeAllowed`, dropping the `decision.shouldNudge` requirement — meaning nudges could fire on negative growth as long as the growth floor condition was met.
|
|
436
|
+
|
|
437
|
+
**Fix**: (1) PR #139: Changed the format check to `part.type === "tool" && part.tool === "compress"` and removed the `(part as any)` casts. Suppression now correctly detects compress tool calls in recent messages and resets `overMaxLimit`. (2) PR #140: `nudgeAllowed` now requires `decision.shouldNudge || emergencyOverride`, restoring the intended two-condition gate.
|
|
438
|
+
|
|
439
|
+
Files: `lib/messages/inject/utils.ts` (Bug 20 fix), `lib/messages/inject/inject.ts` (growth floor correction). 688 tests pass.
|
|
440
|
+
|
|
425
441
|
### v1.12.4 — Protection-Aware Stats + Nudge Ranges Fix + Growth Floor Gate (PRs #132, #133, #134)
|
|
426
442
|
|
|
427
443
|
**Problem**: Three issues since v1.12.3. (1) `buildCompressibleRanges` and `estimateContextComposition` listed ALL messages as compressible, silently including protected tool output — the model saw inflated ranges, compressed, and most content was filtered out → ineffective compression with confusing stats. (2) When nudge anchors were active (context over minLimit) but growth was below the cadence threshold, the nudge text fired but the compressible ranges list was gated by growth cadence → model saw "compress now" with no ranges. (3) After fixing #2, the model could be nudged every turn (turn anchors re-add every turn) → thrashing risk.
|
package/README.zh-CN.md
CHANGED
|
@@ -395,6 +395,22 @@ ACP 在首次启动时自动将配置从 `dcp.jsonc` 迁移到 `acp.jsonc`,将
|
|
|
395
395
|
|
|
396
396
|
## 更新日志
|
|
397
397
|
|
|
398
|
+
### v1.12.6 — Stale contextLimitAnchors 修复(PR #143)
|
|
399
|
+
|
|
400
|
+
**问题**:`contextLimitAnchors` 仅在 `overMaxLimit=true` 时添加,但只在当前 turn 有 compress 调用时 (`currentTurnHasCompress`) 才清除。如果上下文通过其他机制(OpenCode compaction、外部消息删除)降到 `maxLimit` 以下,anchors 保持 stale → `applyAnchoredNudges` 持续注入 "⚠️ Context limit reached" 模板,即使实际上下文很低(低至 10%)。
|
|
401
|
+
|
|
402
|
+
**修复**:在 `lib/messages/inject/inject.ts` 添加 `else` 分支,当 `!overMaxLimit` 时清除 `contextLimitAnchors`,与已有的 `!overMinLimit` 清除 turn/iteration anchors 逻辑对称。3 个回归测试(state 级、prompt marker 集成、sub-minLimit 清除)。双 agent review(Oracle + 独立 reviewer,均 APPROVE)。
|
|
403
|
+
|
|
404
|
+
文件:`lib/messages/inject/inject.ts`。测试:`tests/inject.test.ts`。691 测试通过。
|
|
405
|
+
|
|
406
|
+
### v1.12.5 — Bug 20 抑制修复 + 增长下限门控修正(PR #139, #140)
|
|
407
|
+
|
|
408
|
+
**问题**:v1.12.4 后引入的两个 nudge 抑制逻辑 bug。(1)`isContextOverLimits` 的 Bug 20 抑制检查 `(part as any).type === "tool-invocation" && (part as any).toolInvocation?.toolName === "compress"` —— 这个消息部件格式在 SDK 中根本不存在(代码库中其他 18+ 处工具类型检查全部使用 `part.type === "tool" && part.tool === "compress"`)。抑制逻辑永不匹配,所以压缩后 `overMaxLimit` 从不置 false → max-limit 告警每轮触发 → 过度压缩正反馈循环。(2)增长下限门控(PR #134)使 `growthFloor` 成为 `nudgeAllowed` 的唯一 gate,丢弃了 `decision.shouldNudge` 要求 —— 意味着即使增长为负,只要满足增长下限条件 nudge 就会触发。
|
|
409
|
+
|
|
410
|
+
**修复**:(1)PR #139:将格式检查改为 `part.type === "tool" && part.tool === "compress"`,移除了 `(part as any)` 类型断言。抑制现在正确检测最近消息中的 compress 工具调用并重置 `overMaxLimit`。(2)PR #140:`nudgeAllowed` 现在要求 `decision.shouldNudge || emergencyOverride`,恢复预期的双条件门控。
|
|
411
|
+
|
|
412
|
+
文件:`lib/messages/inject/utils.ts`(Bug 20 修复)、`lib/messages/inject/inject.ts`(增长下限修正)。688 测试通过。
|
|
413
|
+
|
|
398
414
|
### v1.12.4 — 保护感知统计 + Nudge 范围修复 + 增长下限门控(PR #132, #133, #134)
|
|
399
415
|
|
|
400
416
|
**问题**:v1.12.3 以来三个问题。(1)`buildCompressibleRanges` 和 `estimateContextComposition` 将所有消息列为可压缩,静默包含受保护工具输出 → 模型看到虚高的范围,压缩后大部分被过滤 → 无效压缩和混乱统计。(2)当 nudge anchors 激活(context 超过 minLimit)但增长低于节奏阈值时,nudge 文本触发但可压缩范围列表被增长节奏门控 → 模型看到"立即压缩"但没有范围。(3)修复 #2 后,模型可能每轮被 nudge(turn anchors 每轮重新添加)→ thrashing 风险。
|
package/dist/index.js
CHANGED
|
@@ -6497,7 +6497,7 @@ function isContextOverLimits(config, state, providerId, modelId, messages) {
|
|
|
6497
6497
|
for (const msg of recentMessages) {
|
|
6498
6498
|
if (msg.info.role === "assistant" && msg.parts) {
|
|
6499
6499
|
for (const part of msg.parts) {
|
|
6500
|
-
if (part.type === "tool
|
|
6500
|
+
if (part.type === "tool" && part.tool === "compress") {
|
|
6501
6501
|
overMaxLimit = false;
|
|
6502
6502
|
break;
|
|
6503
6503
|
}
|
|
@@ -7160,35 +7160,41 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
7160
7160
|
anchorsChanged = true;
|
|
7161
7161
|
}
|
|
7162
7162
|
}
|
|
7163
|
-
} else
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
state.nudges.turnNudgeAnchors.add(lastMessage.message.info.id);
|
|
7168
|
-
state.nudges.turnNudgeAnchors.add(lastAssistantMessage.info.id);
|
|
7169
|
-
if (state.nudges.turnNudgeAnchors.size !== previousSize) {
|
|
7170
|
-
anchorsChanged = true;
|
|
7171
|
-
}
|
|
7163
|
+
} else {
|
|
7164
|
+
if (state.nudges.contextLimitAnchors.size > 0) {
|
|
7165
|
+
state.nudges.contextLimitAnchors.clear();
|
|
7166
|
+
anchorsChanged = true;
|
|
7172
7167
|
}
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
);
|
|
7190
|
-
|
|
7191
|
-
|
|
7168
|
+
if (overMinLimit) {
|
|
7169
|
+
const isLastMessageUser = lastMessage?.message.info.role === "user";
|
|
7170
|
+
if (isLastMessageUser && lastAssistantMessage) {
|
|
7171
|
+
const previousSize = state.nudges.turnNudgeAnchors.size;
|
|
7172
|
+
state.nudges.turnNudgeAnchors.add(lastMessage.message.info.id);
|
|
7173
|
+
state.nudges.turnNudgeAnchors.add(lastAssistantMessage.info.id);
|
|
7174
|
+
if (state.nudges.turnNudgeAnchors.size !== previousSize) {
|
|
7175
|
+
anchorsChanged = true;
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
const lastUserMessage = getLastUserMessage(messages);
|
|
7179
|
+
if (lastUserMessage && lastMessage) {
|
|
7180
|
+
const lastUserMessageIndex = messages.findIndex(
|
|
7181
|
+
(message) => message.info.id === lastUserMessage.info.id
|
|
7182
|
+
);
|
|
7183
|
+
if (lastUserMessageIndex >= 0) {
|
|
7184
|
+
const messagesSinceUser = countMessagesAfterIndex(messages, lastUserMessageIndex);
|
|
7185
|
+
const iterationThreshold = getIterationNudgeThreshold(config);
|
|
7186
|
+
if (lastMessage.index > lastUserMessageIndex && messagesSinceUser >= iterationThreshold) {
|
|
7187
|
+
const interval = getNudgeFrequency(config);
|
|
7188
|
+
const added = addAnchor(
|
|
7189
|
+
state.nudges.iterationNudgeAnchors,
|
|
7190
|
+
lastMessage.message.info.id,
|
|
7191
|
+
lastMessage.index,
|
|
7192
|
+
messages,
|
|
7193
|
+
interval
|
|
7194
|
+
);
|
|
7195
|
+
if (added) {
|
|
7196
|
+
anchorsChanged = true;
|
|
7197
|
+
}
|
|
7192
7198
|
}
|
|
7193
7199
|
}
|
|
7194
7200
|
}
|
|
@@ -7220,7 +7226,7 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
7220
7226
|
nudgeGrowthTokens: effectiveThreshold
|
|
7221
7227
|
});
|
|
7222
7228
|
const growthSinceBaseline = currentTokens !== void 0 && growthReference !== void 0 ? currentTokens - growthReference : void 0;
|
|
7223
|
-
const nudgeAllowed = emergencyOverride || growthSinceBaseline !== void 0 && growthSinceBaseline >= growthFloor;
|
|
7229
|
+
const nudgeAllowed = emergencyOverride || decision.shouldNudge && growthSinceBaseline !== void 0 && growthSinceBaseline >= growthFloor;
|
|
7224
7230
|
state.nudges.shouldInjectThisTurn = nudgeAllowed;
|
|
7225
7231
|
const effectiveTipsVariant = emergencyOverride ? "maxLimit" : decision.tipsVariant;
|
|
7226
7232
|
if (nudgeAllowed) {
|