refactor: 引入模块钩子系统,解耦认证逻辑,支持模块/normalizer/parser 自动发现

- 新增 HookDispatcher 钩子分发器,支持 FIRST_RESULT 和 COLLECT_ALL 两种策略
- LDAP 认证逻辑从 AuthService 移至 ldap 模块钩子实现
- Management Token 前缀认证从 pipeline 硬编码改为模块钩子注册
- src/modules/ 改为自动扫描子目录发现 ModuleDefinition
- normalizers 和 parsers 注册改为基于类属性自动发现
- OpenAI CLI 增加 /v1/responses/compact 端点和并行 tool_call 支持
- OpenAI CLI normalizer 支持 Chat Completions 格式自动回退
- Codex 适配器增加 compact 模式上下文传递和 header 调整
- HeaderBuilder 改进非 latin-1 字符处理(UTF-8 字节透传)
- Gunicorn 增加 graceful_timeout 防止僵尸进程
This commit is contained in:
fawney19
2026-02-19 21:26:18 +08:00
parent 7a81e56553
commit 5629edf487
23 changed files with 953 additions and 226 deletions

View File

@@ -334,19 +334,21 @@ class HeaderBuilder:
def build(self) -> dict[str, str]:
"""构建最终的头部字典
Safety net: 跳过值中包含非 ASCII 字符的头部并记录警告,
防止 httpx 发送时抛出 ``UnicodeEncodeError``。
httpx 要求 header 值可被 latin-1 编码。对于包含非 latin-1 字符
(如中文)的值,先 UTF-8 编码再按 latin-1 解码,使 httpx 将原始
UTF-8 字节逐字节发送到上游 —— 与 Go net/http 的行为一致。
"""
result: dict[str, str] = {}
for original_key, value in self._headers.values():
try:
value.encode("ascii")
value.encode("latin-1")
except (UnicodeEncodeError, UnicodeDecodeError):
logger.warning(
"Dropping non-ASCII header before upstream request: {}",
# 将 UTF-8 字节逐字节映射为 latin-1 字符串httpx 会原样发送
logger.debug(
"Header '{}' contains non-latin-1 chars, encoding as raw UTF-8 bytes",
original_key,
)
continue
value = value.encode("utf-8").decode("latin-1")
result[original_key] = value
return result