OpenCode Go 接入 Claude Desktop 后上下文一直显示 200K:1M 映射问题排查与解决
最近我在 Claude Desktop 的 Code 模式中,通过 CC Switch 接入 OpenCode Go。
整体链路大致如下:
Claude Desktop
↓
CC Switch 本地路由
↓
OpenAI Chat Completions 格式转换
↓
OpenCode Go
↓
deepseek-v4-pro 等模型
OpenCode Go 里的部分模型支持较大的上下文窗口。以 deepseek-v4-pro 为例,我在 CC Switch 中已经勾选了“声明支持 1M”,但 Claude Desktop 的上下文面板仍然显示:
31.9k / 200.0k
在一个更长的历史会话中,甚至出现了:
402.3k / 200.0k(100%)
这显然不太合理。
如果上游真的硬限制在 200K,那么会话不应该已经超过 400K 后仍能继续运行。最终排查下来,问题并不是 OpenCode Go 模型本身不支持长上下文,而是 Claude Desktop 没有正确采用第三方模型的上下文能力声明,仍然按照默认的 200K 预算管理当前会话。
本文记录完整的排查过程和最终解决办法。
一、先理解这条调用链
Claude Desktop 并不会直接认识所有第三方模型名称。
例如:
deepseek-v4-pro
glm-5.2
mimo-v2.5-pro
这些名称不属于 Claude Desktop 原生识别的 Sonnet、Opus、Haiku 角色,因此需要 CC Switch 进行模型映射。
模型映射模式下,链路实际上是:
Claude Desktop 看到的模型角色
claude-opus-* / claude-sonnet-* / claude-haiku-*
↓
CC Switch 本地网关
↓
OpenCode Go 实际模型
deepseek-v4-pro
CC Switch 负责:
- 向 Claude Desktop 暴露能够识别的模型角色;
- 将角色模型映射到真正的上游模型;
- 在 Anthropic Messages 与 OpenAI Chat Completions 等格式之间转换;
- 使用 CC Switch 中保存的 API Key 请求上游。
在 Windows 下,本地路由通常是:
http://127.0.0.1:15721/claude-desktop
CC Switch 官方文档也明确说明,非 Claude 模型通常需要使用模型映射模式,并保持本地路由运行。
二、“声明支持 1M”到底做了什么
CC Switch 的模型映射页面中有一个“1M”复选框。
它的含义并不是:
把一个 200K 模型强行扩容到 1M
而是:
向 Claude Desktop 声明当前映射模型支持 1M 上下文
对应写入 Claude Desktop profile 的字段为:
{
"supports1m": true
}
CC Switch 新版本使用 supports1m 布尔标记替代旧的 [1M] 模型名后缀,从而将“实际请求模型”和“上下文能力声明”分开。
因此,“实际请求模型”仍然应该填写:
deepseek-v4-pro
而不是:
deepseek-v4-pro[1m]
后者并不是 OpenCode Go 的真实模型 ID,直接发送给上游可能会得到“模型不存在”的错误。
三、确认 CC Switch 是否真的写入成功
首先检查 CC Switch 是否已经把 supports1m 写入 Claude Desktop 的配置文件。
在 Windows PowerShell 中执行:
Get-Content "$env:LOCALAPPDATA\Claude-3p\configLibrary\00000000-0000-4000-8000-000000157210.json" |
Select-String "supports1m|deepseek|opus|sonnet|fable"
我的输出中已经出现:
"name": "claude-fable-5",
"supports1m": true
"labelOverride": "deepseek-v4-pro",
"name": "claude-opus-4-8",
"supports1m": true
"labelOverride": "deepseek-v4-flash",
"name": "claude-sonnet-5",
"supports1m": true
这一步说明:
- CC Switch 中的配置已经保存;
deepseek-v4-pro已经映射到 Opus 角色;supports1m已经正确写入;- 问题不是“忘记勾选 1M”。
CC Switch 在 Windows 中维护的 Claude Desktop 配置文件位于:
%LOCALAPPDATA%\Claude-3p\configLibrary\
这些文件由 CC Switch 自动维护,不建议直接手动修改。配置不一致时,应回到 CC Switch 重新启用当前供应商,再彻底重启 Claude Desktop。
四、为什么已经是 supports1m: true,仍然显示 200K
这里需要区分三个不同层次。
1. 上游模型的真实能力
这是 OpenCode Go 最终调用的模型实际上能接收多少上下文。
例如:
deepseek-v4-pro
它的真实上限由 OpenCode Go 和上游服务决定。
2. CC Switch 的模型映射
CC Switch 负责把 Claude Desktop 中的 Opus、Sonnet、Haiku 角色转换为真正的上游模型,并完成接口格式转换。
3. Claude Desktop 的本地上下文预算
Claude Desktop 还需要知道:
当前模型应该按照 200K、256K、512K,还是 1M 管理会话?
这个值会影响:
- Context window 的分母;
- 剩余空间计算;
- 自动压缩触发时机;
- Compact buffer 的预留;
- 长会话能否继续积累。
这次真正出问题的是第三层。
CC Switch 已经写入:
"supports1m": true
但 Claude Desktop 当前版本或当前第三方路由组合,没有把这一能力正确应用到当前会话,于是出现:
上游可以继续接受长会话
但客户端仍然按 200K 显示和管理
这也解释了为什么会出现:
402.3k / 200.0k(100%)
分子已经超过分母,但会话仍然可以继续运行。
五、先尝试正常的 1M 映射方式
在使用全局覆盖之前,建议先完成下面这些步骤:
- 在 CC Switch 中编辑 OpenCode Go 供应商;
- 开启“需要模型映射”;
- 将
deepseek-v4-pro映射到 Opus 或 Sonnet; - 勾选“声明支持 1M”;
- 保存配置;
- 回到供应商列表重新启用该供应商;
- 确认 Claude Desktop 本地路由已开启;
- 完全退出 Claude Desktop;
- 重新打开并新建会话;
- 在模型菜单中选择生成的
deepseek-v4-pro 1M变体。
CC Switch 官方文档明确说明,Claude Desktop 不会热加载第三方 profile。每次切换供应商或修改模型映射后,都需要彻底退出并重新打开。
如果完成以上步骤后,Context window 仍然显示 200K,再使用下面的客户端覆盖方案。
六、最终生效的办法:覆盖 Claude Code 的上下文预算
Claude Code 提供了环境变量:
CLAUDE_CODE_MAX_CONTEXT_TOKENS
它的作用是覆盖 Claude Code 对活动模型上下文窗口大小的判断。
在我的环境中,将它设置为:
1000000
重启 Claude Desktop 后,Context window 从:
402.3k / 200.0k
变成了:
402.3k / 1.0M
这说明之前的 200K 确实主要是客户端预算识别问题。
Claude Code 的用户级配置文件位于:
%USERPROFILE%\.claude\settings.json
加入:
{
"env": {
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "1000000"
}
}
如果文件中已经存在其他配置,需要把 env 合并进去,不要直接覆盖整个文件。
例如原配置为:
{
"permissions": {
"defaultMode": "bypassPermissions"
}
}
修改后应为:
{
"permissions": {
"defaultMode": "bypassPermissions"
},
"env": {
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "1000000"
}
}
七、使用 PowerShell 安全写入
手动编辑 JSON 容易因为逗号或层级写错,可以使用下面的 PowerShell 脚本。
它会:
- 备份原来的
settings.json; - 保留已有配置;
- 创建或更新
env; - 写入 1M 上下文覆盖。
$path = "$env:USERPROFILE\.claude\settings.json"
if (Test-Path $path) {
$backup = "$path.bak-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
Copy-Item $path $backup
$cfg = Get-Content $path -Raw | ConvertFrom-Json
} else {
New-Item -ItemType Directory -Force `
"$env:USERPROFILE\.claude" | Out-Null
$cfg = [pscustomobject]@{}
}
if (-not $cfg.PSObject.Properties["env"]) {
$cfg | Add-Member `
-NotePropertyName env `
-NotePropertyValue ([pscustomobject]@{})
}
if (
$cfg.env.PSObject.Properties[
"CLAUDE_CODE_MAX_CONTEXT_TOKENS"
]
) {
$cfg.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS = "1000000"
} else {
$cfg.env | Add-Member `
-NotePropertyName CLAUDE_CODE_MAX_CONTEXT_TOKENS `
-NotePropertyValue "1000000"
}
$cfg |
ConvertTo-Json -Depth 100 |
Set-Content $path -Encoding UTF8
Write-Host "配置完成:$path"
if ($backup) {
Write-Host "备份文件:$backup"
}
写入后检查:
Get-Content "$env:USERPROFILE\.claude\settings.json"
确认存在:
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "1000000"
八、关于 DISABLE_COMPACT
Claude Code 官方文档说明:
- 从 v2.1.193 开始,对于 Claude Code 不识别为 Claude 模型的名称,
CLAUDE_CODE_MAX_CONTEXT_TOKENS可以直接生效; - 对于被识别为 Claude 模型的名称,通常还需要同时设置
DISABLE_COMPACT。
配置形式如下:
{
"env": {
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "1000000",
"DISABLE_COMPACT": "1"
}
}
但这项设置需要谨慎。
DISABLE_COMPACT=1 会关闭自动压缩。客户端可能持续积累上下文,直到直接撞上上游真实限制。因此我的建议是:
先只设置 CLAUDE_CODE_MAX_CONTEXT_TOKENS
如果完全不生效,再临时测试 DISABLE_COMPACT
不同 Claude Desktop / Claude Code 版本,以及 CC Switch 暴露给客户端的内部模型名称不同,实际行为可能有所区别。
我的环境中,仅设置:
CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000
就已经让界面显示为 1M。
这属于当前环境中的实际测试结果,不代表所有版本都一定相同。
九、必须彻底重启 Claude Desktop
配置写入后,只关闭窗口通常不够。
可以在 PowerShell 中执行:
Get-Process |
Where-Object {
$_.ProcessName -match "Claude"
} |
Stop-Process -Force
然后:
保持 CC Switch 运行
→ 确认 Claude Desktop 本地路由开启
→ 重新打开 Claude Desktop
→ 新建会话
→ 选择 OpenCode Go 模型
→ 查看 Context window
修改后,我的界面显示为:
402.3k / 1.0M(40%)
十、为什么上下文数字仍然对不上
修复后,我的面板顶部显示:
Context window:402.3k / 1.0M
但下面分类明细相加大约是:
Messages 375.0k
System tools 18.8k
System prompt 5.2k
Skills 5.0k
Compact buffer 3.0k
MCP tools 0.914k
────────────────────────
合计约 407.9k
同时:
1,000k - 592.1k Free space
≈ 407.9k
也就是说:
- 顶部显示约 402.3K;
- 分类合计约 407.9K;
- 相差约 5.6K。
这说明 Claude Desktop 顶部计数和分类明细不一定采用完全相同的统计口径。
可能的原因包括:
- 顶部使用最近一次 API 返回的 usage;
- 分类明细是客户端本地估算;
- 工具定义、系统提示和缓存 token 的口径不同;
- Anthropic 与 OpenAI 格式转换后 token 计算存在差异;
- 面板不同区域的刷新时间不一致。
因此,Context window 更适合作为剩余空间和压缩时机的近似参考,而不是精确账单。
真正的 API 用量应以上游返回的 usage、OpenCode Go 的计费记录和 CC Switch 的请求日志为准。
十一、这种方法是不是“强行造了一个 1M”
从客户端角度看,确实比较直接。
CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000
相当于明确告诉 Claude Desktop:
当前活动模型按照 1,000,000 token 的窗口管理
但它不会改变模型真实能力。
如果上游实际只有 256K,而客户端被设置成 1M,就可能出现:
Claude Desktop 认为还有空间
↓
继续发送更长的请求
↓
上游先到达真实限制
↓
返回 context length exceeded
因此,这个方法只适用于:
已经确认上游模型支持对应上下文,但 Claude Desktop 没有正确识别的情况。
不能因为界面显示 1M,就认为模型真的拥有 1M 上限。
十二、全局覆盖带来的副作用
CLAUDE_CODE_MAX_CONTEXT_TOKENS 是全局环境变量。
这意味着它可能影响所有通过该 Claude Code / Claude Desktop 配置启动的模型,而不只是 deepseek-v4-pro。
例如模型菜单中同时存在:
deepseek-v4-pro
deepseek-v4-pro 1M
glm-5.2
glm-5.2 1M
设置全局覆盖后,普通模型也可能显示成 1M。
因此长期使用时需要注意:
- 只切换到确实支持 1M 的模型;
- 不要把 200K 或 256K 模型误当成 1M;
- 切换模型后检查 Context window;
- 上游返回上下文超限时,优先核对真实模型能力。
如果以后 CC Switch 和 Claude Desktop 的 supports1m 映射能够稳定生效,最好移除全局覆盖,改用模型菜单中的 1M 变体。
十三、如何撤销全局 1M 覆盖
撤销不会删除历史会话,也不会破坏 CC Switch 的模型映射。
PowerShell:
$path = "$env:USERPROFILE\.claude\settings.json"
if (Test-Path $path) {
$backup = "$path.bak-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
Copy-Item $path $backup
$cfg = Get-Content $path -Raw | ConvertFrom-Json
if ($cfg.env) {
$cfg.env.PSObject.Properties.Remove(
"CLAUDE_CODE_MAX_CONTEXT_TOKENS"
)
$cfg.env.PSObject.Properties.Remove(
"DISABLE_COMPACT"
)
}
$cfg |
ConvertTo-Json -Depth 100 |
Set-Content $path -Encoding UTF8
Write-Host "已移除全局上下文覆盖"
Write-Host "备份文件:$backup"
}
然后彻底重启 Claude Desktop。
撤销后:
- 普通模型恢复客户端默认上下文判断;
- CC Switch 中的
supports1m配置仍然保留; - OpenCode Go 的 API Key 和实际请求模型不会受影响。
十四、最终可复现配置
CC Switch
API 格式:
OpenAI Chat Completions
需要模型映射:
开启
模型角色:
Opus
菜单显示名:
deepseek-v4-pro
实际请求模型:
deepseek-v4-pro
声明支持 1M:
开启
Claude Desktop 本地路由:
开启
Claude Code 设置
文件:
%USERPROFILE%\.claude\settings.json
配置:
{
"env": {
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "1000000"
}
}
若当前版本中该变量完全不生效,再测试:
{
"env": {
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "1000000",
"DISABLE_COMPACT": "1"
}
}
启动顺序
启动 CC Switch
→ 开启 Claude Desktop 本地路由
→ 完全退出旧 Claude Desktop 进程
→ 重新打开 Claude Desktop
→ 新建会话
→ 选择目标模型
→ 检查 Context window
预期结果:
... / 1.0M
十五、排障清单
1. 检查 supports1m
Get-Content "$env:LOCALAPPDATA\Claude-3p\configLibrary\00000000-0000-4000-8000-000000157210.json" |
Select-String "supports1m|labelOverride"
2. 检查上下文覆盖
Get-Content "$env:USERPROFILE\.claude\settings.json" |
Select-String "CLAUDE_CODE_MAX_CONTEXT_TOKENS|DISABLE_COMPACT"
3. 检查本地路由
确认 CC Switch 中 Claude Desktop 本地路由处于开启状态。
4. 检查残留进程
Get-Process |
Where-Object {
$_.ProcessName -match "Claude"
}
5. 使用新会话验证
旧会话可能保留启动时读取的模型状态。修改后优先创建新会话测试。
6. 确认真实模型能力
客户端显示 1M 不等于上游真的支持 1M。应以 OpenCode Go 的模型说明和实际 API 返回为准。
十六、复盘
一开始我以为:
勾选支持 1M
→ Claude Desktop 自动显示 1M
实际排查后才发现,中间至少有三层:
上游真实上下文能力
↓
CC Switch 模型映射与能力声明
↓
Claude Desktop 本地上下文预算
任何一层没有对齐,最终显示都会不正常。
这次的问题并不是:
- API Key 配置错误;
- OpenCode Go 一定不支持 1M;
- 实际请求模型名称写错;
- CC Switch 没有保存
supports1m。
真正的问题是:
Claude Desktop 没有把第三方模型的长上下文能力正确应用到当前会话预算中。
而:
CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000
所做的事情,就是直接覆盖客户端的上下文判断。
它不是给模型扩容,也不是修改 OpenCode Go 的模型,而是修正 Claude Desktop 对当前第三方模型上下文窗口的识别。
以后再遇到类似问题,可以按照这个顺序排查:
确认上游真实能力
→ 确认实际请求模型
→ 检查 CC Switch 映射
→ 检查 supports1m
→ 完全重启 Claude Desktop
→ 最后再使用客户端上下文覆盖