OpenCode 解决上下文问题的核心技术手段
1. 动态会话压缩与剪枝 (Session Compaction & Pruning)
这是 OpenCode 最具工业级特色的方案,位于 session/compaction.ts 。
- 自动溢出检测 :通过 isOverflow 函数实时监控当前 Token 消耗。它预留了一个 COMPACTION_BUFFER (20,000 Token),一旦总消耗接近模型限制,就会触发压缩。
- 工具调用剪枝 (Pruning) :
- 逆向回溯策略 :从最新的消息往回扫描,保留最近的 40,000 Token。
- 非破坏性擦除 :对于较早的、不再关键的工具输出(如之前的 ls 或 grep 结果),系统会将 part.state.time.compacted 标记为当前时间,并在发送给 LLM 时剔除这些冗长的输出内容。
- 特权保护 :特定的工具(如 skill )会被保护,其输出不会被剪枝,以保证 Agent 的核心能力不丢失。
2. 响应截断与分流策略 (Truncation Strategy)
位于 tool/truncation.ts ,解决单次工具调用输出过大的问题。
- 硬限阈值 :单次输出严格限制在 2,000 行 或 50 KB 。
- 本地缓存分流 :如果工具输出(如执行测试的结果)超过阈值,系统会将完整内容写入本地磁盘( tool-output 目录),仅在上下文中返回一个“摘要+预览”。
- 引导式感知 :在截断后的提示词中,系统会显式引导 Agent:“输出已截断,完整内容已存至 X 路径。请使用 grep 或 read (带有 offset/limit) 来分段查看”。
3. 结构化代码感知 (Semantic Context via LSP)
不同于 SWE-agent 这种主要依赖 shell 读文件的项目,OpenCode 深度集成了 LSP。
- 符号替代文本 :当 Agent 需要了解某个类或函数时,OpenCode 优先提供符号定义和类型签名,而不是把整个源文件塞进上下文。
- 按需读取 : tool/read.ts 默认带有 limit 参数(2000行),并支持 offset 。Agent 习惯于“翻页式”阅读,极大地节省了 Token。
4. 智能过滤与忽略 (Smart Filtering)
- 全链路忽略 :在 file/ignore.ts 中定义了工业级通用的 FOLDERS 和 FILES 黑名单(如 node_modules 、 .git 、 dist 、 target 等)。
- 搜索限额 :在 tool/ls.ts 中,文件列表被硬限制在 100 个 。如果目录太深,Agent 必须通过多次、具体的 ls 来探索,避免一次性加载数万个文件路径。
5. 任务聚焦机制 (Task/Todo Focused)
- Todo 维持 : session/todo.ts 让 Agent 始终维护一份“待办清单”。
- 作用 :即使历史消息被剪枝,Agent 只要看到最新的 Todo 列表,就能找回执行状态,避免因上下文丢失而导致的“原地打转”。
如何平衡记忆
1. 工业级持久化存储 (Structured Persistence)
OpenCode 没有将对话存在内存中,而是使用了 SQLite (Drizzle ORM) 进行物理持久化(见 session.sql.ts )。
- 多级表结构 :分为 SessionTable (会话)、 MessageTable (单条消息)和 PartTable (消息内部的片段,如 Tool Call 或文本)。
- 作用 :这意味着即使你关闭 IDE 再打开,甚至 Agent 进程崩溃,它也能从数据库中精准恢复每一条对话历史。
2. 动态摘要机制 (Session Summarization)
为了防止历史对话太长占用过多 Token,OpenCode 引入了 Summary 机制 (见 session/summary.ts )。
- 关键差异化记忆 :它不仅仅是总结文本,还会计算 Diffs (代码变更摘要)。系统会记录该 Session 期间修改了哪些文件、增加了多少行、删除了多少行。
- 快照关联 :摘要会与 Git 的 Snapshot 关联。当对话太长被剪枝(Pruning)时,Agent 仍然能通过 summary_diffs 字段知道之前“做了什么”,而不需要重读整个对话过程。
3. 跨会话的“元记忆”:Todo 机制
这是 OpenCode 保持长期任务记忆的神技。
- Todo 表 (TodoTable) :在数据库中独立维护一个任务清单(见 session.sql.ts#L86 )。
- 逻辑闭环 :每轮对话开始时,System Prompt 会注入当前的 Todo 列表。
- 解决的问题 :如果对话历史因为太长被剪枝了,Agent 可能会忘记“接下来该干嘛”。但 Todo 列表是持久化且每轮必读的,它充当了 Agent 的 “工作记忆(Working Memory)” ,确保任务目标不漂移。
4. 环境感知的 System Prompt (Environment Awareness)
在 session/system.ts 中,每一轮对话都会动态构建一个环境块:
- 实时注入 :包括当前工作目录、Git 仓库状态、甚至当前的日期。
- 作用 :这让 Agent 始终记得自己“身处何处”,避免因为对话太久而忘记了自己是在 Windows 还是 Linux 下工作,或者忘记了当前项目的根目录。
5. 自动重试与回滚 (Retry & Revert)
记忆不仅包括“说了什么”,还包括“做错了什么”。
- Revert 记录 : SessionTable 中有一个 revert 字段,记录了回滚的信息。
- 记忆逻辑 :当 Agent 的一次尝试失败并回滚时,这个动作会被记录。在下一轮对话中,Agent 会“记得”之前的路径行不通,从而尝试新的方案
OpenCode 解决上下文问题的核心技术手段
1. 动态会话压缩与剪枝 (Session Compaction & Pruning)
这是 OpenCode 最具工业级特色的方案,位于 session/compaction.ts 。
2. 响应截断与分流策略 (Truncation Strategy)
位于 tool/truncation.ts ,解决单次工具调用输出过大的问题。
3. 结构化代码感知 (Semantic Context via LSP)
不同于 SWE-agent 这种主要依赖 shell 读文件的项目,OpenCode 深度集成了 LSP。
4. 智能过滤与忽略 (Smart Filtering)
5. 任务聚焦机制 (Task/Todo Focused)
如何平衡记忆
1. 工业级持久化存储 (Structured Persistence)
OpenCode 没有将对话存在内存中,而是使用了 SQLite (Drizzle ORM) 进行物理持久化(见 session.sql.ts )。
2. 动态摘要机制 (Session Summarization)
为了防止历史对话太长占用过多 Token,OpenCode 引入了 Summary 机制 (见 session/summary.ts )。
3. 跨会话的“元记忆”:Todo 机制
这是 OpenCode 保持长期任务记忆的神技。
4. 环境感知的 System Prompt (Environment Awareness)
在 session/system.ts 中,每一轮对话都会动态构建一个环境块:
5. 自动重试与回滚 (Retry & Revert)
记忆不仅包括“说了什么”,还包括“做错了什么”。