farion1231/cc-switch

[Bug] Claude 1M context marker fails: uppercase [1M] written + fallback model lacks toggle

Open

#3,679 opened on Jun 4, 2026

View on GitHub
 (3 comments) (0 reactions) (0 assignees)Rust (71,012 stars) (4,558 forks)batch import
buggood first issue

Description

[Bug] Claude 1M context marker fails: uppercase [1M] written + fallback model lacks toggle

概要 / Summary

cc-switch 在为 Claude Code 配置 1M context 时存在两个相关问题,导致用户勾选"声明支持 1M"后 1M context 实际并未启用

  1. Bug 1:写入的 marker 是大写 [1M],但 Claude Code 官方只识别小写 [1m]
  2. Bug 2:默认兜底模型(ANTHROPIC_MODEL)输入框旁边没有"声明支持 1M"勾选框,而它的优先级高于 alias 字段,会反向覆盖三角色的设置

环境(已验证):

  • cc-switch v3.16.1(main 当前 HEAD ce53826
  • Claude Code v2.1.161
  • macOS 25.4.0
  • model: claude-opus-4-7

Bug 1:Marker 写入用大写 [1M]

位置

src/components/providers/forms/hooks/useModelState.ts:17

export const CLAUDE_ONE_M_MARKER = "[1M]";

表现

  1. 在 cc-switch 模型映射区,为 Sonnet/Opus 勾选"声明支持 1M"
  2. 保存并启动 Claude Code
  3. /context 命令输出仍显示 200K tokens 分母,不是预期的 1M
  4. 检查 ~/.claude/settings.json,发现写入的是 claude-opus-4-7[1M](大写)
  5. 手动改成 claude-opus-4-7[1m](小写)后重启 Claude Code,/context 立刻变为 1m tokens

根因

Claude Code 官方文档 model-config 原文明确要求小写:

Append [1m] to the model ID to enable the 1M context window for a pinned model.

源码读取路径(第 20、25 行)都用 .toLowerCase() 容错,所以已经写入的大写值能被正确识别和 strip——这隐藏了写入侧的 bug:

// L20 — 读取容错
return model.trimEnd().toLowerCase().endsWith("[1m]");

// L25 — strip 容错
if (!trimmedEnd.toLowerCase().endsWith("[1m]")) return model;

// L32 — 写入硬编码大写!
return enabled ? `${base}${CLAUDE_ONE_M_MARKER}` : base;

修复

一行修改(见 patch 01-bug1-marker-lowercase.patch):

-export const CLAUDE_ONE_M_MARKER = "[1M]";
+export const CLAUDE_ONE_M_MARKER = "[1m]";

Bug 2:默认兜底模型缺"声明支持 1M"勾选框

位置

src/components/providers/forms/ClaudeFormFields.tsx:924

表现

模型映射区为 Sonnet/Opus/Haiku 三个角色提供"声明支持 1M"勾选框(截图见下),但底部"默认兜底模型"(ANTHROPIC_MODEL)输入框旁边没有同样的勾选框。

普通用户即使在 Sonnet/Opus 勾选了 1M(在叠加 Bug 1 修复后写出正确的 [1m]),只要兜底模型未带 [1m],1M 仍不会启用。

根因

Claude Code 官方文档 env-vars 原文:

ANTHROPIC_MODEL overrides the model setting

兜底模型优先级高于所有 alias 解析(ANTHROPIC_DEFAULT_OPUS_MODEL 等)。当用户在三角色上勾选 1M(写入 _DEFAULT_OPUS_MODEL=...[1m]),但兜底字段没带 [1m] 后缀时,兜底硬覆盖所有 alias,1M 不会被启用

这跟 Bug 1 叠加时影响放大:

  • 用户在 cc-switch UI 完成所有勾选 → 觉得"配置好了"
  • 实际启动 Claude Code → 1M 没启用
  • 调查后才会发现:UI 没暴露兜底字段的 1M 开关

社区已有用户反馈过类似问题(discussion #2693 中用户提到:"我的默认兜底模型是 deepseek-v4-pro[1m] cc-switch 选择时没有后面的 [1m] 这是我自己加的")。

修复

UI 加 checkbox + state 联动(见 patch 02-bug2-fallback-1m-checkbox.patch),约 25 行 inline 改动,复用现有 i18n key providerForm.modelOneMLabel,不引入新依赖、不重构数组。


修复验证(本地)

Patch 1 单独应用后

操作 结果
在 Sonnet/Opus 勾选 1M settings.json 写入 ...[1m] ✓(之前是 [1M]
Bug 2 仍未修,兜底字段无 [1m] 1M 仍不启用 ✗(被 ANTHROPIC_MODEL 覆盖)

Patch 1 + Patch 2 一起应用后

操作 结果
在 Sonnet/Opus 勾选 1M + 兜底字段勾选 1M settings.json 全部 ...[1m]
重启 Claude Code,/context 显示 1M tokens 分母 ✓
transcript.model 字段 claude-opus-4-7[1m](带后缀) ✓

建议

两个 bug 强相关,建议合并到同一个 PR 修复。Patch 1 是 1 行修改,Patch 2 是 ~25 行 UI inline。

如果要拆,至少 Bug 1 应该单独 cherry-pick 优先合入——它对所有用户都是无副作用的安全修复。

Contributor guide