feat(provider,adapter): Codex 默认 body_rules 按 provider_type 维度注册,adapter 全链路传递 provider_type

- 新增 register_provider_default_body_rules 注册机制,将 Codex 特有的
  body_rules 从 EndpointDefinition 全局默认移至 codex plugin 按
  (provider_type, endpoint_sig) 维度注册
- handler adapter 的 build_endpoint_url/build_request_body/get_cli_extra_headers
  增加 provider_type 参数,Codex 判断优先使用 provider_type 而非 URL 匹配
- 前端 getDefaultBodyRules API 支持 provider_type 参数,缓存 key 区分不同
  provider 类型;Codex 路径判断同样优先使用 provider_type
- ProviderDetailDrawer 将 mapping-preview 拆为独立加载,不阻塞首屏渲染
- PoolManagement 补全 KeyFormDialog 缺失的 endpoint/available-api-formats props
- 固定类型 Provider 创建时自动填充 provider-scoped 默认 body_rules
This commit is contained in:
fawney19
2026-03-05 19:04:21 +08:00
parent 694167f78f
commit da915208a8
15 changed files with 214 additions and 54 deletions

View File

@@ -141,10 +141,13 @@ async def create_provider_endpoint(
async def get_default_endpoint_body_rules(
api_format: str,
request: Request,
provider_type: str | None = None,
db: Session = Depends(get_db),
) -> dict[str, Any]:
"""获取指定 endpoint signature 的默认 body_rules。"""
adapter = AdminGetDefaultBodyRulesAdapter(api_format=api_format)
adapter = AdminGetDefaultBodyRulesAdapter(
api_format=api_format, provider_type=provider_type or None
)
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
@@ -308,7 +311,7 @@ class AdminCreateProviderEndpointAdapter(AdminApiAdapter):
raise NotFoundException(f"Provider {self.provider_id} 不存在")
# 固定类型 Provider禁止通过该接口新增 Endpoints端点由模板自动创建并锁定
provider_type = getattr(provider, "provider_type", "custom")
provider_type = getattr(provider, "provider_type", None) or "custom"
if _is_fixed_provider(provider_type):
raise InvalidRequestException("固定类型 Provider 不允许手动新增 Endpoint")
@@ -338,7 +341,12 @@ class AdminCreateProviderEndpointAdapter(AdminApiAdapter):
normalized_api_format = sig.key
body_rules = self.endpoint_data.body_rules
if body_rules is None:
body_rules = get_default_body_rules_for_endpoint(normalized_api_format) or None
body_rules = (
get_default_body_rules_for_endpoint(
normalized_api_format, provider_type=provider_type
)
or None
)
new_endpoint = ProviderEndpoint(
id=str(uuid.uuid4()),
@@ -613,6 +621,7 @@ class AdminDeleteProviderEndpointAdapter(AdminApiAdapter):
@dataclass
class AdminGetDefaultBodyRulesAdapter(AdminApiAdapter):
api_format: str
provider_type: str | None = None
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
try:
@@ -622,5 +631,7 @@ class AdminGetDefaultBodyRulesAdapter(AdminApiAdapter):
return {
"api_format": normalized_api_format,
"body_rules": get_default_body_rules_for_endpoint(normalized_api_format),
"body_rules": get_default_body_rules_for_endpoint(
normalized_api_format, provider_type=self.provider_type
),
}

View File

@@ -489,11 +489,20 @@ class AdminCreateProviderAdapter(AdminApiAdapter):
# 固定类型 Provider自动创建并锁定预置 Endpoints同一事务
template = _get_fixed_provider_template(provider.provider_type)
if template:
from src.core.api_format.metadata import get_default_body_rules_for_endpoint
now = datetime.now(timezone.utc)
for sig in template.endpoint_signatures:
endpoint_config: dict[str, str] | None = None
if provider.provider_type == ProviderType.CODEX.value and sig == "openai:cli":
endpoint_config = {"upstream_stream_policy": "force_stream"}
# 获取 provider-scoped 默认 body rules
default_body_rules = (
get_default_body_rules_for_endpoint(
sig, provider_type=provider.provider_type
)
or None
)
endpoint = ProviderEndpoint(
id=str(uuid.uuid4()),
provider_id=provider.id,
@@ -503,6 +512,7 @@ class AdminCreateProviderAdapter(AdminApiAdapter):
base_url=template.api_base_url,
custom_path=None,
header_rules=None,
body_rules=default_body_rules,
max_retries=provider.max_retries or 2,
is_active=True,
config=endpoint_config,