Skip to main content

为什么 OpenCode 上下文没到 100% 就被压缩了?

· 4 min read

TUI 右下角才显示 60%、70%,自动 compact 突然就触发了——这是用 OpenCode 最高频的困惑。原因不止一个,按可能性从高到低排:

  1. 给输出 token 预留 buffer:TUI 显示 80% 触发压缩,真正留给"历史"的安全位可能只有 50% 左右。
  2. Tool calls 占空间:一次 Bash 输出几百行、一次大文件读取直接干到 10k+ tokens,这才是隐形杀手
  3. Provider 实际限制比标称小:qwen3.7-plus 在 OpenCode 上硬卡 200k(issue #30838),即使模型标称 1M。
  4. Compaction 循环 bug:issue #29450 报过一句话烧光 200k 的 case,先升级 / 换 provider 再说。
  5. 手动控制:用 /compact 自己把握时机,/compact 50 保留最近 50 条消息不压。

用 OpenCode 一段时间,几乎每个人都问过同一个问题:TUI 右下角的上下文百分比才 60%、70%,怎么突然就被压缩了?

这个问题的答案不是单一的——OpenCode 显示的百分比、模型的 context window、自动 compact 的触发条件是三件不同的事情,下面把它们拆开讲。

1. 给输出 token 预留 buffer(最常见)

一次完整的请求 = 输入历史 + 模型输出 + tool calls。OpenCode 算"还能不能塞下"时,必须把预想的输出长度也算进去,否则半句话截断就是事故。

所以 TUI 显示 80% 触发压缩,真正留给"历史"的安全位可能只有 50% 左右——剩下 30% 全是给"还没发生的输出"留的 buffer。

这是设计,不是 bug。任何 coding agent 都是这么算的(Anthropic API、Cursor、Copilot 同理),只是不显式告诉你预留了多少。

2. Tool calls 占空间(隐形杀手)

工具调用的 JSON、返回结果、错误重试全部进上下文。几个量级参考:

  • 一次 Bash 调用带几百行输出:~5k tokens
  • 一次大文件读取(Read 一个 1000 行文件):~10k tokens
  • 一次 Grep 返回几百行匹配:~10-30k tokens
  • 一次 Glob 返回几千个路径:~20k+ tokens

这些 token 在 TUI 的百分比里全算进去了,但视觉上不容易察觉——你看到的是"我才聊了几句话",其实上下文里堆了十几个 tool 调用结果。

实际建议:长对话里多看一眼 tool calls 的输出体积。读大文件之前先用 head / Grep -n 截取,跑命令用 | head -100 限流。

3. Provider 实际限制比标称小

某些渠道对模型有限制,即使模型标称支持 1M context,实际 provider 还是会硬卡

典型 case:qwen3.7-plus 在 OpenCode 上硬卡 200k(issue #30838),即使模型标称 1M context window。如果你的百分比长期上不去,先查 provider 是不是真的给了完整 context,不是配置问题。

判断方法:

# TUI 里看右下角的 context window 显示
# 或在 /models 里看 provider 的 maxTokens 字段

4. Compaction 循环 bug

issue #29450 报过一种 case:模型在循环里反复做 summarization,一句话就把 200k 烧光

触发条件比较苛刻(一般是输出格式异常 + provider 端 retry 逻辑叠加),但如果你的 OpenCode 最近在自动循环 compact,先换个 provider 或升级版本再说,别浪费时间调配置。

手动控制:把节奏握在自己手里

觉得自动压缩时机不对,用 /compact 自己把握:

/compact # 立即压缩
/compact 50 # 保留最近 50 条消息不压

/compact N 的 N 是保留最近 N 条消息,不是 token 数。如果想保留最近 50k tokens 的内容,得自己估算消息数量。

想完全关掉自动 compact 在 opencode.jsoncompaction 段里改:

{
"compaction": {
"auto": false
}
}

提醒:这个字段官方文档没完整说明——一般手动 /compact 就够用,不建议关掉自动压缩。

References

  1. Issue #29450 —— compaction loop 烧光 200k 的 case
  2. Issue #30838 —— qwen3.7-plus 硬卡 200k 的 case
  3. OpenCode Compaction 文档 —— /compact 行为说明(文档站搜索 compaction)