Skip to content

Commit a785f3e

Browse files
wehosHongzhi Wen
andauthored
fix(config): 补齐 qwen_intl/minimax/minimax_intl 的 gated fallback(对偶 Project-N-E-K-O#873) (Project-N-E-K-O#876)
* fix(config): qwen_intl/minimax/minimax_intl 也走 gated fallback,对偶 Project-N-E-K-O#873 PR Project-N-E-K-O#873 修掉了 assistApiKey 广播污染,但只对 12 个 provider 统一走了 _fb(),剩下 qwen_intl / minimax / minimax_intl 三个字段仍然是裸 core_cfg.get(...)。结果是:当用户把 coreApi 或 assistApi 选成这三个 provider 之一时,ASSIST_API_KEY_*_INTL / MINIMAX 拿不到 CORE_API_KEY 的 fallback —— 对其他 provider 是"选中就 fallback",对这三个是"永不 fallback",行为不对偶。 本 PR 让这三个字段也走 _fb()。_fallback_providers 集合已经做了 gating, fallback 只在用户实际选中该 provider 时才触发,不会回归 Project-N-E-K-O#873 修掉的 广播污染。两处文件(config_router GET 端点 + config_manager.get_core_config) 对偶修改。 顺手修掉 test_missing_keys_fallback_to_core_key —— 该测试是 Project-N-E-K-O#873 之前 的老行为(断言所有 provider 都 fallback),Project-N-E-K-O#873 merge 时漏改,之前跑 就已经红。新测试覆盖: - test_missing_keys_gated_fallback_to_core_key: 仅选中的 provider fallback, 其余槽位保持空,验证不再广播 - test_special_providers_fallback_when_selected (parametrize 3 个): qwen_intl / minimax / minimax_intl 被选中时也能 fallback * fix(config): 收 Codex P1 反馈 — minimax 不做 fallback @chatgpt-codex-connector 指出:MiniMax 是 assist-only(TTS 专用), 不在 coreApi 候选集里(测试 expected_core 不含 minimax)。所以 coreApiKey 永远不是 minimax 兼容的 key。给 ASSIST_API_KEY_MINIMAX* 加 fallback 会把无效 key 塞进 TTS 凭证槽位,get_tts_api_key('minimax*') 就会用一个 qwen/openai 的 key 去调 minimax → 401,反而掩盖"未配置 minimax key"的真实提示。 Revert minimax/minimax_intl 的 fallback,加注释说清楚为什么排除。 qwen_intl 保留 fallback —— qwen_intl 是合法的 coreApi,migration 场景成立(老版本 core_config.json 只有 coreApiKey 的情况)。 测试对齐: - test_minimax_never_fallbacks 替代原 parametrize 的 minimax case: 即使 assistApi=minimax 也要保持 '' - test_qwen_intl_fallback_when_selected 单独保留 qwen_intl 的正向断言 * test(config): parametrize test_minimax_never_fallbacks 覆盖 minimax_intl CodeRabbit nitpick:原测试只驱动 assistApi='minimax',加上 'minimax_intl' 变体防'仅国际版误回退'的偏置回归。 --------- Co-authored-by: Hongzhi Wen <cartabio.coder1@gmail.com>
1 parent 1e33784 commit a785f3e

3 files changed

Lines changed: 50 additions & 18 deletions

File tree

main_routers/config_router.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ def _fb(provider: str) -> str:
573573
"coreApi": _core_api_provider,
574574
"assistApi": _assist_api_provider,
575575
"assistApiKeyQwen": core_cfg.get('assistApiKeyQwen', '') or _fb('qwen'),
576-
"assistApiKeyQwenIntl": core_cfg.get('assistApiKeyQwenIntl', ''),
576+
"assistApiKeyQwenIntl": core_cfg.get('assistApiKeyQwenIntl', '') or _fb('qwen_intl'),
577577
"assistApiKeyOpenai": core_cfg.get('assistApiKeyOpenai', '') or _fb('openai'),
578578
"assistApiKeyGlm": core_cfg.get('assistApiKeyGlm', '') or _fb('glm'),
579579
"assistApiKeyStep": core_cfg.get('assistApiKeyStep', '') or _fb('step'),
@@ -582,6 +582,9 @@ def _fb(provider: str) -> str:
582582
"assistApiKeyKimi": core_cfg.get('assistApiKeyKimi', '') or _fb('kimi'),
583583
"assistApiKeyDeepseek": core_cfg.get('assistApiKeyDeepseek', '') or _fb('deepseek'),
584584
"assistApiKeyDoubao": core_cfg.get('assistApiKeyDoubao', '') or _fb('doubao'),
585+
# MiniMax 是 assist-only(TTS 专用),不在 coreApi 候选集里,
586+
# coreApiKey 永远不是 minimax 兼容的;不 fallback,以免把无效 key
587+
# 塞进 TTS 凭证槽位导致 401,掩盖"未配置 minimax key"的真实提示。
585588
"assistApiKeyMinimax": core_cfg.get('assistApiKeyMinimax', ''),
586589
"assistApiKeyMinimaxIntl": core_cfg.get('assistApiKeyMinimaxIntl', ''),
587590
"assistApiKeyGrok": core_cfg.get('assistApiKeyGrok', '') or _fb('grok'),

tests/unit/test_api_config_manager.py

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,32 +78,58 @@ def test_round_trip_all_keys(self, config_manager):
7878
)
7979

