mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 12:44:18 +08:00
fix(codex): reject web_search for Qwen3-Coder and correct LongCat context window
- Add `qwen3-coder` to the web_search reject model-prefix blacklist so the native qwen3-coder-plus direct-connect preset suppresses the built-in tool (百炼 rejects it for the coder series), while general Qwen models sharing the DashScope host keep web_search enabled. Matched on the model axis, not host. - Correct LongCat-2.0-Preview context window from 128K to its real 1M (1048576), aligning with the MiMo/Qwen 2^20 convention. - Tighten native Responses preset tests to assert exact model→contextWindow catalogs instead of only checking catalog presence.
This commit is contained in:
@@ -37,10 +37,11 @@ const CODEX_WEB_SEARCH_DISABLED: &str = "disabled";
|
||||
/// - `base_url` host substring, and
|
||||
/// - the model id's brand prefix (after stripping any `vendor/` path segment).
|
||||
///
|
||||
/// Verified 2026-06-27 doc audit — reject: MiMo (hard 400), LongCat (official
|
||||
/// Verified 2026-06-28 doc audit — reject: MiMo (hard 400), LongCat (official
|
||||
/// config ships `web_search = "disabled"`), MiniMax (tool-type enum `['function']`
|
||||
/// only). Deliberately NOT listed (they support it): 火山方舟豆包, 阿里百炼 Qwen,
|
||||
/// and all GPT-native relays.
|
||||
/// only), and Qwen3-Coder models (百炼 marks built-in tools unsupported for
|
||||
/// the coder series). Deliberately NOT listed by host: 火山方舟豆包, general
|
||||
/// 阿里百炼 Qwen models that support built-in web_search, and GPT-native relays.
|
||||
const CODEX_WEB_SEARCH_REJECT_HOSTS: &[&str] = &[
|
||||
"xiaomimimo.com", // Xiaomi MiMo (api.xiaomimimo.com, token-plan-cn.xiaomimimo.com)
|
||||
"longcat.chat", // Meituan LongCat (api.longcat.chat)
|
||||
@@ -52,7 +53,8 @@ const CODEX_WEB_SEARCH_REJECT_HOSTS: &[&str] = &[
|
||||
/// against the model id's last `/`-segment so aggregator ids like
|
||||
/// `MiniMaxAI/MiniMax-M3` are caught. Exact brand names (not a fuzzy heuristic),
|
||||
/// so a supporting gateway is never wrongly matched.
|
||||
const CODEX_WEB_SEARCH_REJECT_MODEL_PREFIXES: &[&str] = &["mimo", "longcat", "minimax"];
|
||||
const CODEX_WEB_SEARCH_REJECT_MODEL_PREFIXES: &[&str] =
|
||||
&["mimo", "longcat", "minimax", "qwen3-coder"];
|
||||
|
||||
/// Top-level `model` id from a Codex `config.toml`.
|
||||
fn codex_top_level_model(config_text: &str) -> Option<String> {
|
||||
@@ -79,7 +81,8 @@ fn codex_native_gateway_rejects_web_search(config_text: &str) -> bool {
|
||||
}
|
||||
if let Some(model) = codex_top_level_model(config_text) {
|
||||
let model = model.to_ascii_lowercase();
|
||||
// Strip any aggregator "vendor/" prefix, e.g. "MiniMaxAI/MiniMax-M3".
|
||||
// Strip any aggregator "vendor/" prefix, e.g. "MiniMaxAI/MiniMax-M3"
|
||||
// or "qwen/qwen3-coder-plus".
|
||||
let model = model.rsplit('/').next().unwrap_or(model.as_str());
|
||||
if CODEX_WEB_SEARCH_REJECT_MODEL_PREFIXES
|
||||
.iter()
|
||||
@@ -948,8 +951,9 @@ pub fn prepare_codex_config_text_with_model_catalog(
|
||||
if let Some(catalog) = codex_model_catalog_from_settings(settings, config_text, profile)? {
|
||||
let config_text = set_codex_model_catalog_json_field(config_text, Some(&catalog_path))?;
|
||||
// Disable web_search only for native gateways on the reject blacklist
|
||||
// (MiMo/LongCat/MiniMax, by host or model brand). Everything else —
|
||||
// relays, DouBao/Qwen, unknown providers — keeps Codex's default.
|
||||
// (MiMo/LongCat/MiniMax by host or model brand; Qwen3-Coder by model).
|
||||
// Everything else — relays, DouBao, web-search-capable Qwen models,
|
||||
// unknown providers — keeps Codex's default.
|
||||
let disable_web_search = profile == CodexCatalogToolProfile::NativeResponses
|
||||
&& codex_native_gateway_rejects_web_search(&config_text);
|
||||
let config_text = set_codex_native_web_search_field(&config_text, disable_web_search)?;
|
||||
@@ -2622,6 +2626,10 @@ web_search = "disabled"
|
||||
("MiniMax-M3", "https://api.siliconflow.cn/v1"),
|
||||
("MiniMaxAI/MiniMax-M3", "https://api.siliconflow.cn/v1"),
|
||||
("mimo-v2.5-pro", "https://some-aggregator.example/v1"),
|
||||
(
|
||||
"qwen/qwen3-coder-plus",
|
||||
"https://some-aggregator.example/v1",
|
||||
),
|
||||
] {
|
||||
assert!(
|
||||
codex_native_gateway_rejects_web_search(&cfg(model, host)),
|
||||
@@ -2629,8 +2637,20 @@ web_search = "disabled"
|
||||
);
|
||||
}
|
||||
|
||||
// NOT blacklisted → keep Codex default (relays/GPT, DouBao, Qwen, and any
|
||||
// unknown provider incl. an aggregator serving a non-reject model).
|
||||
// Qwen3-Coder is blacklisted by model, not by DashScope host. This keeps
|
||||
// general Qwen models that support built-in web_search on the same host
|
||||
// enabled while protecting the native qwen3-coder-plus preset.
|
||||
assert!(codex_native_gateway_rejects_web_search(&cfg(
|
||||
"qwen3-coder-plus",
|
||||
"https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
)));
|
||||
assert!(!codex_native_gateway_rejects_web_search(&cfg(
|
||||
"qwen3.7-plus",
|
||||
"https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
)));
|
||||
|
||||
// NOT blacklisted → keep Codex default (relays/GPT, DouBao, general Qwen,
|
||||
// and any unknown provider incl. an aggregator serving a non-reject model).
|
||||
for (model, host) in [
|
||||
("gpt-5.5", "https://www.packyapi.com/v1"),
|
||||
("gpt-5-codex", "https://aihubmix.com/v1"),
|
||||
@@ -2638,10 +2658,6 @@ web_search = "disabled"
|
||||
"doubao-seed-2-1-pro",
|
||||
"https://ark.cn-beijing.volces.com/api/v3",
|
||||
),
|
||||
(
|
||||
"qwen3-coder-plus",
|
||||
"https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
),
|
||||
("Pro/moonshotai/Kimi-K2.6", "https://api.siliconflow.cn/v1"),
|
||||
] {
|
||||
assert!(
|
||||
|
||||
@@ -625,7 +625,7 @@ requires_openai_auth = true`,
|
||||
{
|
||||
model: "LongCat-2.0-Preview",
|
||||
displayName: "LongCat 2.0 Preview",
|
||||
contextWindow: 131072,
|
||||
contextWindow: 1048576,
|
||||
},
|
||||
]),
|
||||
category: "cn_official",
|
||||
|
||||
@@ -154,17 +154,36 @@ describe("Codex Chat provider presets", () => {
|
||||
});
|
||||
|
||||
it("uses native Responses API for migrated CN providers without local route mapping", () => {
|
||||
const nativeResponsesPresets = [
|
||||
"DouBaoSeed",
|
||||
"Bailian",
|
||||
"Longcat",
|
||||
"MiniMax",
|
||||
"MiniMax en",
|
||||
"Xiaomi MiMo",
|
||||
"Xiaomi MiMo Token Plan (China)",
|
||||
];
|
||||
const nativeResponsesPresets = new Map<
|
||||
string,
|
||||
{ contextWindows: Record<string, number> }
|
||||
>([
|
||||
["DouBaoSeed", { contextWindows: { "doubao-seed-2-1-pro": 262144 } }],
|
||||
["Bailian", { contextWindows: { "qwen3-coder-plus": 1048576 } }],
|
||||
["Longcat", { contextWindows: { "LongCat-2.0-Preview": 1048576 } }],
|
||||
["MiniMax", { contextWindows: { "MiniMax-M3": 1000000 } }],
|
||||
["MiniMax en", { contextWindows: { "MiniMax-M3": 1000000 } }],
|
||||
[
|
||||
"Xiaomi MiMo",
|
||||
{
|
||||
contextWindows: {
|
||||
"mimo-v2.5-pro": 1048576,
|
||||
"mimo-v2.5": 1048576,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"Xiaomi MiMo Token Plan (China)",
|
||||
{
|
||||
contextWindows: {
|
||||
"mimo-v2.5-pro": 1048576,
|
||||
"mimo-v2.5": 1048576,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
for (const name of nativeResponsesPresets) {
|
||||
for (const [name, expected] of nativeResponsesPresets) {
|
||||
const preset = codexProviderPresets.find((item) => item.name === name);
|
||||
|
||||
expect(preset, `${name} preset`).toBeDefined();
|
||||
@@ -174,6 +193,14 @@ describe("Codex Chat provider presets", () => {
|
||||
// apply_patch)。带 catalog 不再强制开“本地路由映射”——前端已按
|
||||
// apiFormat 解耦(openai_responses 默认不开接管)。
|
||||
expect((preset?.modelCatalog ?? []).length).toBeGreaterThan(0);
|
||||
expect(
|
||||
Object.fromEntries(
|
||||
(preset?.modelCatalog ?? []).map((model) => [
|
||||
model.model,
|
||||
model.contextWindow,
|
||||
]),
|
||||
),
|
||||
).toEqual(expected.contextWindows);
|
||||
// 原生(直连)不走 Chat 转换,因此不需要 codexChatReasoning。
|
||||
expect(preset?.codexChatReasoning).toBeUndefined();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user