目录

OpenCode Go 接入 Claude Desktop 后上下文一直显示 200K:1M 映射问题排查与解决

214

最近我在 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 负责:

  1. 向 Claude Desktop 暴露能够识别的模型角色;
  2. 将角色模型映射到真正的上游模型;
  3. 在 Anthropic Messages 与 OpenAI Chat Completions 等格式之间转换;
  4. 使用 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 映射方式

在使用全局覆盖之前,建议先完成下面这些步骤:

  1. 在 CC Switch 中编辑 OpenCode Go 供应商;
  2. 开启“需要模型映射”;
  3. deepseek-v4-pro 映射到 Opus 或 Sonnet;
  4. 勾选“声明支持 1M”;
  5. 保存配置;
  6. 回到供应商列表重新启用该供应商;
  7. 确认 Claude Desktop 本地路由已开启;
  8. 完全退出 Claude Desktop;
  9. 重新打开并新建会话;
  10. 在模型菜单中选择生成的 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
→ 最后再使用客户端上下文覆盖

参考资料