Files
writer-work-flow/apps/api/ww_api/schemas/providers.py
Yaojia Wang 3868f80502 fix(qa): 修 3 个 QA MEDIUM——规则/档位路由校验收紧
- 规则 GET 不存在 project → 404(原返误导性空 200,掩盖坏 id):list_rules 加
  项目存在校验(仿 C1/H2)。
- 规则 content 纯空白 → 422(原 strip 前校验 min_length,空白行入库成垃圾):
  改 StringConstraints(strip_whitespace=True, min_length=1)。
- 档位路由 tier 限定 writer/analyst/light(Tier Literal)→ 未知档位 422
  (原接受任意字符串)。

回归测试:test_generation(GET rules 404)/ test_rules(空白 content 422)/
test_settings_providers(未知 tier 422)。门禁绿:ruff/format/mypy(210)/pytest。
2026-06-24 17:51:02 +02:00

79 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""提供商凭据/档位路由的请求/响应 schemaC3 / ARCH §4.7, §7.2)。
snake_case响应一律 **掩码 Key**,绝不含明文。前端经 OpenAPI 生成 TS 类型消费。
"""
from __future__ import annotations
from pydantic import BaseModel, Field
from ww_llm_gateway.types import Tier
class ProviderView(BaseModel):
"""已配置提供商(掩码视图)。"""
provider: str
masked_key: str # 形如 sk-…1234明文永不出现
class TierRoutingView(BaseModel):
"""档位 → provider:model 路由(含回退链)。"""
tier: str
provider: str
model: str
fallback: list[str] = Field(default_factory=list)
class ProvidersResponse(BaseModel):
"""GET/PUT 响应:已配置提供商(掩码)+ 当前档位路由。"""
providers: list[ProviderView] = Field(default_factory=list)
tier_routing: list[TierRoutingView] = Field(default_factory=list)
class ProviderCredentialInput(BaseModel):
"""单条提供商凭据写入。"""
provider: str = Field(min_length=1)
api_key: str = Field(min_length=1) # 明文入站,加密入库,绝不回显
class TierRoutingInput(BaseModel):
"""单条档位路由写入。"""
# tier 限定已知档位 writer/analyst/light未知档位 → 422QA MEDIUM原接受任意字符串
tier: Tier
provider: str = Field(min_length=1)
model: str = Field(min_length=1)
fallback: list[str] = Field(default_factory=list)
class ProvidersUpsertRequest(BaseModel):
"""PUT 请求:可同时 upsert 若干凭据与档位路由(幂等)。"""
credentials: list[ProviderCredentialInput] = Field(default_factory=list)
tier_routing: list[TierRoutingInput] = Field(default_factory=list)
class TestConnectionRequest(BaseModel):
"""POST /test最小探测请求。"""
provider: str = Field(min_length=1)
class CapabilitiesView(BaseModel):
"""探测得到的能力矩阵(镜像网关 `Capabilities`)。"""
structured_output: bool = False
prefix_cache: bool = False
thinking: bool = False
class TestConnectionResponse(BaseModel):
"""POST /test 响应:连通性 + 能力矩阵。"""
provider: str
ok: bool
capabilities: CapabilitiesView