8080
@pytest.mark.unit
81-
def test_missing_keys_fallback_to_core_key(self, config_manager):
82-
"""Unset assist keys (except minimax) fall back to CORE_API_KEY."""
81+
def test_missing_keys_gated_fallback_to_core_key(self, config_manager):
82+
"""仅用户选中的 coreApi/assistApi 对应的槽位会回退到 CORE_API_KEY,
83+
其余槽位保持空字符串,避免主 Key 被广播到 Key Book 所有栏位。"""
8384
_write_core_config(config_manager, {
8485
'coreApiKey': 'sk-core-master',
8586
'coreApi': 'qwen',
86-
'assistApi': 'qwen',
87+
'assistApi': 'openai',
8788
})
8889
cfg = config_manager.get_core_config()
8990

90-
# These should fall back to CORE_API_KEY
91-
for upper in ['ASSIST_API_KEY_QWEN', 'ASSIST_API_KEY_OPENAI',
92-
'ASSIST_API_KEY_GLM', 'ASSIST_API_KEY_STEP',
91+
# 选中的两个 provider 应该 fallback
92+
assert cfg['ASSIST_API_KEY_QWEN'] == 'sk-core-master'
93+
assert cfg['ASSIST_API_KEY_OPENAI'] == 'sk-core-master'
94+
95+
# 其余所有槽位保持空,不应被 CORE_API_KEY 污染
96+
for upper in ['ASSIST_API_KEY_GLM', 'ASSIST_API_KEY_STEP',
9397
'ASSIST_API_KEY_SILICON', 'ASSIST_API_KEY_GEMINI',
9498
'ASSIST_API_KEY_KIMI', 'ASSIST_API_KEY_DEEPSEEK',
95-
'ASSIST_API_KEY_DOUBAO', 'ASSIST_API_KEY_GROK']:
96-
assert cfg[upper] == 'sk-core-master', (
97-
f'{upper} should fall back to CORE_API_KEY'
99+
'ASSIST_API_KEY_DOUBAO', 'ASSIST_API_KEY_GROK',
100+
'ASSIST_API_KEY_CLAUDE', 'ASSIST_API_KEY_OPENROUTER',
101+
'ASSIST_API_KEY_QWEN_INTL',
102+
'ASSIST_API_KEY_MINIMAX', 'ASSIST_API_KEY_MINIMAX_INTL']:
103+
assert cfg[upper] == '', (
104+
f'{upper} 未被选中,不应 fallback 到 CORE_API_KEY'
98105
)
99106

100-
# MiniMax should NOT fall back
101-
assert cfg['ASSIST_API_KEY_MINIMAX'] == '', (
102-
'MINIMAX must NOT fall back to CORE_API_KEY'
103-
)
104-
assert cfg['ASSIST_API_KEY_MINIMAX_INTL'] == '', (
105-
'MINIMAX_INTL must NOT fall back to CORE_API_KEY'
106-
)
107+
@pytest.mark.unit
108+
def test_qwen_intl_fallback_when_selected(self, config_manager):
109+
"""qwen_intl 是合法的 coreApi,被选中时应 fallback,对偶其他 provider。"""
110+
_write_core_config(config_manager, {
111+
'coreApiKey': 'sk-core-master',
112+
'coreApi': 'qwen_intl',
113+
'assistApi': 'qwen_intl',
114+
})
115+
cfg = config_manager.get_core_config()
116+
assert cfg['ASSIST_API_KEY_QWEN_INTL'] == 'sk-core-master'
117+
118+
@pytest.mark.unit
119+
@pytest.mark.parametrize('assist_api', ['minimax', 'minimax_intl'])
120+
def test_minimax_never_fallbacks(self, config_manager, assist_api):
121+
"""MiniMax 是 assist-only(TTS 专用),不在 coreApi 候选集里,
122+
coreApiKey 永远不是 minimax 兼容的 key。即使 assistApi=minimax* 也不应 fallback,
123+
以免把无效 key 塞进 TTS 凭证槽位导致 401。
124+
parametrize 两个变体防止"仅国际版误回退"的偏置回归。"""
125+
_write_core_config(config_manager, {
126+
'coreApiKey': 'sk-core-master',
127+
'coreApi': 'qwen',
128+
'assistApi': assist_api,
129+
})
130+
cfg = config_manager.get_core_config()
131+
assert cfg['ASSIST_API_KEY_MINIMAX'] == ''
132+
assert cfg['ASSIST_API_KEY_MINIMAX_INTL'] == ''
107133

108134

109135
# ---------------------------------------------------------------------------

utils/config_manager.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1729,7 +1729,7 @@ def _fb(provider: str) -> str:
17291729
return config['CORE_API_KEY'] if provider in _fallback_providers else ''
17301730

17311731
config['ASSIST_API_KEY_QWEN'] = core_cfg.get('assistApiKeyQwen', '') or _fb('qwen')
1732-
config['ASSIST_API_KEY_QWEN_INTL'] = core_cfg.get('assistApiKeyQwenIntl', '')
1732+
config['ASSIST_API_KEY_QWEN_INTL'] = core_cfg.get('assistApiKeyQwenIntl', '') or _fb('qwen_intl')
17331733
config['ASSIST_API_KEY_OPENAI'] = core_cfg.get('assistApiKeyOpenai', '') or _fb('openai')
17341734
config['ASSIST_API_KEY_GLM'] = core_cfg.get('assistApiKeyGlm', '') or _fb('glm')
17351735
config['ASSIST_API_KEY_STEP'] = core_cfg.get('assistApiKeyStep', '') or _fb('step')
@@ -1738,6 +1738,9 @@ def _fb(provider: str) -> str:
17381738
config['ASSIST_API_KEY_KIMI'] = core_cfg.get('assistApiKeyKimi', '') or _fb('kimi')
17391739
config['ASSIST_API_KEY_DEEPSEEK'] = core_cfg.get('assistApiKeyDeepseek', '') or _fb('deepseek')
17401740
config['ASSIST_API_KEY_DOUBAO'] = core_cfg.get('assistApiKeyDoubao', '') or _fb('doubao')
1741+
# MiniMax 是 assist-only(TTS 专用),不在 coreApi 候选集里,
1742+
# coreApiKey 永远不是 minimax 兼容的;不 fallback,以免把无效 key
1743+
# 塞进 TTS 凭证槽位导致 401,掩盖"未配置 minimax key"的真实提示。
17411744
config['ASSIST_API_KEY_MINIMAX'] = core_cfg.get('assistApiKeyMinimax', '')
17421745
config['ASSIST_API_KEY_MINIMAX_INTL'] = core_cfg.get('assistApiKeyMinimaxIntl', '')
17431746
config['ASSIST_API_KEY_GROK'] = core_cfg.get('assistApiKeyGrok', '') or _fb('grok')

0 commit comments

Comments
 (0)