fix: 修复同族 API 格式转换判断逻辑

- OPENAI 和 OPENAI_CLI 使用不同协议(Chat Completions vs Responses API),需要转换
- CLAUDE/CLAUDE_CLI、GEMINI/GEMINI_CLI 格式相同仅认证不同,可透传
- 添加 max_completion_tokens 参数支持(OpenAI 新参数名)
- 移除登录表单冗余的 keyup.enter 事件处理
This commit is contained in:
fawney19
2026-01-27 21:59:12 +08:00
parent 6f340b7b91
commit 3c0bf5fdae
9 changed files with 220 additions and 14 deletions

View File

@@ -16,6 +16,9 @@
"B"
],
"stream": true,
"stream_options": {
"include_usage": true
},
"temperature": 0.2,
"tool_choice": "auto",
"tools": [

View File

@@ -161,3 +161,123 @@ def test_conversion_allowed_when_converter_supports_full() -> None:
assert ok is True
assert needs_conv is True
assert reason is None
# ==================== 同族格式测试 ====================
def test_claude_cli_to_claude_no_conversion_needed() -> None:
"""CLAUDE 和 CLAUDE_CLI 格式相同,只是认证不同,可透传"""
ok, needs_conv, reason = is_format_compatible(
"CLAUDE_CLI",
"CLAUDE",
endpoint_format_acceptance_config=None,
is_stream=False,
global_conversion_enabled=False,
registry=MagicMock(),
)
assert ok is True
assert needs_conv is False
assert reason is None
def test_claude_to_claude_cli_no_conversion_needed() -> None:
"""CLAUDE 和 CLAUDE_CLI 格式相同,只是认证不同,可透传"""
ok, needs_conv, reason = is_format_compatible(
"CLAUDE",
"CLAUDE_CLI",
endpoint_format_acceptance_config=None,
is_stream=False,
global_conversion_enabled=False,
registry=MagicMock(),
)
assert ok is True
assert needs_conv is False
assert reason is None
def test_gemini_cli_to_gemini_no_conversion_needed() -> None:
"""GEMINI 和 GEMINI_CLI 格式相同,只是认证不同,可透传"""
ok, needs_conv, reason = is_format_compatible(
"GEMINI_CLI",
"GEMINI",
endpoint_format_acceptance_config=None,
is_stream=False,
global_conversion_enabled=False,
registry=MagicMock(),
)
assert ok is True
assert needs_conv is False
assert reason is None
def test_openai_cli_to_openai_needs_conversion() -> None:
"""OPENAI 和 OPENAI_CLI 格式不同Chat Completions vs Responses API需要转换"""
registry = MagicMock()
registry.can_convert_full.return_value = True
ok, needs_conv, reason = is_format_compatible(
"OPENAI_CLI",
"OPENAI",
endpoint_format_acceptance_config=None, # 同族转换不需要端点配置
is_stream=False,
global_conversion_enabled=False, # 同族转换不需要全局开关
registry=registry,
)
assert ok is True
assert needs_conv is True # 需要转换!
assert reason is None
def test_openai_to_openai_cli_needs_conversion() -> None:
"""OPENAI 和 OPENAI_CLI 格式不同Chat Completions vs Responses API需要转换"""
registry = MagicMock()
registry.can_convert_full.return_value = True
ok, needs_conv, reason = is_format_compatible(
"OPENAI",
"OPENAI_CLI",
endpoint_format_acceptance_config=None, # 同族转换不需要端点配置
is_stream=False,
global_conversion_enabled=False, # 同族转换不需要全局开关
registry=registry,
)
assert ok is True
assert needs_conv is True # 需要转换!
assert reason is None
def test_openai_cli_to_openai_stream_needs_conversion() -> None:
"""OPENAI_CLI 流式请求到 OPENAI 也需要转换"""
registry = MagicMock()
registry.can_convert_full.return_value = True
ok, needs_conv, reason = is_format_compatible(
"OPENAI_CLI",
"OPENAI",
endpoint_format_acceptance_config=None,
is_stream=True,
global_conversion_enabled=False,
registry=registry,
)
assert ok is True
assert needs_conv is True
assert reason is None
def test_openai_cli_to_openai_fails_without_converter() -> None:
"""如果转换器不支持,同族转换也会失败"""
registry = MagicMock()
registry.can_convert_full.return_value = False
ok, needs_conv, reason = is_format_compatible(
"OPENAI_CLI",
"OPENAI",
endpoint_format_acceptance_config=None,
is_stream=False,
global_conversion_enabled=False,
registry=registry,
)
assert ok is False
assert needs_conv is False
assert reason and "转换器" in reason

View File

@@ -81,6 +81,39 @@ def test_openai_request_instructions_roundtrip() -> None:
assert out_messages[3]["content"] == "ok"
def test_openai_request_max_completion_tokens_support() -> None:
"""测试 max_completion_tokens 参数的兼容性OpenAI API 新参数名)"""
n = OpenAINormalizer()
# 测试 max_completion_tokens 优先于 max_tokens
req_new = {
"model": "gpt-4o",
"messages": [{"role": "user", "content": "hi"}],
"max_completion_tokens": 100,
"max_tokens": 50, # 旧参数应被忽略
}
internal = n.request_to_internal(req_new)
assert internal.max_tokens == 100
# 测试仅使用 max_completion_tokens
req_only_new = {
"model": "gpt-4o",
"messages": [{"role": "user", "content": "hi"}],
"max_completion_tokens": 200,
}
internal = n.request_to_internal(req_only_new)
assert internal.max_tokens == 200
# 测试仅使用 max_tokens向后兼容
req_only_old = {
"model": "gpt-4o",
"messages": [{"role": "user", "content": "hi"}],
"max_tokens": 150,
}
internal = n.request_to_internal(req_only_old)
assert internal.max_tokens == 150
def test_openai_request_tool_calls_and_tool_role_roundtrip() -> None:
n = OpenAINormalizer()