opencode-acp 1.9.1 → 1.9.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
@@ -421,6 +421,25 @@ For the complete list with root cause analysis, see the [bug tracker](https://gi
421
421
 
422
422
  ## Changelog
423
423
 
424
+ ### v1.9.2 — Persist Nudge Baseline Across Restart (bug #60)
425
+
426
+ **Problem**: After a per-message nudge fired purely on token growth (no compress/decompress around it), the updated `lastPerMessageNudgeTokens` baseline was written to in-memory state but **not persisted to disk** — `saveSessionState()` only ran when `anchorsChanged` was true, and a growth nudge does not always change anchors (turn/iteration anchor sets saturate once seeded, or the last message is an assistant turn with no user turn to anchor). After an OpenCode restart, the stale baseline was reloaded, so `growth = currentTokens − staleBaseline` exceeded the threshold again → the nudge refired on **every single turn** for the rest of the session.
427
+
428
+ **Fix** (PR #61): The save guard in `lib/messages/inject/inject.ts` now persists whenever a nudge has actually fired, not just when anchors moved:
429
+
430
+ ```
431
+ - if (anchorsChanged) {
432
+ + if (anchorsChanged || decision.shouldNudge) {
433
+ saveSessionState(state, logger).catch(() => {})
434
+ }
435
+ ```
436
+
437
+ After this, `lastPerMessageNudgeTokens` is correctly flushed to `~/.local/share/opencode/storage/plugin/acp/{sessionId}.json` on every nudge, so a restart computes growth against the real post-nudge baseline and the nudge only refires when *actual* new growth exceeds `nudgeGrowthTokens`. Regression test added in `tests/inject.test.ts` (seeds a stale baseline to disk, fires a growth nudge with `anchorsChanged=false`, reloads, asserts the persisted baseline advanced).
438
+
439
+ **Compatibility**: No schema changes. Existing persisted state loads unchanged. Users hitting #60 should upgrade and the every-turn nudge loop stops on the first nudge after restart.
440
+
441
+ ---
442
+
424
443
  ### v1.9.1 — Disjoint Visible-Range Segments & Nudge Wording (issue #9 root cause)
425
444
 
426
445
  **Problem**: Even after v1.9.0, the model kept calling `compress` against IDs that a prior block had consumed. The root cause was that the suffix advertised a single contiguous span "first visible → last visible" that **straddled compression holes** — so the model's first guess for an `endId` landed inside an already-summarized range. Separately, the suffix's `(+X tokens since last nudge)` growth line was being misread as an *overflow* warning, triggering panic compressions of large-but-still-needed ranges.
package/README.zh-CN.md CHANGED
@@ -393,6 +393,25 @@ ACP 在首次启动时自动将配置从 `dcp.jsonc` 迁移到 `acp.jsonc`,将
393
393
 
394
394
  ## 更新日志
395
395
 
396
+ ### v1.9.2 — 重启后正确持久化提醒基线(bug #60)
397
+
398
+ **问题**:当每条消息的提醒纯粹因为 token 增长而触发(周围没有 compress/decompress 操作)时,更新后的 `lastPerMessageNudgeTokens` 基线只写进了内存、**没有落盘** —— `saveSessionState()` 仅在 `anchorsChanged` 为 true 时执行,而增长提醒并不总是改变 anchor(turn/iteration anchor 集合一经播种就会饱和,或最后一轮是 assistant、没有可锚定的 user 轮)。OpenCode 重启后读到的还是陈旧基线,于是 `growth = currentTokens − 陈旧基线` 又超过阈值 → 提醒在**之后每一轮**都会重新触发,直到会话结束。
399
+
400
+ **修复**(PR #61):`lib/messages/inject/inject.ts` 的保存守卫现在在「提醒确实触发」时就落盘,而不只是 anchor 变动时:
401
+
402
+ ```
403
+ - if (anchorsChanged) {
404
+ + if (anchorsChanged || decision.shouldNudge) {
405
+ saveSessionState(state, logger).catch(() => {})
406
+ }
407
+ ```
408
+
409
+ 修复后,`lastPerMessageNudgeTokens` 在每次提醒时都会被正确写入 `~/.local/share/opencode/storage/plugin/acp/{sessionId}.json`,重启后基于真实的提醒后基线计算增长,只有当*实际新增长*超过 `nudgeGrowthTokens` 时才会再次触发提醒。回归测试已加入 `tests/inject.test.ts`(先向磁盘写入陈旧基线,在 `anchorsChanged=false` 下触发增长提醒,重载后断言持久化基线已推进)。
410
+
411
+ **兼容性**:无 schema 变更,现有持久化 state 正常加载。遇到 #60 的用户升级后,重启后第一轮提醒即会落盘,每轮重复触发的循环随之停止。
412
+
413
+ ---
414
+
396
415
  ### v1.9.1 — 不相交可见范围段 & 提醒措辞修正(issue #9 根因)
397
416
 
398
417
  **问题**:即便有了 v1.9.0,模型仍反复对已被先前块消费的 ID 调用 `compress`。根因是 suffix 一直广播一条"从首条可见到最后一条可见"的**跨越压缩空洞的连续 span** —— 模型对 `endId` 的第一反应往往是落在已经被摘要的范围里。此外,suffix 的 `(+X tokens since last nudge)` 增长行被误读为**溢出警告**,触发对"大但仍然需要"范围的恐慌性压缩。
package/dist/index.js CHANGED
@@ -6394,7 +6394,7 @@ Top blocks: ${topBlocks.map((b) => `b${b.blockId} ${fmt2(b.compressedTokens)}\u2
6394
6394
  if (suffixMessage) {
6395
6395
  appendToLastTextPart(suffixMessage, "\n");
6396
6396
  }
6397
- if (anchorsChanged) {
6397
+ if (anchorsChanged || decision.shouldNudge) {
6398
6398
  saveSessionState(state, logger).catch(() => {
6399
6399
  });
6400
6400
  }