fix(claude-desktop): show one picker row per 1M model

Claude Desktop lists every model marked supports1m twice: the plain
entry and a "1M context window" variant. Desktop 1.21459.0 added
prefer1m, which keeps only the plain row and hands the embedded CLI
`<id>[1m]` when that row is picked, so the context window stays 1M.

Write prefer1m next to supports1m for every model entry. Route and
aggregation profiles pick it up on the next CC Switch launch (or the
next mode switch); direct profiles keep the old two rows until the
provider is switched or saved again. Requests still arrive with the
[1m] suffix, which routing already strips.
This commit is contained in:
Jason committed 2026-10-16 09:05:15 +08:00
1 parent 0a8d064591
commit d4f2d4e429
3 files changed
+8 -5

No files matched your search

+5 -2
View File
@@ -378,6 +378,9 @@ fn inference_model_json(spec: &InferenceModelSpec) -> Value {
}
if spec.supports_1m {
item["supports1m"] = json!(true);
// 只有 `supports1m` 时 Desktop 每个模型列两行(原名 + 「1M context window」)。
// 加上 `prefer1m`(1.21459.0 起)只列原名,交给内嵌 CLI 时自动补 `[1m]`。
item["prefer1m"] = json!(true);
}
item
} else {
@@ -1844,7 +1847,7 @@ mod tests {
);
assert_eq!(
profile["inferenceModels"],
json!([{ "name": "claude-sonnet-4-6", "supports1m": true }])
json!([{ "name": "claude-sonnet-4-6", "supports1m": true, "prefer1m": true }])
);
}
@@ -1887,7 +1890,7 @@ mod tests {
.starts_with("ccs-"));
assert_eq!(
profile["inferenceModels"],
json!([{ "name": "claude-sonnet-4-6", "labelOverride": "Kimi K2", "supports1m": true }])
json!([{ "name": "claude-sonnet-4-6", "labelOverride": "Kimi K2", "supports1m": true, "prefer1m": true }])
);
assert!(!profile.to_string().contains("kimi-k2"));
}
+2 -2
View File
@@ -114,7 +114,7 @@ fn slug(text: &str) -> String {
}
/// Stack 模型 id。Claude 的上游是 1M 窗口时末尾带 `[1M]`,Claude Code 才按 1M 计算;Claude
/// Desktop 的 1M 写在模型条目里(`supports1m`),id 不带标记。
/// Desktop 的 1M 写在模型条目里(`supports1m` + `prefer1m`),id 不带标记。
pub fn encode(app: &AppType, key: &str, model: &str, one_m: bool) -> String {
match app {
AppType::Codex => format!("{CODEX_PREFIX}{key}{CODEX_SEPARATOR}{model}"),
@@ -182,7 +182,7 @@ pub fn decode<'a>(app: &AppType, id: &'a str) -> Decoded<'a> {
let Some(rest) = id.strip_prefix(DESKTOP_PREFIX) else {
return Decoded::Plain;
};
// Desktop 给 `supports1m` 的条目多生成一行 `<id>[1m]`
// 1M 条目 Desktop 发请求时用 `<id>[1m]`(`prefer1m` 自动补;旧版另列一行)
let code = strip_one_m_suffix_for_upstream(rest);
return if code.len() == DESKTOP_CODE_DIGITS && code.bytes().all(|b| b.is_ascii_digit())
{
+1 -1
View File
@@ -2382,7 +2382,7 @@ requires_openai_auth = true
assert_eq!(profile["inferenceGatewayAuthScheme"], json!("bearer"));
assert_eq!(
profile["inferenceModels"],
json!([{ "name": "claude-sonnet-4-6", "labelOverride": "DeepSeek V4 Flash Updated", "supports1m": true }]),
json!([{ "name": "claude-sonnet-4-6", "labelOverride": "DeepSeek V4 Flash Updated", "supports1m": true, "prefer1m": true }]),
"provider edits should propagate into the Claude Desktop 3P profile during takeover"
);
}