⏳ This skill is pending AI review.
Scores will appear once the review pipeline completes.
Context Compressor
自动上下文压缩。当session超阈值时,先提取重要内容到日记,再压缩JSONL。支持light/standard/aggressive模式。触发条件:session>8K tokens、用户要求压缩、心跳维护时发现session过大。v5.0新增:防死循环、大输出截断、性能优化。
Choose how to use this skill
You do not need every option. Choose the path your AI client supports. The stable page stays the same; versioned files are immutable.
1. Native installer
This listing has no registered native installer command. Use the complete package or source fallback below, depending on what your client supports.
Do not guess an installer command or replace an existing version without reviewing the diff.
2. Complete package recommended
Download the ZIP when available. It includes SKILL.md plus the references, security notes and version metadata.
No complete ProSkills package is published for this listing yet.3. Prompt-only
Copy the prompt above when the agent can read the stable page or when you want to adopt the workflow without installing a skill.
Need only the instruction file?
Download SKILL.md only if your client requires a single file. The complete ZIP is safer for a full installation because it preserves the references and release context.
No path installs or executes anything by itself. Your agent still needs access to the project files. Before updating, compare the installed version and review the diff.
// RATINGS
Not yet listed on ClawHub or SkillsMP
// README
name: Context Compressor slug: context-compressor version: 5.0.0 description: 自动上下文压缩。当session超阈值时,先提取重要内容到日记,再压缩JSONL。支持light/standard/aggressive模式。触发条件:session>8K tokens、用户要求压缩、心跳维护时发现session过大。v5.0新增:防死循环、大输出截断、性能优化。 metadata: {"openclaw":{"emoji":"📦","requires":{"bins":[]},"os":["linux","darwin","win32"]}}
Context Compressor 📦
两阶段压缩:先提取,再压缩。不提取就压缩 = 丢信息。
何时压缩
| 条件 | 动作 |
|---|---|
| Session > 8K tokens(~32K字符) | 主动压缩 |
| 用户说"压缩上下文"/"compress context" | 立即压缩 |
| 心跳检查发现session膨胀 | 主动压缩 |
| 长任务开始前,session已很大 | 先压缩再继续 |
不要压缩:任务进行中、session即将结束、刚压缩过且仍低于2倍阈值。
Token估算
| 内容 | 公式 | 说明 |
|---|---|---|
| 主要中文 | 字符数 / 1.5 | 中文token密度高 |
| 主要英文 | 字符数 / 4 | 英文token密度低 |
| 混合 | 字符数 / 3 | 通用估算(脚本默认) |
| JSON/代码多 | 字符数 / 3.5 | 结构化内容更紧凑 |
注意:以上为粗略估算,实际token数因模型而异。建议用模型官方tokenizer精确计算。
快速判断:session文件 > 32K字符 ≈ > 8K tokens(混合内容),该压缩了。
Phase 1: 提取(必须先做)
扫描session中间部分,把重要内容存到外部文件。
| 要提取的 | 存到哪里 | 格式 |
|---|---|---|
| 用户偏好/事实 | SOUL.md → 偏好部分 | 更新或新增bullet |
| 关键决策/结论 | memory/YYYY-MM-DD.md | ## Decision: <topic> |
| 创作作品全文 | memory/YYYY-MM-DD.md | ## Creative: <title> |
| 重要对话摘录 | memory/YYYY-MM-DD.md | ## Conversation: <topic> |
| 技术解决方案 | memory/YYYY-MM-DD.md | ## Technical: <issue> |
| 新话题/类别 | SOUL.md → 事件索引 | 新增条目 |
| 闲聊/日常 | 不存 | — |
日记追加格式:
---
## 压缩提取 HH:mm
### <Category>: <Brief Title>
- **Context**: 为什么重要
- **Content**: 实际信息
- **Session ref**: 大致轮次范围
日记追加,绝不覆盖。
Phase 2: 压缩Session
优先级系统(从低到高删)
| 优先级 | 内容 | 删减顺序 |
|---|---|---|
| P0 | 无法解析的行(安全保留) | 保留 |
| P1 | 大型tool输出(>2000字符) | 1st |
| P2 | 导航/探索调用(ls, pwd, grep未命中) | 2nd |
| P3 | 成功但常规的tool调用 | 3rd |
| P4 | 冗长的assistant解释 | 4th |
| P5 | 日常寒暄("好的""谢谢") | 5th |
| P6 | 有意图的用户消息 | 保留 |
| P7 | 最近对话(tail) | 保留 |
| P8 | System消息 | 保留 |
| P9 | 已有Summary(合并处理) | 合并 |
| P10 | Session header | 保留 |
压缩模式
| 模式 | Token目标 | 操作 | 适用场景 |
|---|---|---|---|
| light | 6K | 只删P1-P2 | 刚过阈值,主要是tool膨胀 |
| standard | 4K | 删P1-P3,摘要P4-P5 | 常规维护(默认) |
| aggressive | 2.5K | 删P1-P5,最大化摘要 | session很长,需要最大压缩 |
大输出截断策略
当tool输出 >2000字符时,不要只做全删/全留二选一。优先截断:
| 策略 | 操作 | 节省 |
|---|---|---|
| 截断到500字符 | 保留前500字符 + ...[truncated, N chars omitted] | ~75% |
| 截断到200字符 | 保留前200字符 + 截断标记 | ~90% |
| 全删 | 完全移除该行 | 100% |
截断优先级:先截断到500 → 仍超标则截断到200 → 仍超标则全删。
截断时保留tool调用的结构信息(tool name、参数摘要),只删输出内容。
操作步骤
1. 读取 session JSONL
路径: ~/.openclaw-autoclaw/agents/<agentId>/sessions/<sessionId>.jsonl
2. 估算token数,低于阈值则退出
3. 检查防死循环标记(见下方),如触发则跳过
4. 备份原文件 → <sessionId>.jsonl.bak
5. 分类每行(P0-P10),缓存解析结果,避免重复JSON解析
6. 识别tail(从末尾往前数60行P6+内容)
7. 截断大输出(P1行先截断到500字符,再截断到200,最后全删)
8. 按优先级从低到高删除(不删tail)
直到token数达标或只剩P6+
每删一行计数+1,超过maxIter则停止
9. 生成 [SESSION SUMMARY](合并已有摘要,不要堆叠)
≤6条bullet,每条≤2行,带文件引用
10. 组装:header + summary(1行) + tail
11. 验证:每行有效JSON、至少1条user+1条assistant、token数达标
12. 写入,验证通过后删.bak,失败则回滚
13. 写入防死循环标记
14. 日志:追加到 memory/YYYY-MM-DD.md
Summary格式
[SESSION SUMMARY]
• [Decision] <决定内容> → memory/<YYYY-MM-DD>.md##Section
• [Technical] <解决方案> → memory/<YYYY-MM-DD>.md##Section
• [Fact] <关键事实>
• [State] <当前任务状态>
• [Warning] <未来必须知道的事>
规则:≤6条、每条≤2行、带文件引用、用标签分类、只写结果不写过程。日期使用当天日期。
处理已有Summary
如果session中已有 [SESSION SUMMARY]:
- 解析旧summary
- 与新内容合并
- 去重:
[State]替换为新[State],已解决的[Warning]删除,同类多bullet保留(如多个[Technical]) - 结果始终只有一条
[SESSION SUMMARY]
绝对不要堆叠多条summary。
防死循环机制 ⚠️
本地模型执行压缩时可能陷入死循环。以下机制防止此问题:
1. 最大迭代限制
| 参数 | 默认值 | 说明 |
|---|---|---|
| maxIter | 100 | 模型内操作时,删除操作的最大迭代次数 |
| maxIter (脚本) | 5000 | 脚本执行时的最大迭代次数 |
超过限制后立即停止,输出当前结果。
2. 压缩冷却期
压缩完成后,在session中写入标记:
{"type":"system","lastCompressed":"<timestamp>","compressedTokens":<N>}
规则:
- 距上次压缩 < 5分钟 → 不压缩
- 上次压缩后token数未增长 > 20% → 不压缩
- 连续3次压缩后仍未达标 → 停止压缩,报告错误
3. 压缩效果检查
压缩后验证:
- 压缩后token数必须 < 压缩前token数 × 0.9(至少减少10%)
- 如果压缩后几乎没减少 → 说明session主要由P6+内容组成,无法进一步压缩
- 此时不要重试,而是报告:"Session主要由高优先级内容组成,无法进一步压缩。建议增大阈值或手动清理。"
4. 模型执行安全
当由本地模型执行压缩时:
- 单次执行:每次只执行一次完整的压缩流程
- 不自动重试:压缩完成后不自动检查是否需要再次压缩
- 明确退出:压缩完成后输出
"Compression complete. <N> tokens remaining."然后停止 - 异常中断:如果执行过程中遇到错误,立即停止并报告,不要尝试恢复
安全与恢复
| 步骤 | 动作 |
|---|---|
| 压缩前 | 复制 .jsonl → .jsonl.bak |
| 验证通过 | 删除 .jsonl.bak |
| 验证失败 | 回滚 .jsonl.bak → .jsonl |
| 手动恢复 | 用户可从 .jsonl.bak 恢复 |
验证清单:每行有效JSON ✅ 至少1条user消息 ✅ 至少1条assistant消息 ✅ token数达标 ✅
脚本(可选)
如需脚本化执行,见 scripts/ 目录:
| 脚本 | 平台 | 用法 |
|---|---|---|
compress-session.ps1 | Windows | .\compress-session.ps1 -SessionFile <path> [-Mode standard] [-KeepTail 60] [-MaxIter 100] [-DryRun] |
compress-session.sh | Linux/macOS | ./compress-session.sh <session-file> [mode] [keep-tail] [dry-run] |
compress-simple.py | 跨平台 | python compress-simple.py <session.jsonl> [mode] [tail_lines] |
compress-all.py | 跨平台(批量) | python compress-all.py |
diary-logger.py | 跨平台 | 见下方日记记录章节 |
模型内操作优先:直接用read/write/exec工具按上述步骤执行,比脚本更灵活。
日记记录
diary-logger.py 用法
# Phase 1: 压缩前提取重要内容到日记
python diary-logger.py extract <session.jsonl> <workspace_dir>
# 压缩后记录压缩事件
python diary-logger.py log-compression <workspace_dir> --mode standard --before 8000 --after 4000 --removed 45
# 验证日记完整性
python diary-logger.py validate <workspace_dir>
# 手动更新 MEMORY.md 索引
python diary-logger.py update-index <workspace_dir> --note "手动添加的备注"
日记记录触发机制
| 触发时机 | 动作 | 命令 |
|---|---|---|
| 压缩前(Phase 1) | 提取重要内容到日记 | diary-logger.py extract |
| 压缩后 | 记录压缩事件 | diary-logger.py log-compression |
| 心跳检查时 | 验证日记完整性 | diary-logger.py validate |
| 手动 | 更新MEMORY.md索引 | diary-logger.py update-index |
日记数据格式
压缩提取追加到 memory/YYYY-MM-DD.md:
---
## 压缩提取 HH:mm
### Decision: <简要标题>
- **Context**: 为什么重要
- **Content**: 实际信息
- **Source**: user/assistant/summary
压缩事件追加到 memory/YYYY-MM-DD.md:
---
## 压缩执行 HH:mm
### Compression: standard mode
- **Before**: 8,000 tokens
- **After**: 4,000 tokens
- **Saved**: 50.0%
- **Removed lines**: 45
- **Timestamp**: 2026-04-21T12:00:00+08:00
错误处理策略
| 错误场景 | 处理方式 |
|---|---|
| 日记文件不存在 | 自动创建,含正确标题 |
| 写入失败 | 从 .bak 回滚,报告错误 |
| MEMORY.md 格式异常 | 前缀匹配日期,兼容 ### 2026-04-21 — 标题 格式 |
| 提取无重要内容 | 输出提示,不创建空条目 |
| .bak 文件残留 | validate 命令检测并报告 |
完整性验证
diary-logger.py validate 检查以下项目:
- ✅ 今日日记文件存在
- ✅ 日记标题格式正确(
# YYYY-MM-DD) - ✅ 日记包含章节内容
- ✅ MEMORY.md 包含今日条目
- ✅ SOUL.md 存在
- ✅ memory/ 目录存在且有文件
- ✅ 无残留 .bak 文件
- ⚠️ 检测空章节
- ⚠️ 检测压缩提取次数过多(>3次)
配置
| 参数 | 默认值 | 说明 |
|---|---|---|
| tokenThreshold | 8000 | 超过此token数触发压缩 |
| charThreshold | 32000 | 备用:超过此字符数触发 |
| keepTail | 60 | 保留最近对话的最小行数 |
| mode | standard | 压缩模式:light/standard/aggressive |
| autoBackup | true | 压缩前自动备份 |
| maxIter | 100 | 模型内操作最大迭代次数 |
| truncateThreshold | 2000 | 超过此字符数的tool输出触发截断 |
| truncateSize | 500 | 截断后保留的字符数 |
| cooldownMinutes | 5 | 两次压缩之间的最小间隔(分钟) |
最佳实践
- 先提取再压缩 — 不提取就压缩 = 永久丢失信息
- 按token不是按行 — 100行短对话 ≠ 100行tool输出
- 先截断再删除 — 截断大输出比全删更安全,保留上下文线索
- 先删tool调用 — 最低价值、最高token,通常单这一步就能省20-40%
- 只有一条summary — 合并不堆叠
- summary里引用外部文件 — 让未来的自己能找到详情
- 不中途压缩 — 等任务边界再压缩
- 遵守冷却期 — 不要连续压缩,至少间隔5分钟
- 日志记录 — 压缩后追加到日记:
"Compressed X→Y tokens (mode)" - 压缩失败就停止 — 不要重试,报告错误让用户决定
// HOW IT'S BUILT
KEY FILES