会话状态永不丢失opencode-dynamic-context-pruning持久化设计与compaction重置机制揭秘【免费下载链接】opencode-dynamic-context-pruningDynamic context pruning plugin for OpenCode - intelligently manages conversation context to optimize token usage项目地址: https://gitcode.com/gh_mirrors/op/opencode-dynamic-context-pruningopencode-dynamic-context-pruningDCP是 OpenCode 的一款上下文剪枝插件通过 compress 压缩、工具去重等策略持续降低 token 消耗。它的会话状态持久化设计让已压缩的内容、剪枝记录、统计数字在进程重启后完整恢复而 compaction 重置机制则在 OpenCode 官方压缩发生后自动清掉失效的旧状态。本文带你快速看懂这两套机制的设计思路与源码位置。opencode-dynamic-context-pruning 会话状态持久化设计为什么会话状态持久化如此关键DCP 的核心承诺是你的原始会话历史永远不会被修改。它只是在把请求发给 LLM 之前把已剪枝的内容替换成占位符或高保真摘要。但这里有个容易忽视的问题DCP 自己也需要记住——哪些消息被压缩过、哪些工具输出被去重过、累计省了多少 token。如果这些信息只存在内存里那么每次重启 OpenCode压缩记录从零开始重复压缩、统计归零模型看到的占位符与插件状态不一致行为变得不可预测DCP 的解法是每个会话对应一个独立的 JSON 状态文件随会话生命周期持续写入、随时恢复。一份状态文件里存了什么持久化逻辑集中在 lib/state/persistence.ts 中。每次状态变化后saveSessionState会把整个会话快照序列化写盘存储位置遵循 XDG 规范lib/state/persistence.ts~/.local/share/opencode/storage/plugin/dcp/{sessionId}.json每份文件PersistedSessionState结构见 lib/state/types.ts包含五类信息字段作用prune.tools被去重剪枝的工具调用 ID 及其所在轮次prune.messages压缩块CompressionBlock的完整清单摘要、锚点消息、起止消息 ID、压缩/摘要 token 数、嵌套关系nudges已触发过的压缩提醒锚点避免重复骚扰模型stats本会话累计节省的 token 数manualMode该会话是否启用手动模式值得称道的细节是读取端的防御性校验loadSessionStatelib/state/persistence.ts会逐一验证字段类型过滤掉格式错误的锚点并去重loadPruneMessagesStatelib/state/utils.ts还会重建activeBlockIds集合、根据现有块 ID 自动修正nextBlockId计数器。换句话说即使文件被手改过或版本升级后格式略有变化DCP 也能安全地软着陆而不是直接崩溃。compaction 重置机制旧状态为何必须清零OpenCode 自身内置了 compaction官方压缩当会话逼近模型上下文上限时它会把历史消息折叠成一条summary消息。这给 DCP 带来了麻烦——压缩之后旧消息 ID、锚点、消息编号映射全部失效继续引用它们只会指向不存在的内容。DCP 的处理非常干净核心逻辑在 lib/state/state.ts 的checkSession中检测findLastCompactionTimestamplib/state/utils.ts从消息列表尾部倒序扫描找到最近一条role: assistant且summary: true的消息取其时间戳作为最近一次 compaction的时间点判断若该时间戳大于内存中记录的state.lastCompaction说明刚刚发生了一次新的 compaction重置调用resetOnCompactionlib/state/utils.ts清空工具参数缓存、工具剪枝表、压缩块状态、消息 ID 映射和所有提醒锚点落盘重置结果立即持久化保证重启后依然生效。检测到新 compaction ── 清空 prune / nudges / messageIds ── 立即 saveSessionState这种检测到边界事件就整体清零的策略与平时只增不减、增量写盘的持久化策略形成互补写路径追求少而稳重置路径追求快而彻底。同时isMessageCompactedlib/state/utils.ts会把 compaction 时间戳之前的消息一律视为已折叠保证压缩提醒、轮次计数等逻辑不会把旧消息算进活跃上下文。重启恢复与全时统计会话恢复同样无感当checkSession发现当前会话 ID 变化时lib/state/state.tsensureSessionInitialized会先重置内存状态再从磁盘加载该会话的持久化快照还原剪枝表、压缩块、锚点和手动模式设置。之后你在 TUI 里看到的已节省 xxK tokens依然连续。更妙的是跨会话的全时统计loadAllSessionStatslib/state/persistence.ts会遍历存储目录下所有会话 JSON 文件聚合出累计 token、剪枝工具数、压缩消息数与会话总数——这正是/dcp面板和 scripts/opencode-token-stats 脚本的数据来源。核心模块速查想深入源码可以从这些入口读起模块职责lib/state/persistence.ts状态读写盘、校验、全时统计聚合lib/state/state.ts会话初始化、compaction 检测与重置调度lib/state/utils.tsfindLastCompactionTimestamp、resetOnCompaction、状态反序列化lib/state/types.tsSessionState、CompressionBlock等数据结构定义lib/commands/stats.ts基于持久化数据生成统计报告lib/compress/pipeline.ts压缩完成后触发状态落盘小结DCP 的持久化设计可以总结为三句话一会话一文件随改随存读盘时层层校验坏数据自动降级compaction 是明确的分界线越线即整体重置。这套机制让它在省 token的同时也保证了行为可预测——无论是跨重启的长会话还是被官方 compaction 折叠过的历史状态都始终一致。如果你也在为 OpenCode 的 token 消耗发愁不妨从 README.md 的安装一节开始用一行命令装好它然后打开~/.local/share/opencode/storage/plugin/dcp/亲眼看看自己的会话状态文件 【免费下载链接】opencode-dynamic-context-pruningDynamic context pruning plugin for OpenCode - intelligently manages conversation context to optimize token usage项目地址: https://gitcode.com/gh_mirrors/op/opencode-dynamic-context-pruning创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
