feat(async-context-compression): branch aware context compression#94
Conversation
Replace count-only summary reuse with per-branch snapshots validated against ordered covered refs (message id + payload fingerprint) and the full OpenWebUI history graph. A cached summary is reused only when every covered ref matches the current active-branch ancestor in order or is provably deleted from the graph; live sibling refs and in-place edits force rejection, so a stale or sibling-branch summary can no longer be injected into the active branch. Includes review fixes (review-2-opu-4.8): drop branch-valid snapshot when budgeting forces the previous-summary marker out of the compression input, protect the shortest-prefix snapshot from retention pruning, isolate prune failures from the snapshot save transaction, expunge async sessions before returning loaded snapshots, fold protected_head_count into the dedup hash, and include images in the payload fingerprint. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the snapshot-validation cases the review flagged as untested: R7 selection rejects coverage that splits a native tool-call atomic group (and accepts a group-aligned boundary); R9 two-branch round-trip selects each branch's own snapshot and rejects the sibling's; corrupted refs JSON is skipped as invalid coverage without breaking the chat; covered refs carry payload fingerprints (not just ids). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ssed Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep DB-backed summary recompression aligned to the previous snapshot boundary, share summary budget validation rules, remove no-op pruning after retain-all snapshot retention, and update plugin docs/review notes.
Explain the branch-aware summary model with non-aligned fork examples, update bilingual plugin docs and release notes to 1.7.0, and clarify the summary token window validation rationale.
Add generated branch graph fixtures and a forced compression driver so branch, delete, and branch-switch scenarios prove actual summary generation occurred. Mock only the summary model output while exercising the real compression and snapshot selection flow.
Add branch-aware referenced chat handling that can combine the nearest valid cached summary with the current active branch tail, summarize oversized tails through the configured summary model, and persist continuation summaries for later reuse. Document the 1.7.0 behavior and cover active-branch selection, authorization, budget fitting, tail preservation, and generated summary reuse with focused tests.
There was a problem hiding this comment.
Code Review
此拉取提交将“异步上下文压缩”过滤器升级至 1.7.0 版本,引入了分支感知的摘要复用、单表分支摘要存储、分支感知引用聊天以及更安全的数据库升级检查等功能。同时,PR 增加了多个设计方案、评审记录和测试套件计划,并更新了相关文档和社区统计数据。审查反馈指出,英文和中文插件文档(docs/plugins/filters/async-context-compression.md 和 .zh.md)未与对应的 README 文件完全同步,违反了仓库关于文档镜像的风格指南。此外,审查建议将英文和中文 README 中重叠的“分支感知摘要复用”与“1.7.0 版本更新”章节进行合并,以提升文档的清晰度与简洁性。
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| ## What's new in 1.7.0 | ||
|
|
||
| - **Compression style control**: Added a new `compression_style` valve with `aggressive`, `balanced`, and `faithful` modes so you can directly tune summaries for minimum token use or higher context fidelity. | ||
| - **Faithful prompt mode**: `compression_style=faithful` now tells the summary model to spend more of the available budget on key reasoning chains, evaluation criteria, active alternatives, and nuanced context instead of compressing them into abstract notes. | ||
| - **Branch-aware summary reuse**: Cached summaries are now validated against message ids and payload fingerprints before reuse, so summaries from sibling branches or edited content are rejected instead of being injected into the wrong branch. | ||
| - **Single-table branch summary storage**: Branch-valid summary rows are stored in `chat_summary`, while untrusted count-only summaries are regenerated. | ||
| - **Branch-aware referenced chats**: Referenced chats can now reuse the largest valid prefix summary plus the uncovered active-branch tail. If that mixed reference needs a new summary, the continuation summary is saved back to `chat_summary` for the referenced chat and reused later. | ||
| - **Safer upgrade checks**: Legacy tables that still enforce one row per chat are rebuilt, and schema inspection failures leave existing tables untouched instead of running destructive DDL. | ||
|
|
There was a problem hiding this comment.
此文档未与 plugins/filters/async-context-compression/README.md 完全同步,缺少了“Branch-aware summary reuse”部分,违反了仓库风格指南中关于文档镜像的规定。请在更新时确保内容完全一致。
References
- 仓库风格指南要求插件文档文件 (
docs/plugins/{type}/{name}.md) 必须是其README.md文件的镜像。 (link)
| ## 1.7.0 版本更新 | ||
|
|
||
| - **新增压缩风格控制**:新增 `compression_style` 配置项,支持 `aggressive`、`balanced`、`faithful` 三档,可以直接控制摘要更偏“省 token”还是更偏“保留上下文细节”。 | ||
| - **新增 faithful 提示词模式**:当 `compression_style=faithful` 时,摘要 prompt 会明确要求模型更多保留关键论证链、评估标准、仍在比较中的候选方案和细微上下文,而不是过度抽象化。 | ||
| - **分支感知摘要复用**:缓存摘要现在会先用 message id 和 payload fingerprint 验证覆盖范围。来自 sibling 分支或编辑前内容的旧摘要会被拒绝,不会注入到错误分支。 | ||
| - **单表分支摘要存储**:branch-valid 摘要行统一写入 `chat_summary`,缺少覆盖元数据的 count-only 摘要会重新生成。 | ||
| - **分支感知引用聊天**:引用聊天现在可以复用当前 active branch 上最大的有效前缀摘要,并拼接未覆盖的原文 tail。如果因此生成 continuation summary,会写回被引用聊天自己的 `chat_summary`,后续引用可直接复用。 | ||
| - **更安全的升级检查**:仍通过 `chat_id` unique 限制每个 chat 只能一行的旧表会被重建;如果无法反射检查现有 schema,会保留表不动并禁用摘要持久化,不会执行破坏性 DDL。 | ||
|
|
There was a problem hiding this comment.
此文档未与 plugins/filters/async-context-compression/README_CN.md 完全同步,缺少了“分支感知摘要复用”部分,违反了仓库风格指南中关于文档镜像的规定。请在更新时确保内容完全一致。
References
- 仓库风格指南要求插件的中文文档文件 (
docs/plugins/{type}/{name}.zh.md) 必须是其README_CN.md文件的镜像。 (link)
| ## Branch-aware summary reuse | ||
|
|
||
| - **Compression style control**: Added a new `compression_style` valve with `aggressive`, `balanced`, and `faithful` modes so you can directly tune summaries for minimum token use or higher context fidelity. | ||
| - **Faithful prompt mode**: `compression_style=faithful` now tells the summary model to spend more of the available budget on key reasoning chains, evaluation criteria, active alternatives, and nuanced context instead of compressing them into abstract notes. | ||
| - **Branch-safe cached summaries**: Stored summaries are reused only when every saved message-id + payload-fingerprint ref can be explained as either a current active-branch ancestor or a message proven deleted from the full history graph. Summary rows that still contain live sibling-branch refs are rejected, so new or edited current-branch messages stay in the raw live tail instead of being hidden by an old summary. | ||
| - **Single-table persistence**: Branch-specific reusable coverage is stored as multiple rows in `chat_summary`; there is no separate current-pointer row. Branch-valid historical rows are retained so a future fork can reuse the nearest matching ancestor, even when the user branches from an older point. | ||
| - **Protected-head tracking**: Summary rows remember how many leading messages were kept outside the summary. If the current `keep_first` policy no longer preserves those messages, the row is not reused as branch-valid coverage. | ||
| - **Safe upgrade behavior**: Legacy summaries without coverage metadata are not trusted as coverage. The first turn after upgrading may send more raw context until a branch-valid summary row is generated. | ||
|
|
||
| ## What's new in 1.7.0 | ||
|
|
||
| - **Branch-aware summary reuse**: Cached summaries are validated against ordered message refs and payload fingerprints before reuse, so sibling-branch or edited-history summaries are not injected into the wrong branch. | ||
| - **Single-table summary storage**: Branch-valid historical rows are stored directly in `chat_summary`; all branch summaries live in that table. | ||
| - **Branch-aware referenced chats**: Referenced chats can now reuse the largest valid prefix summary plus the uncovered active-branch tail. If that mixed reference needs a new summary, the continuation summary is saved back to `chat_summary` for the referenced chat and reused later. | ||
| - **Safer schema upgrades**: Legacy count-only summaries are not trusted as coverage, and old one-row-per-chat schemas are rebuilt so summaries can be regenerated safely. | ||
|
|
| ## 分支感知摘要复用 | ||
|
|
||
| - **分支安全的缓存摘要**:只有当已保存摘要行里的每个 message id + payload fingerprint ref 都能解释为当前活跃分支祖先,或能从完整 history graph 证明已经删除时,缓存摘要才会被复用。仍包含 live sibling 分支 refs 的摘要行会被拒绝,因此新增或编辑后的当前分支消息必须留在原文 live tail 里,不能被旧摘要隐藏。 | ||
| - **单表持久化**:分支专属的可复用覆盖范围以多行形式写入 `chat_summary`;不再保留单独的 current pointer 行。插件会保留 branch-valid 历史摘要行,使用户从更早位置分叉时仍能复用当前分支上最接近的祖先摘要。 | ||
| - **受保护头部追踪**:摘要行会记录有多少开头消息是在摘要之外按原文保留的。如果当前 `keep_first` 策略已经不再保留这些消息,该摘要行不会作为 branch-valid 覆盖范围复用。 | ||
| - **安全升级行为**:没有覆盖范围元数据的 legacy summary 不再被当成可信覆盖。升级后的第一轮对话可能会发送更多原始上下文,直到生成 branch-valid 摘要行。 | ||
|
|
||
| ## 1.7.0 版本更新 | ||
|
|
||
| - **分支感知摘要复用**:缓存摘要会先用有序 message refs 和 payload fingerprints 校验,来自 sibling 分支或编辑前历史的摘要不会注入到错误分支。 | ||
| - **单表摘要存储**:branch-valid 历史摘要行直接保存在 `chat_summary`,所有分支摘要都在这张表里。 | ||
| - **分支感知引用聊天**:引用聊天现在可以复用当前 active branch 上最大的有效前缀摘要,并拼接未覆盖的原文 tail。如果因此生成 continuation summary,会写回被引用聊天自己的 `chat_summary`,后续引用可直接复用。 | ||
| - **更安全的 schema 升级**:legacy count-only 摘要不会被当成可信覆盖,旧的一 chat 一行 schema 会重建,后续重新生成安全摘要。 | ||
|
|
||
| ## 1.6.5 版本更新 | ||
|
|
||
| - **新增压缩风格控制**:新增 `compression_style` 配置项,支持 `aggressive`、`balanced`、`faithful` 三档,可以直接控制摘要更偏“省 token”还是更偏“保留上下文细节”。 |
Fork PRs receive a read-only GITHUB_TOKEN even with pull-requests: write, so createComment/updateComment 403 and turn the whole version-check job red — even when the version check itself passed (as seen on PR #94). Mark the "Comment on PR" step continue-on-error so a missing comment no longer fails the job. The enforce-version / enforce-description steps below remain the real gate, so check strictness is unchanged.
Async Context Compression: Branch aware context compression
Overview
This release adds branch-aware summary storage and reuse. Cached summaries are now validated against ordered message references and payload fingerprints before they are injected, so summaries from sibling branches or edited history are rejected instead of being reused in the wrong conversation branch.
Because the persisted summary schema changed from count-only/current-summary storage to branch-aware rows, this release is versioned as 1.7.0.
New Features
chat_summary; all branch summaries are stored in that table.chat_summarytables, or tables that still enforce one row per chat, are rebuilt so unsafe summaries are regenerated.Branch Example
OpenWebUI chats can form a tree when a user edits or forks from an earlier message. Version 1.7.0 treats a summary as valid only for the branch whose ordered message ids and payload fingerprints it covers.
Example with a fork that does not align with a compression boundary:
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10.1-5.1-10by summarizing the previous1-5summary plus messages6-10.7, which sits between the two compression boundaries, and creates a sibling branch:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8b -> 9b.1-10summary is rejected because it contains live sibling refs8-10from the original branch. The filter can still reuse the nearest valid ancestor summary,1-5, then keep6 -> 7 -> 8b -> 9bas live tail context.1-9bfrom the old1-5summary plus the sibling branch's live tail. Both1-10and1-9bremain available, but only the newest summary valid for the current branch is injected.This is why the filter records exact message identity instead of only storing a compressed message count. A count-based summary for "10 messages" cannot tell whether those 10 messages belong to the current branch or a sibling branch.
Configuration Notes
max_summary_tokensmust be strictly less than 80% of the summary model input window. The reserved space lets the next compression pass send the previous summary plus new messages to the summary model; if the previous summary can occupy the whole input window, repeated compression cannot make meaningful progress. Invalid valve settings raise a configuration error instead of being silently lowered.Migration Notes
This release changes the summary database schema:
chat_summarytables are dropped and recreated; those old summaries are discarded and regenerated on future compression.Update or reinstall the filter so OpenWebUI's stored function content includes the new schema logic and validation changes.
Async Context Compression: 分支感知的摘要存储和复用
概述
这个版本新增了分支感知的摘要存储和复用。缓存摘要现在会先用有序 message refs 和 payload fingerprints 校验,只有当前分支有效的摘要才会被注入;来自 sibling 分支或编辑前历史的旧摘要会被拒绝。
由于持久化摘要 schema 从 count-only/current-summary 存储改成了 branch-aware 行,本次版本提升为 1.7.0。
新功能
chat_summary,所有分支摘要都在这张表里。chat_summary表,或仍限制每个 chat 只能一行的表,会被重建,避免复用不可信摘要。分支示例
OpenWebUI 里用户从早期消息编辑或重新生成时,对话会形成一棵树。1.7.0 会把摘要视为某条分支上的覆盖范围;只有当摘要记录的有序 message ids 和 payload fingerprints 都能匹配当前分支时,才会复用。
下面这个例子的分叉点没有刚好落在压缩边界上:
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10。1-5的 branch-aware 摘要。1-5摘要加上6-10生成覆盖1-10的新摘要。7处分叉。这个分叉点位于两个压缩边界之间,生成的 sibling 分支是:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8b -> 9b。1-10摘要会被拒绝,因为它包含原主分支上仍然存在的8-10refs。过滤器仍然可以复用最近的有效祖先摘要1-5,然后把6 -> 7 -> 8b -> 9b保留为 live tail 原文上下文。1-5摘要加上 sibling 分支的 live tail 派生并保存独立摘要,例如1-9b。此后1-10和1-9b可以同时保留,但实际注入给大模型的只会是当前分支上覆盖范围最大的那个有效摘要。这就是为什么插件记录精确 message 身份,而不是只记录“已经压缩了几条消息”。如果只按数量判断,一个“10 条消息摘要”无法区分它覆盖的是当前分支,还是 sibling 分支。
配置说明
max_summary_tokens必须严格小于摘要模型输入窗口的 80%。预留出来的空间用于让下次压缩可以把旧摘要和新消息一起送入摘要模型;如果旧摘要自己就能占满整个输入窗口,反复压缩就无法有效推进。不满足要求的 valve 配置会报错,不会被静默改小。迁移说明
本版本修改了摘要数据库 schema:
chat_summary表会删除并重建;这些旧摘要会丢弃,后续压缩时重新生成。请更新或重新安装过滤器,确保 OpenWebUI 中保存的 function 内容包含新的 schema 逻辑和配置校验。