refactor: 继续拆分大型模块并增强模块注册健壮性

后端:
- chat_handler_base 错误处理函数提取到 chat_error_utils 子模块
- CLI mixin 引入 CliHandlerProtocol 协议类改善类型标注
- aware_scheduler 拆分为 _candidate_builder 和 _candidate_sorter 子模块
- usage recording 拆分为 _billing_integration 和 _recording_helpers 子模块
- ModuleRegistry 添加循环依赖检测,将写操作从查询方法分离到 reconcile_module_state
- 修正 plugin manager 入度注释

前端:
- 路由守卫逻辑拆分为独立 guards 模块
- ProviderManagement 拆分为 TableHeader/TableRow/BalanceCell/MobileCard 子组件
- SystemSettings 拆分为多个 Section 子组件和 composables
- 提取 useEndpointStatus/useProviderBalance/useProviderFilters composables

测试适配重构后的子模块结构
This commit is contained in:
fawney19
2026-02-14 20:06:38 +08:00
parent 676e918edc
commit 8a670f5524
51 changed files with 7095 additions and 5359 deletions

View File

@@ -38,8 +38,9 @@ async def test_build_candidates_allows_cross_format_when_endpoint_accepts_and_ov
register_default_normalizers()
scheduler = CacheAwareScheduler()
scheduler._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
scheduler._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
builder = scheduler._candidate_builder
builder._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
builder._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
provider = MagicMock()
provider.name = "p1"
@@ -52,7 +53,7 @@ async def test_build_candidates_allows_cross_format_when_endpoint_accepts_and_ov
]
provider.api_keys = [_mock_key("k1", ["openai:chat"])]
candidates = await scheduler._build_candidates(
candidates = await builder._build_candidates(
db=MagicMock(),
providers=[provider],
client_format="claude:chat",
@@ -75,8 +76,9 @@ async def test_build_candidates_allows_cross_format_when_global_off_but_endpoint
register_default_normalizers()
scheduler = CacheAwareScheduler()
scheduler._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
scheduler._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
builder = scheduler._candidate_builder
builder._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
builder._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
provider = MagicMock()
provider.name = "p1"
@@ -89,7 +91,7 @@ async def test_build_candidates_allows_cross_format_when_global_off_but_endpoint
]
provider.api_keys = [_mock_key("k1", ["openai:chat"])]
candidates = await scheduler._build_candidates(
candidates = await builder._build_candidates(
db=MagicMock(),
providers=[provider],
client_format="claude:chat",
@@ -114,8 +116,9 @@ async def test_build_candidates_blocks_cross_format_when_global_off_and_endpoint
register_default_normalizers()
scheduler = CacheAwareScheduler()
scheduler._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
scheduler._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
builder = scheduler._candidate_builder
builder._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
builder._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
provider = MagicMock()
provider.name = "p1"
@@ -123,7 +126,7 @@ async def test_build_candidates_blocks_cross_format_when_global_off_and_endpoint
provider.endpoints = [_mock_endpoint("openai:chat", None)] # 端点未配置格式接受策略
provider.api_keys = [_mock_key("k1", ["openai:chat"])]
candidates = await scheduler._build_candidates(
candidates = await builder._build_candidates(
db=MagicMock(),
providers=[provider],
client_format="claude:chat",
@@ -141,8 +144,9 @@ async def test_build_candidates_includes_cross_format_when_enabled() -> None:
register_default_normalizers()
scheduler = CacheAwareScheduler()
scheduler._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
scheduler._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
builder = scheduler._candidate_builder
builder._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
builder._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
provider = MagicMock()
provider.name = "p1"
@@ -153,7 +157,7 @@ async def test_build_candidates_includes_cross_format_when_enabled() -> None:
]
provider.api_keys = [_mock_key("k1", ["openai:chat"])]
candidates = await scheduler._build_candidates(
candidates = await builder._build_candidates(
db=MagicMock(),
providers=[provider],
client_format="claude:chat",
@@ -172,8 +176,9 @@ async def test_exact_matches_rank_before_convertible() -> None:
register_default_normalizers()
scheduler = CacheAwareScheduler()
scheduler._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
scheduler._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
builder = scheduler._candidate_builder
builder._check_model_support = AsyncMock(return_value=(True, None, None, {"m"})) # type: ignore[method-assign]
builder._check_key_availability = MagicMock(return_value=(True, None, None)) # type: ignore[method-assign]
provider = MagicMock()
provider.name = "p1"
@@ -191,7 +196,7 @@ async def test_exact_matches_rank_before_convertible() -> None:
_mock_key("k_claude", ["claude:chat"]),
]
candidates = await scheduler._build_candidates(
candidates = await builder._build_candidates(
db=MagicMock(),
providers=[provider],
client_format="claude:chat",