refactor: 提取 HandlerAdapterBase 基类,新增 api_family/endpoint_kind 结构化维度

- 从 ChatAdapterBase 和 CliAdapterBase 提取公共逻辑到 HandlerAdapterBase,
  消除头部处理、异常处理、计费策略等重复代码
- Usage 记录链路全程透传 api_family / endpoint_kind / provider_api_family /
  provider_endpoint_kind 四个结构化字段,替代从 api_format 字符串解析
- 删除冗余的 ClaudeCliNormalizer、GeminiCliNormalizer、ClaudeCliResponseParser、
  GeminiCliResponseParser,改用 data_format_id 回退机制自动复用 Chat 版本
- build_endpoint_url 签名统一扩展 request_data / model_name 参数
- 新增 Alembic 迁移,含历史数据回填
This commit is contained in:
fawney19
2026-02-21 13:17:11 +08:00
parent 54988916e3
commit 0fe5346f4d
36 changed files with 967 additions and 1310 deletions

View File

@@ -11,9 +11,7 @@ from __future__ import annotations
from typing import Any, cast
from src.core.api_format.conversion.normalizers.claude import ClaudeNormalizer
from src.core.api_format.conversion.normalizers.claude_cli import ClaudeCliNormalizer
from src.core.api_format.conversion.normalizers.gemini import GeminiNormalizer
from src.core.api_format.conversion.normalizers.gemini_cli import GeminiCliNormalizer
from src.core.api_format.conversion.normalizers.openai import OpenAINormalizer
from src.core.api_format.conversion.normalizers.openai_cli import OpenAICliNormalizer
from src.core.api_format.conversion.registry import FormatConversionRegistry
@@ -26,9 +24,8 @@ def _make_registry_with_cli() -> FormatConversionRegistry:
reg.register(OpenAINormalizer())
reg.register(OpenAICliNormalizer())
reg.register(ClaudeNormalizer())
reg.register(ClaudeCliNormalizer())
reg.register(GeminiNormalizer())
reg.register(GeminiCliNormalizer())
# claude:cli / gemini:cli 通过 data_format_id 回退自动复用对应的 Chat normalizer
return reg
@@ -405,15 +402,13 @@ def test_stream_openai_cli_noop_and_unknown_events() -> None:
# noop 事件不应产生内部事件
assert (
normalizer.stream_chunk_to_internal({"type": "response.function_call_arguments.done"}, state)
normalizer.stream_chunk_to_internal(
{"type": "response.function_call_arguments.done"}, state
)
== []
)
assert (
normalizer.stream_chunk_to_internal({"type": "response.content_part.added"}, state) == []
)
assert (
normalizer.stream_chunk_to_internal({"type": "response.content_part.done"}, state) == []
)
assert normalizer.stream_chunk_to_internal({"type": "response.content_part.added"}, state) == []
assert normalizer.stream_chunk_to_internal({"type": "response.content_part.done"}, state) == []
# unknown 事件应返回 UnknownStreamEvent
events = normalizer.stream_chunk_to_internal(