实战 05:简易 OpenCode——会话、上下文压缩与模型运行时
1、本篇任务:让长时间编码 Session 不失控
编码 Agent 的难点不是第一次回答,而是第 30 轮仍知道任务、改了哪些文件、测试为何失败,同时不把整个仓库和全部日志重复塞进模型。本篇完善 Session 生命周期、上下文构建、压缩与 Provider 路由。
2、Session 与 Turn
Session 表示持续协作空间;Turn 表示一次用户输入到 Agent 停止的运行。一个 Session 可 fork 子 Session,用于尝试另一方案而不污染主线。
Session
├─ Turn 1:解释认证代码
├─ Turn 2:提出修改计划
├─ Turn 3:应用 Patch + 测试失败
└─ Turn 4:修复测试
Turn 保存起始 workspace snapshot、用户消息、Assistant/Tool Parts、模型 usage、结束原因和变更 Patch。取消只取消当前 Turn;删除 Session 需要清理消息、事件、checkpoint、worktree 和 artifacts。
3、Context Builder 的输入
每次调用模型都重新构建 context,不把数据库全部消息直接发送:
1. Harness/system 规则
2. Project rules:根 AGENTS.md + 当前文件路径上的更近规则
3. Agent/mode 规则:plan/build/reviewer
4. 当前用户消息与明确 @file 引用
5. 最近关键消息和工具摘要
6. 压缩后的旧 Session summary
7. 当前步骤需要的 diagnostics、diff、todo
8. 当前允许工具 schema
每一块记录 source、priority、estimated_tokens、version。Context manifest 写入 trace,才能回答“模型为什么没看到这个文件”。
4、文件引用与仓库发现
@path 只是一种显式引用,仍经过路径权限与大小限制。目录引用先生成树与相关文件列表,不一次读取全部。仓库初始化可扫描语言、包管理器、入口、测试配置和规则文件,生成可人工审阅的 ProjectProfile,而非长期把全仓库文本放 prompt。
type ProjectProfile = {
languages: string[];
packageManagers: string[];
testSuites: Record<string, string>;
importantPaths: string[];
rulesFiles: { path: string; hash: string }[];
};
profile 在 Git commit 或规则文件 hash 变化时更新。
5、Token 预算算法
先为输出和工具调用预留空间,再分配输入预算:
context_window
- max_output_tokens
- tool_schema_tokens
- safety_margin
= available_input
system/权限规则不可删除;当前用户消息最高优先;最近消息、当前 diff/diagnostic 次之;旧工具原文、大日志和低相关文件最先卸载。工具结果保留摘要与 artifact ID,需要时再读取局部。
不要用字符串末尾硬截断,可能切坏 JSON、Patch 或代码。按完整 content block 选择,超过大小的 block 先专门摘要或存 artifact。
6、上下文压缩
触发条件可以是 token 达到窗口的 70% 或预计下一次调用会超预算。Compactor 生成结构化摘要:
type SessionSummary = {
objective: string;
confirmedFacts: string[];
decisions: { decision: string; reason: string }[];
filesRead: { path: string; hash: string; purpose: string }[];
filesChanged: { path: string; patchArtifactId: string }[];
tests: { suite: string; status: string; artifactId?: string }[];
openQuestions: string[];
coveredUntilMessageId: string;
};
摘要不取代权威 workspace。文件 hash 变化时,旧的 filesRead 事实标 stale;测试结果关联 commit/snapshot;用户纠正决定时更新 summary。保留压缩前消息以供审计,但不再默认发模型。
7、Provider 路由
Model Catalog 保存能力:context 长度、工具、图片、结构化输出、价格和可用状态。Plan/review 可选更强推理模型,简单摘要/标题可用低成本模型;但路由是配置规则,不让模型自行选择任意 provider。
fallback 只用于兼容模型。若主模型已产生工具调用或文本 delta,切换 provider 要开启新 step 并明确记录,不能把两家不兼容流拼成一个响应。
8、缓存与重试
可缓存 ProjectProfile、规则文件、LSP 查询和相同 hash 文件摘要。模型响应缓存只适合确定测试或明确可复用任务,不能让带用户隐私/动态 workspace 的结果跨 Session 泄露。
重试 provider 429/临时 5xx;解析错误最多有限修复;权限 deny、路径错误和测试失败不可通过模型重试掩盖。每次重试计入预算并写 Step Part。
9、Doom-loop 检测
检测连续相同工具+相同参数、相同 Patch 被拒后再次提出、测试错误未变却重复运行、模型多轮没有新增 artifact/状态。达到阈值暂停并询问用户或终止;不要继续消耗费用。
10、测试
长 Session 压缩后保留目标、决策、变更和失败测试;文件变化会使旧摘要 stale;token 选择不切断 JSON/Patch;规则优先级正确;provider fallback 不重复工具;缓存按 project/session namespace;doom-loop 能在固定次数暂停。
本篇完成后,编码 Agent 才能从“会改一个文件”升级为可持续协作工具。
官方参考:OpenCode Rules、Models、Agents。
如果您觉得这篇文章有帮助,请点个赞吧~
评论
请登录后发表评论
去登录