feat(test,export,headers): 模型测试复用统一运行时、实时进度展示、导出增强与请求头大小写保留

- 模型测试 failover 从手动 FailoverEngine 改为 TaskService.execute_sync_candidates 统一运行时
- 前端新增实时 trace 轮询进度展示(候选状态、测试账号、进度条)
- 用户导出/导入支持明文 Key 优先(版本升至 1.2),新增 email_verified 字段
- SENSITIVE_CREDENTIAL_FIELDS 统一到 provider_ops/types.py,补充 refresh_token
- 请求头大小写保留机制(resolve_header_name_case + HeaderBuilder.add 语义修改)
- Codex envelope 移除合成头部,保留客户端原始请求头
- endpoint_checker 支持自定义超时透传
- 新增 x-forwarded-scheme 到上游丢弃头部列表
This commit is contained in:
fawney19
2026-03-06 21:06:45 +08:00
parent 7950ba7dc5
commit 90760da499
28 changed files with 1485 additions and 429 deletions

View File

@@ -2,7 +2,9 @@ from types import SimpleNamespace
from src.api.admin.provider_query import (
_build_direct_test_candidates,
_build_test_attempts_from_candidate_keys,
_filter_test_candidates_by_endpoint,
_resolve_test_effective_model,
)
@@ -36,3 +38,54 @@ def test_filter_test_candidates_by_endpoint_keeps_matching_candidates() -> None:
assert {candidate.endpoint.id for candidate in filtered} == {endpoint_a.id}
assert all(candidate.endpoint.id != endpoint_b.id for candidate in filtered)
def test_resolve_test_effective_model_prefers_pool_key_mapping() -> None:
provider, endpoint_a, _endpoint_b = _build_provider()
candidate = _build_direct_test_candidates(provider, endpoint_id=endpoint_a.id)[0] # type: ignore[arg-type]
pool_key = SimpleNamespace(id="pool-key", _pool_mapping_matched_model="mapped-model")
request = SimpleNamespace(mode="global", model_name="gpt-4")
effective = _resolve_test_effective_model(
provider=provider, # type: ignore[arg-type]
candidate=candidate,
request=request, # type: ignore[arg-type]
gm_obj=None,
key=pool_key,
)
assert effective == "mapped-model"
def test_build_test_attempts_from_candidate_keys_includes_retry_index() -> None:
candidate_keys = [
SimpleNamespace(
candidate_index=2,
retry_index=1,
key_id="key-b",
key_name="Key B",
auth_type="api_key",
status="failed",
skip_reason=None,
error_message="timeout",
status_code=504,
latency_ms=1200,
)
]
attempts = _build_test_attempts_from_candidate_keys(
candidate_keys=candidate_keys,
candidate_meta_by_pair={
(2, "key-b"): {
"endpoint_api_format": "openai:chat",
"endpoint_base_url": "https://example.test/v1",
"effective_model": "mapped-model",
}
},
candidate_meta_by_index={},
)
assert len(attempts) == 1
assert attempts[0].retry_index == 1
assert attempts[0].effective_model == "mapped-model"
assert attempts[0].endpoint_api_format == "openai:chat"